2016-12-12 3 views
-2

私はWindowsフォームアプリケーションでdataGridviewを持っており、手動で生成された列のすべてのセルに日付ピッカーを生成しようとしています。以下のコードを以下に示します。DataGridViewで手動で生成された列のすべてのセルにDateTimePickerを表示するにはどうすればよいですか?

private void Form1_Load(object sender, EventArgs e) 
    { 
     using (SqlConnection sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["conString"].ConnectionString)) 
     { 
      string query1 = "SELECT [Full] FROM database table"; 

      sqlCon.Open(); 

      using (SqlCommand command1 = new SqlCommand(query1, sqlCon)) 
      { 
       DataTable dt = new DataTable(); 
       SqlDataAdapter da = new SqlDataAdapter(command1); 
       da.Fill(dt); 
       dataGridView2.AutoGenerateColumns = false; 
       dataGridView2.ColumnCount = 3; 
       dataGridView2.Columns[0].HeaderText = "Test"; 
       dataGridView2.Columns[0].DataPropertyName = "Full"; 
       dataGridView2.Columns[1].HeaderText = "Date"; 

       //timedate picker here 
       //dataGridView2.Columns[1]. 
       dataGridView2.Columns[2].HeaderText = "Result"; 
       dataGridView2.DataSource = dt; 
       da.Dispose(); 
      } 
      sqlCon.Close(); 
     }  
    } 
+1

[DataGridViewにDateTimePickerを表示するにはどうすればいいですか?](http://stackoverflow.com/questions/4815677/how-can-i-display-a-datetimepicker-in-a-datagridview) –

+0

いいえ#Wim。私はそれを手動で生成しようとしています。私のコードを見てください。 –

+0

あなたのコードがあなたの質問にどのように関係しているのか分かりません。もっと説明できますか? – Takarii

答えて

0

これは、箱から出して動作しませんが、それはあなたが選んだの任意のコントロールをホストするSystem.Windows.Forms.DataGridViewColumnをサブクラス化するすべてのことは難しいことではありません。その上、System.Windows.Forms名前空間には既にDateTimePickerクラスが含まれていますが、この時点ではDataGridViewの内部での使用には適していません。これら2つを一緒に接着しましょう。

我々はDataGridViewCalendarColumnクラスを作成することから始めましょう:

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

だから、このクラスが何をするのでしょうか?基本的にokと書かれています。DataGridViewColumnは、そのセルにCellTemplateが必要です。これは、DataGridViewに追加する列が特定の標準に準拠していることを確認する制約です。

本質的には、DataGridViewのように、新しい種類のセルを含む新しい種類の列を受け入れようとしています。しかし、この時点で、DataGridViewCalendarCellはまだ存在していないので、我々はそれにも作成することで、継続されます:私たちはDataGridViewが認識しない細胞の一種で開始する必要があるため私たちは、DataGridViewTextBoxCellをsubsclassingことから始めましょう

を。この場合DataGridViewTextBoxCell

public class DataGridViewCalendarCell : DataGridViewTextBoxCell 
{ 
    public DataGridViewCalendarCell() 
    : base() 
    { 
     // Use the short date format. 
     this.Style.Format = "d"; 
    } 

    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); 
     DataGridViewCalendarEditingControl ctl = 
      DataGridView.EditingControl as DataGridViewCalendarEditingControl; 
     // Use the default row value when Value property is null. 
     if (this.Value != null || !String.IsNullOrEmpty(initialFormattedValue.ToString())) 
     { 
      DateTime parsedDate; 
      bool IsDate = DateTime.TryParseExact(this.Value.ToString(), "d/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate); 
      if (IsDate) 
      { 
       ctl.Value = parsedDate; 
      } 
     } 
    } 

    public override Type EditType 
    { 
     get 
     { 
      // Return the type of the editing control that DataGridViewCalendarCell uses. 
      return typeof(DataGridViewCalendarEditingControl); 
     } 
    } 

    public override Type ValueType 
    { 
     get 
     { 
      // Return the type of the value that DataGridViewCalendarCell contains. 

      return typeof(DateTime); 
     } 
    } 

    public override object DefaultNewRowValue 
    { 
     get 
     { 
      // Use the current date and time as the default value. 
      return null; 
     } 
    } 
} 

それでは、これは基本的に行うことは、私たちDataGridViewに言っている:私は知っている、あなたはそれは我々ができる表示と編集の両方のテキストグリッドを作成する方法ですので、あなたは、すでにDataGridViewTextBoxCellを受け入れることに慣れていることを知って、見て。だから私はのテキストセルをあなたに投げつけるつもりです。

さらに、入力値を解析可能なテキストに制限します(DateTime)。

これは参照フレームを作成するので、実際のカレンダーコントロールをセルをクリックして作成しようとすると、グリッドが驚くことはありません。今実際の魔法が現れます:実際のカレンダーコントロール!

通常のDateTimePickerコントロールをサブクラス化し、DataGridView内のコンテンツを編集するコントロールを特定のルールセットにバインドするコントラクトであるIDataGridViewEditingControlインターフェイスを実装します。

public class DataGridViewCalendarEditingControl : DateTimePicker, IDataGridViewEditingControl 
{ 
    DataGridView dataGridView; 
    private bool valueChanged = false; 
    int rowIndex; 

    public DataGridViewCalendarEditingControl() 
    { 
     this.Format = DateTimePickerFormat.Short; 
    } 

    // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
    // property. 
    public object EditingControlFormattedValue 
    { 
     get 
     { 
      return this.Value.ToShortDateString(); 
     } 
     set 
     { 
      if (value is String) 
      { 
       try 
       { 
        // This will throw an exception if the string is 
        // null, empty, or not in the format of a date. 
        DateTime parsedDate; 
        bool IsDate = DateTime.TryParseExact((String)value, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out parsedDate); 
        this.Value = (IsDate) ? parsedDate : DateTime.Now; 
       } 
       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); 
    } 
} 

これはコードの肉です。私はそれがたくさんあるように見えますが、一度これを掛ければ、今まで必要だったすべての種類の列、セル、コントロールを作成することができます。

データベースから引き出したデータ(つまり、db側のDATETIME)は、文字列形式のままにすることができます。今作成したコントロールは、これらの文字列を日付に解析します。したがって、DataTableを記入し、列をプログラムで追加してバインドします。DBからあなたDataTableを埋めるためのロジックがここに

var colText = new DataGridViewTextBoxColumn(); 
colText.DataPropertyName = "dbTextColName"; 
colText.HeaderText = "MyTextColumn"; 
colText.Name = "dbTextColName"; 

var colDateTime = new DataGridViewCalendarColumn(); 
colDateTime.DataPropertyName = "dbDateTimeColName"; 
colDateTime.HeaderText = "MyDateTimeColumn"; 
colDateTime.Name = "dbDateTimeColName"; 

yourDataGridView.Columns.AddRange(new DataGridViewColumn[] {colText, colDateTime}); 

yourDataGridView.DataSource = dt; 
0

グリッドのonclickのイベントをキャプチャし、その場合に行く//

DataTable dt = new DataTable(); 
dt.Columns.Add(new DataColumn("dbTextColName", typeof(string))); 
dt.Columns.Add(new DataColumn("dbDateTimeColName", typeof(string))); // yes string, our code above will take care of the parsing 

:あなたは日付が含まれているそのうちの一つ、あなたのDataTable 2の列を埋めると仮定すると、作成した列をカレンダーコンポーネントでtrueに、または列のxy座標でグリッドの上にDateTimePickerコンポーネントを表示するように設定します。どちらの日付を選択するにしても、その日付の文字列値をクリックしたセルに置き、カレンダーコンポーネントを非表示にします。

関連する問題