2017/12/17

[C#] DateGridView 使用 DateTimePicker 輸入日期

使用DateGridView常常遇到需要輸入日期的情境,對使用者來說DateTimePicker是很直覺的輸入方式
但是原始的DateGridView並不支援DateTimePicker的使用,以往為了解決這個問題,我都是參考微軟
的這一篇 https://msdn.microsoft.com/zh-tw/library/7tas5c80.aspx 進行修改
最近看到這一篇 https://dotblogs.com.tw/danking/2014/11/13/147294 讓我興起改寫
DateGridView的想法。

對於改寫控制項還不是很了解要如何使用在專案的人,可以參考我的另一篇文https://nonfu.blogspot.tw/2017/11/c-checkbox.html

public partial class DataGridViewEx:System.Windows.Forms.DataGridView
{
  // 紀錄可編輯的欄位名稱
  private StringDictionary ColmmEdit;

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

  public DataGridViewEx() : base()
  {
    this.EditMode = DataGridViewEditMode.EditProgrammatically;
    if (!DesignMode)
    {
      ColmmEdit = new StringDictionary();
      ColmmDate = new StringDictionary();
      this.Disposed += DataGridViewEx_Disposed;
      this.CellClick += DataGridViewEx_CellClick;
      this.EditingControlShowing += DataGridViewEx_EditingControlShowing;          
     }
  }

  // 刪除資料清單
  private void DataGridViewEx_Disposed(object sender, EventArgs e)
  {
    if (!DesignMode)
    {
      ColmmEdit.Clear();
      ColmmDate.Clear();
    }
  }
       
  // 設定可編輯的欄位
  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);
    }
  }

  // 檢查欄位是否可以編輯
  private void DataGridViewEx_CellClick(object sender, DataGridViewCellEventArgs e)
  {
    if ((e.RowIndex > -1) || (e.ColumnIndex > -1))
    {

      if (ColmmEdit.ContainsKey(this.Columns[e.ColumnIndex].Name))
      {
        this.BeginEdit(true);
      }
      else
      {
        this.EndEdit();
      }

    }
  }

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

  // 判斷是否適用DateTimePicker的欄位
  private void DataGridViewEx_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
  {
    if (this.CurrentCell.ColumnIndex > -1)
    {
      Control parentCTL = e.Control.Parent;

      if(ColmmDate.ContainsKey(this.Columns[this.CurrentCell.ColumnIndex].Name))
      {
        DateTimePicker dtPicker = new DateTimePicker();
        dtPicker.Name = "dateTimePicker1";
        dtPicker.Size = this .CurrentCell.Size;
        dtPicker.Format = DateTimePickerFormat.Custom;
        dtPicker.CustomFormat = "yyyy/MM/dd";

        dtPicker.Location = new Point(
                                      e.Control.Location.X - e.Control.Margin.Left < 0 ? 0 : e.Control.Location.X - e.Control.Margin.Left,
                                      e.Control.Location.Y - e.Control.Margin.Top < 0 ? 0 : e.Control.Location.Y - e.Control.Margin.Top);

        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;

        foreach (Control tmpCTL in parentCTL.Controls)
        {
          if (tmpCTL.Name == dtPicker.Name) parentCTL.Controls.Remove(tmpCTL);
        }

        parentCTL.Controls.Add(dtPicker);
        dtPicker.ValueChanged += new EventHandler(dateTimePicker1_ValueChanged);              
      }
      else
      {
        foreach (Control tmpCTL in parentCTL.Controls)
        {
          if (tmpCTL.Name == "dateTimePicker1")
          {
           parentCTL.Controls.Remove(tmpCTL);
          }
        }
      }
    }
  }
}

沒有留言:

張貼留言