4

gridviewの編集機能を少しスマートにしようとしています。

最初のステップとして、行に対して[編集]を押すと、データを含む すべての列DateTimeにテキストボックスではなく日付ピッカーが表示されるようにします。私の試みでは、現在表示されている編集項目ではなく、後ろの行しか編集できないようです。

私の目標は、編集している行の日付列をdatepickersに変更することです。

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);
        }
    }
}

しかし、後ろの行を編集しているようです。現在編集しているものを編集するにはどうすればよいですか?

4

4 に答える 4

2

アプローチが異なり、シナリオに対して少し単純すぎる可能性がある場合でも<asp:TemplateField />、編集項目テンプレートをカスタマイズするために を使用することをお勧めします (以下を参照)。もちろん、<asp:Calendar />私が使用したコントロールをカスタムDatePickerControl.DatePickerコントロールに置き換えることもできます。

<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>

[アップデート]

列を動的に作成することもできます。以下のコードを確認してください。

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();
    }

}
于 2013-01-09T13:25:51.247 に答える
2

これは間違ったアプローチだと思います。実行時にコントロールの型を気にするべきではありません。データグリッドが構築されたとき、データグリッド列は日付ピッカー型である必要があります。

残念ながら、MS はそれを提供していません。幸いなことに、MS はそれを可能にするフレームワークを提供しています。

新しい 1) DataGridViewColumn、新しい 2) DataGridViewTextBoxCell、そして最後に実際の 3) DateTimePicker 編集コントロールの 3 つが必要です。

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; }
        }

次に、フォームの Load イベントで:

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);

はどこeventDateDataGridViewCalendarColumnですかprivate DataGridViewCalendarColumn。これで、編集イベントがなくなりました。

これで問題なく動作しますが、ネット上にあるランダムなサンプルと同様に、自己責任で使用してください。

于 2013-01-09T13:19:32.193 に答える
0

行が実際に編集モードになる前にイベントが発生するため、問題はe.NewEditIndex正しい値ではないようです。これは、 の値が、最後に編集した行のインデックスになることを意味します。推測する必要がある場合は、行を順番に繰り返し処理していたので、常に「後ろの行」を変更していたのはまったくの偶然でした。RowEditinge.NewEditIndex

GridView.SelectedIndexドキュメントから、プロパティにアクセスすることで、現在選択されている行のインデックスを取得できるようです。編集する前に行を選択する場合:

次のように変更できます。var row = ((GridView)sender).Rows[e.NewEditIndex].Cells;

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

SetEditRow次のメソッドを使用して、行を手動で編集モードにすることもできます

いずれにせよ、イベントを呼び出す前に現在の行のインデックスを知る必要があります。RowEditingまたは、メソッドを使用して行を強制的に編集モードにする必要があります。SetEditRowこれにより、正しいインデックスがRowEditingイベントに伝達されます。

幸運を。

于 2013-01-07T21:22:23.630 に答える
0
 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);
        }
    }

}

これを試して

于 2013-01-09T12:28:17.167 に答える