2009-11-27 5 views

ответ

1

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

выше и следующая методика была взята из Faking alternative controls within a DataGridView control in Win Forms 2.0

Edit: Вот код -

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

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

3

Глядя на эту же вещь, которую я, наконец, нашел в MSDN article that shows how to make a custom CalendarColumn так Я использовал этот пример кода и изменил его, чтобы создать TimeColumn. Он отлично работает - очень чист и основан на образце Microsoft Code. Это не взломать и может быть эффективно и надежно.

Чтобы реализовать, просто добавьте эти классы в свой проект, а затем выберите 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); 
    } 
} 
0

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

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

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

+0

Я думаю, что нашел решение. Я использовал тип данных DateTime в SQL, но изменил его на Time (плюс несколько изменений в классе TimeColumn), и теперь он работает так, как ожидалось. – tippers

Смежные вопросы