開源DataGridView擴展(6) 簡單實現checkbox行選級聯。

r0

r1

                                                        < 他們有差別嗎?>

 

一、需求

       爲甚有這種想法呢,那是來自需求的壓迫,可憐我們這些苦逼的程序猿及攻城獅們只能徹夜難眠、苦思冥想、幾十億個腦細胞兄弟們前赴後繼最終才能取得芝麻點大的勝利,好吧我們來看需求。

1. 現在要一個表格,表格的第一列是一個選中操作的複選框,要求能再複選框選中時,也對此行進行行選。

二、分析設計

      First,讓我們來看下,GridView中本身帶了哪些我們能用的方法:

      a. 自身帶有checkbox列,我們也自定義了我們的擴展checkbox列。

      b. 表格本身具有行選屬性。

      c. 表格本身帶有多行選擇屬性。

      好吧到然後了,通過利用這些已有的屬性我們簡單實現之,在checkbox的選中事件中進行行選操作。然後就實現啦。。。

     

      Wait,這樣真的就這麼簡單的實現了,讓我們仔細想想是不是哪裏不對勁啊?

      Yeah,問題又來了:

      1) 表格的列是在用的時候才設計checkbox列的,那麼怎樣才能讓這些功能在DataGridView中實現呢?

      2) 我們知道checkbox不一定只是爲了選中某一行,它還是一個狀態的控件,比如他要代表是否,我們不能同意而論啊?

      Ok,來吧,讓我們重新的整理一下:首先我們採用綁定的方式來設置標誌複選框,即指定多個複選框的其中一個爲標誌行選的複選框。其次,在CellPainting事件中選中該標誌複選框爲選中的行或者設置行單元格顏色等。然後就沒有然後了。。。

三、實現

      首先,設置一個標誌列名,如果此屬性設置爲checkbox的列名,則表示該checkbox列是標誌列。

   1:     private string m_FlagColumnName = string.Empty;
   2:          [Category("ut"), Browsable(true), Description("選中標誌選中列的一項"), Localizable(true)]
   3:          [DefaultValue(null), Editor(typeof(DataGridViewFlagRowEditor), typeof(System.Drawing.Design.UITypeEditor))]
   4:          public string FlagColumnName
   5:          {
   6:              get
   7:              {
   8:                  return m_FlagColumnName;
   9:              }
  10:              set
  11:              {
  12:                  m_FlagColumnName = value;
  13:                  if (!string.IsNullOrEmpty(m_FlagColumnName))
  14:                      base.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
  15:              }
  16:          }

      在CellPainting裏處理吧:

   1:    DataGridViewCheckBoxCellEx paintCell;
   2:          protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
   3:          {
   4:              if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
   5:              if (!this.Columns.Contains(FlagColumnName)) return;
   6:              paintCell = this.Rows[e.RowIndex].Cells[FlagColumnName] as DataGridViewCheckBoxCellEx;
   7:              if (paintCell != null && paintCell.Checked)
   8:              {
   9:                  //e.CellStyle.BackColor = e.CellStyle.SelectionBackColor;
  10:                  this.Rows[e.RowIndex].Selected = true;
  11:              }
  12:   
  13:              base.OnCellPainting(e);
  14:          }

      其實,最重點的在哪裏?我們如何將FlagColumnName設置與標誌checkbox的名字一致呢?手動?不至於吧,所以這裏用到了Editor

 

   1:  namespace DataGridViewEx.DataGridViewExs.EditorEx
   2:  {
   3:        /// <summary>
   4:      ///DataGridViewEx中的RowFlag標識設計器
   5:      /// </summary>
   6:      public class DataGridViewFlagRowEditor : UITypeEditor
   7:      {
   8:          const string NullValue = "(None)";
   9:          private IWindowsFormsEditorService m_editorService = null;
  10:          public DataGridViewFlagRowEditor()
  11:              : base()
  12:          {
  13:          }
  14:   
  15:          public override object EditValue(System.ComponentModel.ITypeDescriptorContext context,
  16:              IServiceProvider provider, object value)
  17:          {
  18:              if (context != null && context.Instance != null && provider != null)
  19:              {
  20:                  m_editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
  21:                  DataGridViewCheckBoxColumnEx column = null;
  22:                  List<string> columnNameList = new List<string>();
  23:   
  24:                  foreach (IComponent c in context.Container.Components)
  25:                  {
  26:                      if (c is DataGridViewCheckBoxColumnEx)
  27:                      {
  28:                          column = (DataGridViewCheckBoxColumnEx)c;
  29:                          columnNameList.Add(column.Name);
  30:                      }
  31:                  }
  32:                  if (columnNameList.Count > 0 && m_editorService != null)
  33:                  {
  34:                      int i = 0;
  35:                      string selectValue = (string)value;
  36:                      ListBox listBox = new ListBox();
  37:                      listBox.SelectedIndexChanged += new EventHandler(listBox_SelectedIndexChanged);
  38:                      listBox.Items.Add(NullValue);
  39:                      foreach (string name in columnNameList)
  40:                      {
  41:                          i = listBox.Items.Add(name);
  42:                          if (name == selectValue)
  43:                              listBox.SelectedIndex = i;
  44:                      }
  45:                      m_editorService.DropDownControl(listBox);
  46:                      if (listBox.SelectedItem != null)
  47:                      {
  48:                          if (listBox.SelectedItem.ToString() == NullValue)
  49:                              return string.Empty;
  50:                          return listBox.SelectedItem;
  51:                      }
  52:                  }
  53:              }
  54:              return value;
  55:          }
  56:   
  57:          private void listBox_SelectedIndexChanged(object sender, EventArgs e)
  58:          {
  59:              if (m_editorService != null)
  60:                  m_editorService.CloseDropDown();
  61:          }
  62:   
  63:          /// <summary>
  64:          /// Gets the editor style used by the EditValue method.
  65:          /// </summary>
  66:          /// <param name="context">An ITypeDescriptorContext that can be used to gain additional context information.</param>
  67:          /// <returns>A UITypeEditorEditStyle value that indicates the style of editor used by EditValue. If the UITypeEditor does not support this method, then GetEditStyle will return None</returns>
  68:          public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
  69:          {
  70:              if (context != null && context.Instance != null)
  71:              {
  72:                  return UITypeEditorEditStyle.DropDown;
  73:              }
  74:              return base.GetEditStyle(context);
  75:          }
  76:      }
  77:  }

 

 

這裏的Editor是Winform中自定義控件的一個很好的功能,即UI設計器的擴展。這裏通過Editor使得我們的FlagColumnName通過設計器中尋找到可選的所有的DataGridViewCheckboxColumnEx供用戶選擇:

r2

四、源碼及演示程序下載。

演示程序: FlagCheckboxColumn.rar

開源項目:http://sourceforge.net/p/datagridviewex/code-0/3/tree/trunk/DataGridViewEx/

作者:江心逐浪(個人開發歷程知識庫 - 博客園) 
出處:http://gxjiang.cnblogs.com/ 
文章版權歸本人所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章