C # Winforms DataGridView Time Column - PullRequest
       14

C # Winforms DataGridView Time Column

3 голосов
/ 27 ноября 2009

Как показать столбец Time-picker в DataGridView?

Мне не нужно выбирать дату. Мне нужно только время, чтобы быть выбранным.

Ответы [ 4 ]

3 голосов
/ 08 декабря 2011

В поисках того же самого я наконец нашел статью MSDN, в которой показано, как создать настраиваемый CalendarColumn , поэтому я использовал этот пример кода и изменил его для создания TimeColumn. Он отлично работает - очень чистый и основанный на примере кода Microsoft. Не взломать и может быть эффективно и надежно привязано к данным.

Для реализации просто добавьте эти классы в свой проект, а затем выберите TimeColumn в поле ColumnType объекта DataGridView.

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);
    }
}
1 голос
/ 29 ноября 2009

На самом деле, есть лучший способ, чем создание настраиваемого столбца DataGridView. Что я сейчас делаю для своего приложения, так это когда при вводе столбца TIMESTAMP в моем DataGridView я размещаю элемент управления DateTimePicker непосредственно над ячейкой. Когда пользователь щелкнул мышью из ячейки (что подтверждает его выбор), для параметра DateTimePicker Visible устанавливается значение False, а значение DateTimePicker помещается в ячейку. По умолчанию элемент управления DateTimePicker Visibility установлен в False, пока он мне не понадобится. Я также использую это для элементов управления ComboBox на обычных ячейках, где пользователь не может ввести пользовательское значение и должен использовать список элементов на экране настройки. Эта техника отлично подходит для подделки. У меня нет готового кода, но он меньше кода и проще в обслуживании. ИМХО.

Приведенный выше и следующий метод был взят из Подделка альтернативных элементов управления в элементе управления DataGridView в 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;
}
0 голосов
/ 02 августа 2013

Извините, что отвечаю на старую ветку, но это единственное место, где я могу найти, где кто-то адаптировал код MS так же, как и я. В ответ на RThomas я сделал это, но я нахожу проблемы с использованием TimeColumn при привязке к данным. Я использую его для ввода расписания сотрудников, поэтому элемент даты не виден, только время. Когда я ввожу данные, все работает нормально, но когда я пытаюсь редактировать данные, что-то идет не так.

Значение ячейки является правильным в событии OnValueChanged (с помощью Debug я вижу значение Me.Value), но в событиях DataGridView.CellEndEditing или CellValidated значение показывает текущую дату и отредактированное значение времени. Как ни странно, если пользователь перемещается в другую ячейку, затем обратно в TimeCell, затем в другую ячейку снова значение корректно, но после первоначального редактирования дата неверна.

Я рассмотрел все различные события, но, похоже, что-то среднее между значением, которое редактируется в DataGridView и фиксируется в Datatable, привязанном к DataGridView.

0 голосов
/ 27 ноября 2009

AFAIK, есть прямой способ сделать это. Я думаю, что единственный способ - создать столбец Custom DataGridview. Проверьте эту ссылку для создания настраиваемого столбца таблицы данных

...