2018/01/11

[C#] DateGridView 使用 ComboBox 與 DateTimePicker

這一篇主要是針對 https://nonfu.blogspot.tw/2017/12/c-dategridview-datetimepicker.html 所併發出來的想法與程式碼改進 主要就是讓 DataGridView 能使用 DateTimePicker 與 ComboBox 並改進不足之處。

最終完成的成果如下方的圖

程式碼如下:

public partial class DataGridViewEx:System.Windows.Forms.DataGridView
{
 private Point MyPoint;
 private Control parentCTL;
 private ComboBox dtCombo;
 private DateTimePicker dtPicker;

 /// 紀錄可編輯的欄位名稱
 private StringDictionary ColmmEdit;

 /// 紀錄要使用日期資料的欄位名稱
 private StringDictionary ColmmDate;

 /// 紀錄要使用的下拉欄位名稱
 private StringDictionary ColmmCombo;

 public DataGridViewEx() : base()
 {
  this.EditMode = DataGridViewEditMode.EditProgrammatically;
  if (!DesignMode)
  {
   MyPoint = new Point();
   ColmmEdit = new StringDictionary();
   ColmmDate = new StringDictionary();
   ColmmCombo = new StringDictionary();

   this.Disposed += DataGridViewEx_Disposed;
   this.CellClick += DataGridViewEx_CellClick;
   this.CellEnter += DataGridViewEx_CellClick;
   this.EditingControlShowing += DataGridViewEx_EditingControlShowing;

   FirstSetDataTimePicker();
   FirstSetComboBox();

   this.AllowUserToAddRows = true;
   this.AllowUserToDeleteRows = true;
   this.AllowUserToOrderColumns = false;
   this.AllowUserToResizeColumns = false;
   this.AllowUserToResizeRows = false;
  }
 }

 private void DataGridViewEx_Disposed(object sender, EventArgs e)
 {
  if (!DesignMode)
  {
   dtPicker.Dispose();
   dtCombo.Dispose();
  }
 }
       
 /// 設定可編輯的欄位
 public void SetColmmEditName(string NameValue)
 {
  if(!ColmmEdit.ContainsKey(NameValue))
  {
   ColmmEdit.Add(NameValue, NameValue); 
  }
 }

 /// 設定要使用DateTimePicker的欄位
 public void SetColmmDateName(string NameValue)
 {
  if (!ColmmDate.ContainsKey(NameValue))
  {
   ColmmDate.Add(NameValue, NameValue);
  }
 }

 /// 設定要使用ComboBox的欄位
 public void SetColmmComboName(string NameValue)
 {
  if (!ColmmCombo. ContainsKey(NameValue))
  {
   ColmmCombo.Add(NameValue, NameValue);
  }
 }

 /// 檢查欄位是否可以編輯
 private void DataGridViewEx_CellClick(object sender, DataGridViewCellEventArgs e)
 {
  if(this.Rows.Count>0)
  {
   if ((e.RowIndex> -1) && (e.ColumnIndex > -1))
   {
     if (ColmmEdit.ContainsKey(this.Columns[e.ColumnIndex].Name))
     {
      this.BeginEdit(true);
     }
     else
     {
      this.EndEdit();
     }
    }
    else
    {
     this.EndEdit();
    }
   }
  }

 /// 判斷是否使用DateTimePicker、ComboBox
 private void DataGridViewEx_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
 {
  if (this.Rows.Count > 0)
  {
   if (this.CurrentCell.RowIndex > -1 && this.CurrentCell.ColumnIndex > -1)
   {
    if (parentCTL == null)
    {
     parentCTL = e.Control.Parent;
     parentCTL.Controls.Add(dtPicker);
     parentCTL.Controls.Add(dtCombo);
    }
    MyPoint.X = e.Control.Location.X - e.Control.Margin.Left < 0 ? 0 : e.Control.Location.X - e.Control.Margin.Left;
    MyPoint.Y = e.Control.Location.Y - e.Control.Margin.Top < 0 ? 0 : e.Control.Location.Y - e.Control.Margin.Top;
                    
    if (ColmmDate.ContainsKey(this.Columns[this.CurrentCell.ColumnIndex].Name))
    {
     SetDataTimePickerView(ref e);
    }
    else
    {
     MyPoint.X = 0;
     MyPoint.Y = 0;
     dtPicker.Location = MyPoint;
     dtPicker.Visible = false;
    }

    if (ColmmCombo.ContainsKey(this.Columns[this.CurrentCell.ColumnIndex].Name))
    {
     SetComboBoxView(ref e);
    }
    else
    {
     MyPoint.X = 0;
     MyPoint.Y = 0;
     dtCombo.Location = MyPoint;
     dtCombo.Visible = false;
    }
   }
  }
 }

 private void FirstSetComboBox()
 {
  dtCombo = new ComboBox();
  dtCombo.Name = "ComboBox1";
  dtCombo.FlatStyle = FlatStyle.Flat;

  dtCombo.Font = this.AlternatingRowsDefaultCellStyle.Font;
  dtCombo.Visible = false;
  dtCombo.SelectedIndexChanged += new EventHandler(ComboBox1_SelectedIndexChanged);
 }

 private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
 {
  this.CurrentCell.Value = ((ComboBox)sender).SelectedItem;
 }

 /// 設定下拉選單內容
 public void SetComboData(string[] Value)
 {
  dtCombo.Items.Clear();
  dtCombo.Items.AddRange(Value);
 }

 private void SetComboBoxView(ref DataGridViewEditingControlShowingEventArgs e)
 {
  dtCombo.Size = this.CurrentCell.Size;
  dtCombo.Location = MyPoint;
  if (e.Control.Text != "")
  {
   dtCombo.SelectedItem = e.Control.Text;
  }
  else
  {
   dtCombo.SelectedIndex = -1;
  }          
  
  e.Control.Visible = false;
  dtCombo.Visible = true;
 }

 /// DateTimePicker的日期資料回寫欄位
 private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
 {
   this.CurrentCell.Value = ((DateTimePicker)sender).Value.ToString("yyyy/MM/dd");
 }

 private void FirstSetDataTimePicker()
 {
  dtPicker = new DateTimePicker();
  dtPicker.Name = "dateTimePicker1";
  dtPicker.Format = DateTimePickerFormat.Custom;
  dtPicker.CustomFormat = "yyyy/MM/dd";
  dtPicker.MinDate = DateTime.Parse("1920/01/01");
  dtPicker.CalendarFont = this.AlternatingRowsDefaultCellStyle.Font;
  dtPicker.Visible = false;
  dtPicker.ValueChanged += new EventHandler(dateTimePicker1_ValueChanged);
 }

 private void SetDataTimePickerView(ref DataGridViewEditingControlShowingEventArgs e)
 {
  dtPicker.Size = this.CurrentCell.Size;
  dtPicker.Location = MyPoint;
  dtPicker.MaxDate = DateTime.Now;
  if (e.Control.Text != "")
  {
   dtPicker.Value = DateTime.ParseExact(e.Control.Text, dtPicker.CustomFormat, null);
  }
  else
  {
   dtPicker.Value = DateTime.Now;
   this.CurrentCell.Value = dtPicker.Value.ToString("yyyy/MM/dd");
  }
  
   e.Control.Visible = false;
   dtPicker.Visible = true;
 }

}