在网格视图中操纵弯曲的编辑行



我正在尝试使GridView的编辑功能更聪明。

作为第一步,我想要当我按行编辑时所有带有DateTime数据的列将具有datepicker而不是文本框似乎我的尝试只能编辑后面的行,而不是当前显示的编辑项目。

我的目标是更改我要编辑的日期列的日期列。

protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
    var row = ((GridView)sender).Rows[e.NewEditIndex].Cells;
    for (int i = 0; i < row.Count; i++)
    {
        DateTime dtDate;
        var res = DateTime.TryParse(row[i].Text, out dtDate);
        if (res)
        {
            DatePickerControl.DatePicker text = new DatePickerControl.DatePicker();
            text.CalendarDate = dtDate;
            row[i].Controls.Clear();
            row[i].Controls.Add(text);
        }
    }
}

,但看来它编辑了后面的行,我该如何编辑我的编辑内容?

即使该方法不同,并且可能对您的方案有些简单,我建议您使用<asp:TemplateField />来自定义编辑项目模板(请参见下文)。当然,您可能还需要替换我与您的自定义DatePickerControl.DatePicker控件一起使用的<asp:Calendar />控件。

<asp:GridView ID="GridView1" runat="server" OnRowEditing="GridView1_RowEditing">
    <Columns>
        <asp:TemplateField>
            <EditItemTemplate>
                <asp:Calendar runat="server" SelectedDate='<%# Eval("Date") %>'></asp:Calendar>
            </EditItemTemplate>
            <ItemTemplate>
                <%# Eval("Date") %>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

[update]

您也有可能动态创建列。请检查下面的代码:

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        GridView1.AutoGenerateColumns = false;
        GridView1.AutoGenerateEditButton = true;
        DataTable dataSource = new DataTable();
        dataSource.Columns.Add("Id", typeof(int));
        dataSource.Columns.Add("Date1", typeof(DateTime));
        dataSource.Columns.Add("Date2", typeof(DateTime));
        dataSource.Rows.Add(1, DateTime.Now, DateTime.Now.AddMonths(1));
        dataSource.Rows.Add(2, DateTime.Now.AddMonths(2), DateTime.Now.AddMonths(3));
        GridView1.Columns.Clear();
        foreach (DataColumn column in dataSource.Columns)
        {
            if (column.DataType == typeof(DateTime))
            {
                var templateColumn = new TemplateField();
                templateColumn.EditItemTemplate = new AddTemplateToGridView(ListItemType.EditItem, column.ColumnName);
                templateColumn.ItemTemplate = new AddTemplateToGridView(ListItemType.Item, column.ColumnName);
                templateColumn.HeaderText = column.ColumnName;
                GridView1.Columns.Add(templateColumn);
            }
            else
            {
                var dataBoundColumn = new BoundField();
                dataBoundColumn.DataField = column.ColumnName;
                dataBoundColumn.HeaderText = column.ColumnName;
                GridView1.Columns.Add(dataBoundColumn);
            }
        }
        GridView1.DataSource = dataSource;
        GridView1.DataBind();
    }
    public class AddTemplateToGridView : ITemplate
    {
        ListItemType _type;
        string _colName;
        public AddTemplateToGridView(ListItemType type, string colname)
        {
            _type = type;
            _colName = colname;
        }
        public void InstantiateIn(Control container)
        {
            switch (_type)
            {
                case ListItemType.Item:
                    Label l = new Label();
                    l.DataBinding += l_DataBinding;
                    container.Controls.Add(l);
                    break;
                case ListItemType.EditItem:
                    Calendar calendar = new Calendar();
                    calendar.DataBinding += l_DataBinding;
                    container.Controls.Add(calendar);
                    break;
            }
        }
        void l_DataBinding(object sender, EventArgs e)
        {
            GridViewRow container;
            object dataValue;
            switch (sender.GetType().ToString())
            {
                case "System.Web.UI.WebControls.Label":
                    Label label = (Label)sender;
                    container = (GridViewRow)label.NamingContainer;
                    dataValue = DataBinder.Eval(container.DataItem, _colName);
                    if (dataValue != DBNull.Value)
                    {
                        label.Text = dataValue.ToString();
                    }
                    break;
                //use the DatePickerControl.DatePicker type instead of calendar
                case "System.Web.UI.WebControls.Calendar":
                    Calendar calendar = (Calendar)sender;
                    container = (GridViewRow)calendar.NamingContainer;
                    dataValue = DataBinder.Eval(container.DataItem, _colName);
                    if (dataValue != DBNull.Value)
                    {
                        calendar.SelectedDate = (DateTime)dataValue;
                        calendar.VisibleDate = (DateTime)dataValue;
                    }
                    break;
            }
        }
    }
    protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
    {
        GridView1.EditIndex = e.NewEditIndex;
        GridView1.DataBind();
    }
}

我会说这是错误的方法,您不应该在运行时使用控制类型,而datagrid列则是构建数据杂志时的datepicker类型。<<<<<<<<<<

不幸的是,MS不提供一个,幸运的是,它们确实提供了允许您这样做的框架:

您需要3件事,一个新的1)DataGridViewColumn,新的2)DataGridViewTextBoxCell,最后3)实际3)DateTimePicker编辑控件。

1:

public class DataGridViewCalendarColumn : DataGridViewColumn
{
    public DataGridViewCalendarColumn()
        : base(new DataGridViewCalendarCell())
    { }
    public override DataGridViewCell CellTemplate
    {
        get { return base.CellTemplate; }
        set
        {
            // Ensure that the cell used for the template is a CalendarCell.
            if (value != null &&
                !value.GetType().IsAssignableFrom(typeof(DataGridViewCalendarCell)))
                throw new InvalidCastException("Must be a DataGridViewCalendarCell");
            base.CellTemplate = value;
        }
    }
}

2:

public class DataGridViewCalendarCell : DataGridViewTextBoxCell
{
    public DataGridViewCalendarCell()
        : base()
    {
        this.Style.Format = "d";    //short date style
    }
    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        //set the value of the editing control to the current cell value
        base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
        DataGridViewCalendarControl ctl = DataGridView.EditingControl as DataGridViewCalendarControl;
        //use default value if Value is null
        if (this.Value == null || this.Value == DBNull.Value)
            ctl.Value = (DateTime) this.DefaultNewRowValue;
        else
            ctl.Value = (DateTime) this.Value;
    }
    public override Type EditType
    {
        get
        {
            //return the type of control this cell uses
            return typeof(DataGridViewCalendarControl);
        }
    }
    public override Type ValueType
    {
        get
        {
            //return the type of the value that this cell contains
            return typeof(DateTime);
        }
    }
    public override object DefaultNewRowValue
    {
        get
        {
            //use today's date as the default value
            return DateTime.Now;
        }
    }
}

3:

public class DataGridViewCalendarControl : DateTimePicker, IDataGridViewEditingControl
    {
        private DataGridView dataGridView;
        private bool hasValueChanged = false;
        int rowIndex;
        public DataGridViewCalendarControl()
        {
            this.Format = DateTimePickerFormat.Short;
        }
        protected override void OnValueChanged(EventArgs eventargs)
        {
            //Notify the DataGridView that the value has changed
            hasValueChanged = true;
            this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
            base.OnValueChanged(eventargs);
        }
        #region IDataGridViewEditingControl Members
        public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
        {
            this.Font = dataGridViewCellStyle.Font;
            this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
            this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
        }
        public DataGridView EditingControlDataGridView
        {
            get { return dataGridView; }
            set { dataGridView = value; }
        }
        public object EditingControlFormattedValue
        {
            get { return this.Value.ToShortDateString(); }
            set
            {
                if (value is String)
                    try
                    {
                        this.Value = DateTime.Parse((String) value);
                    }
                    catch
                    {
                        this.Value = DateTime.Now;
                    }
            }
        }
        public int EditingControlRowIndex
        {
            get { return rowIndex; }
            set { rowIndex = value; }
        }
        public bool EditingControlValueChanged
        {
            get { return hasValueChanged; }
            set { hasValueChanged = value; }
        }
        public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
        {
            //the DateTimePicker needs to handle the keys
            switch (keyData & Keys.KeyCode)
            {
                case Keys.Left:
                case Keys.Right:
                case Keys.Up:
                case Keys.Down:
                case Keys.Home:
                case Keys.End:
                case Keys.PageUp:
                case Keys.PageDown:
                    return true;
                default:
                    return !dataGridViewWantsInputKey;
            }
        }
        public Cursor EditingPanelCursor
        {
            get { return base.Cursor; }
        }
        public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
        {
            return EditingControlFormattedValue;
        }
        public void PrepareEditingControlForEdit(bool selectAll)
        {
            //nowt needs doing...
        }
        public bool RepositionEditingControlOnValueChange
        {
            get { return false; }
        }

然后在表格的加载事件中:

eventDateDataGridViewCalendarColumn = new DataGridViewCalendarColumn();
eventDateDataGridViewCalendarColumn.DataPropertyName = "EventDate";
eventDateDataGridViewCalendarColumn.HeaderText = "Date";
//we've created the column, now insert it into the right location (after the ID and UserID)
this.tSEventsDataGridView.Columns.Insert(2, eventDateDataGridViewCalendarColumn);
//remove the original TextBox EventDate column added via VS
this.tSEventsDataGridView.Columns.RemoveAt(3);

其中eventDateDataGridViewCalendarColumnprivate DataGridViewCalendarColumn。就是这样,我们在任何编辑事件中都有现在。

现在这对我们有用,但是与往常一样,在'网络上找到的随机样本,请自行使用!

看起来您的问题是e.NewEditIndex不是正确的值,因为RowEditing事件在 之前 实际上已将其放入编辑模式。这意味着e.NewEditIndex的值将是您上次编辑的任何行的索引。如果我不得不猜测,我会说您依次在行中迭代,所以您总是在修改"后面的行"是纯粹的巧合。

从文档中,您可以通过访问GridView.SelectedIndex属性来获取当前选择的行的索引。如果要在编辑之前选择该行:

您可以更改:var row = ((GridView)sender).Rows[e.NewEditIndex].Cells;

to: var row = ((GridView)sender).Rows[(GridView)sender.SelectedIndex].Cells;

您还可以使用SetEditRow方法手动探索将行放入编辑模式:http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.seteditrow.asteditrow.aspxpex/P>

无论哪种方式,您都需要在调用RowEditing事件之前知道您当前使用的行的索引,或使用SetEditRow方法将行强迫进入编辑模式,该方法将将正确的索引传播到RowEditing事件中。

祝你好运。

 protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
    bindgrid();
    var row = ((GridView)sender).Rows[e.NewEditIndex].Cells;
    for (int i = 0; i < row.Count; i++)
    {
        DateTime dtDate;
        var res = DateTime.TryParse(row[i].Text, out dtDate);
        if (res)
        {
            Calendar cal = new Calendar();
            cal.SelectedDate = dtDate;
            cal.VisibleDate = dtDate;
            cal.DataBind();
            //DatePickerControl.DatePicker text = new DatePickerControl.DatePicker();
            //text.CalendarDate = dtDate;
            row[i].Controls.Clear();
            row[i].Controls.Add(cal);
        }
    }
}

尝试此

最新更新