代码之家  ›  专栏  ›  技术社区  ›  user366312

C WinForms DataGridView时间列

  •  3
  • user366312  · 技术社区  · 15 年前

    如何在DataGridView中显示时间选择器列?

    我不需要选择日期。我只需要时间来选择。

    4 回复  |  直到 12 年前
        1
  •  1
  •   Zacharious    12 年前

    实际上,有比创建自定义DataGridView列更好的方法。我目前为应用程序所做的是,当输入DataGridView的Timestamp列时,我将一个DateTimePicker控件直接放置在单元格上。当用户点击出单元格(从而确认他的选择)时,DateTimePicker Visible设置为false,并且将DateTimePicker的值放入单元格。默认情况下,DateTimePicker控件可见性设置为false,直到我需要它为止。我还将其用于常规单元格上的组合框控件,用户无法在其中输入自定义值,必须使用设置屏幕上的项目列表。这种技术很适合伪装。我没有现成的代码,但是代码更少,维护IMHO也更容易。

    上面和下面的技术是从 Faking alternative controls within a DataGridView control in Win Forms 2.0

    编辑:这是代码-

    private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
    {
                if (selectAllToolStripMenuItem.Checked)
                    selectAllToolStripMenuItem.Checked = false;
    
                if (dtPicker.Visible)
                    dtPicker.Visible = false;
    
                if (e.ColumnIndex >= 0)
                {
                    if (dataGridView1.Columns[e.ColumnIndex].Name == "Delete")
                    {
                        if (adminIsLoggedIn)
                        {
                            removeRow(e);
                        }
                        else
                        {
                            MessageBox.Show("You must be logged in as an Administrator in order to change the facility configuration.", "Delete Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                    else if (dataGridView1.Columns[e.ColumnIndex].Name == "TIMESTAMP")
                    {
                        if (adminIsLoggedIn)
                        {
                            setNewCellDate(e);
                        }
                    }
                    .....
                }
                // ---
    

    }

    private void setNewCellDate(DataGridViewCellEventArgs e)
    {
                dtPicker.Size = dataGridView1.CurrentCell.Size;
                dtPicker.Top = dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true).Top + dataGridView1.Top;
                dtPicker.Left = dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true).Left + dataGridView1.Left;
                if (!(object.Equals(Convert.ToString(dataGridView1.CurrentCell.Value), "")))
                    dtPicker.Value = Convert.ToDateTime(dataGridView1.CurrentCell.Value);
                dtPicker.Visible = true;
    }
    
        2
  •  3
  •   RThomas    13 年前

    找同样的东西,我终于找到了 MSDN article that shows how to make a custom CalendarColumn 所以我使用代码示例并修改它来创建时间列。它工作得很好-非常干净,基于Microsoft代码示例。不是黑客,可以高效可靠地绑定数据。

    要实现,只需将这些类添加到项目中,然后在DataGridView的ColumnType字段中选择TimeColumn。

    public class TimeColumn : DataGridViewColumn
    {
        public TimeColumn()
            : base(new TimeCell())
        {
        }
    
        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(TimeCell)))
                {
                    throw new InvalidCastException("Must be a TimeCell");
                }
                base.CellTemplate = value;
            }
        }
    }
    
    public class TimeCell : DataGridViewTextBoxCell
    {
    
        public TimeCell()
            : base()
        {
            // Use the short date format.
            this.Style.Format = "t";
        }
    
        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);
            TimeEditingControl ctl =
                DataGridView.EditingControl as TimeEditingControl;
            // Use the default row value when Value property is null.
            if (this.Value == null)
            {
                ctl.Value = (DateTime)this.DefaultNewRowValue;
            }
            else
            {
                ctl.Value = (DateTime)this.Value;
            }
        }
    
        public override Type EditType
        {
            get
            {
                // Return the type of the editing control that CalendarCell uses.
                return typeof(TimeEditingControl);
            }
        }
    
        public override Type ValueType
        {
            get
            {
                // Return the type of the value that CalendarCell contains.
    
                return typeof(DateTime);
            }
        }
    
        public override object DefaultNewRowValue
        {
            get
            {
                // Use the current date and time as the default value.
                return DateTime.Now;
            }
        }
    }
    
    class TimeEditingControl : DateTimePicker, IDataGridViewEditingControl
    {
        DataGridView dataGridView;
        private bool valueChanged = false;
        int rowIndex;
    
        public TimeEditingControl()
        {
            this.Format = DateTimePickerFormat.Time;
            this.ShowUpDown = true;  // replace the timepicker calendar drop down with a up down scroller
        }
    
        // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
        // property.
        public object EditingControlFormattedValue
        {
            get
            {
                return this.Value.ToShortTimeString();
            }
            set
            {
                if (value is String)
                {
                    try
                    {
                        // This will throw an exception of the string is 
                        // null, empty, or not in the format of a date.
                        this.Value = DateTime.Parse((String)value);
                    }
                    catch
                    {
                        // In the case of an exception, just use the 
                        // default value so we're not left with a null
                        // value.
                        this.Value = DateTime.Now;
                    }
                }
            }
        }
    
        // Implements the 
        // IDataGridViewEditingControl.GetEditingControlFormattedValue method.
        public object GetEditingControlFormattedValue(
            DataGridViewDataErrorContexts context)
        {
            return EditingControlFormattedValue;
        }
    
        // Implements the 
        // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
        public void ApplyCellStyleToEditingControl(
            DataGridViewCellStyle dataGridViewCellStyle)
        {
            this.Font = dataGridViewCellStyle.Font;
            this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
            this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
        }
    
        // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
        // property.
        public int EditingControlRowIndex
        {
            get
            {
                return rowIndex;
            }
            set
            {
                rowIndex = value;
            }
        }
    
        // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
        // method.
        public bool EditingControlWantsInputKey(
            Keys key, bool dataGridViewWantsInputKey)
        {
            // Let the DateTimePicker handle the keys listed.
            switch (key & Keys.KeyCode)
            {
                case Keys.Left:
                case Keys.Up:
                case Keys.Down:
                case Keys.Right:
                case Keys.Home:
                case Keys.End:
                case Keys.PageDown:
                case Keys.PageUp:
                    return true;
                default:
                    return !dataGridViewWantsInputKey;
            }
        }
    
        // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
        // method.
        public void PrepareEditingControlForEdit(bool selectAll)
        {
            // No preparation needs to be done.
        }
    
        // Implements the IDataGridViewEditingControl
        // .RepositionEditingControlOnValueChange property.
        public bool RepositionEditingControlOnValueChange
        {
            get
            {
                return false;
            }
        }
    
        // Implements the IDataGridViewEditingControl
        // .EditingControlDataGridView property.
        public DataGridView EditingControlDataGridView
        {
            get
            {
                return dataGridView;
            }
            set
            {
                dataGridView = value;
            }
        }
    
        // Implements the IDataGridViewEditingControl
        // .EditingControlValueChanged property.
        public bool EditingControlValueChanged
        {
            get
            {
                return valueChanged;
            }
            set
            {
                valueChanged = value;
            }
        }
    
        // Implements the IDataGridViewEditingControl
        // .EditingPanelCursor property.
        public Cursor EditingPanelCursor
        {
            get
            {
                return base.Cursor;
            }
        }
    
        protected override void OnValueChanged(EventArgs eventargs)
        {
            // Notify the DataGridView that the contents of the cell
            // have changed.
            valueChanged = true;
            this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
            base.OnValueChanged(eventargs);
        }
    }
    
        3
  •  0
  •   Anuraj    15 年前

    阿法克,这是一种直接的方法。我认为唯一的方法是创建一个自定义的DataGridView列。检查此链接 creating a custom datagridview column

        4
  •  0
  •   tippers    12 年前

    很抱歉回复了一个旧的线程,但这是我唯一能找到的地方,有人像我一样修改了MS代码。作为对rthomas的回应,我已经这样做了,但是当绑定到数据表时,我发现使用timecolumn有问题。我将其用于员工时间表条目,因此日期元素不可见,只显示时间。当我输入数据时,它可以正常工作,但当我尝试编辑数据时,有问题。

    单元值在OnValueChanged事件中是正确的(使用debug可以看到me.value的值),但在DataGridView.CellEndediting或CellValidated事件中,该值显示当前日期和编辑的时间值。奇怪的是,如果用户移动到另一个单元格,然后返回到时间单元格,然后再次移动到另一个单元格,那么值是正确的,但是在初始编辑之后,日期是错误的。

    我看过所有不同的事件,但它似乎介于在DataGridView中编辑的值和提交到绑定到DataGridView的DataTable之间。