[WinForm] DataGridView 綁定 DT && ComboBox 列綁定 Dict


一  需求介紹

一般像枚舉類型的數據,我們在數據庫里存儲着諸如(1、2、3、4…)或者(“001”、“002”、“003”…)此類,但是界面上我們想要顯示的是具體的文本內容,以便用戶理解使用。所以在從數據庫中加載出來的數據 DataTable 綁定到 DataGridView 上時,就需要其中一些枚舉列采用下拉框,並綁定對應的枚舉數據源。

二  具體實現

首先,如果 DataGridView 的 AutoGenerateColumns 為 true 時,在綁定 DataTable 到 DataGridView 上時,會自動生成綁定數據中的各列,且默認均為普通的 DataGridViewTextBoxColumn 。所以如果要設置 DataGridView 中的下拉列,首先要把 AutoGenerateColumns 設置為 false

  1 /// <summary>
  2 /// Sample
  3 /// DataGridView綁定DataTable,ComboBox列綁定enum枚舉
  4 /// </summary>
  5 public MainForm()
  6 {
  7     InitializeComponent();
  8 
  9     DataTable dataTable = CreateDataTable();
 10     dataGridView.AutoGenerateColumns = true;// 默認設置
 11     dataGridView.DataSource = dataTable;
 12     // SetGridView(dataTable);
 13 }
 14 
 15 /// <summary>
 16 /// 構建數據源
 17 /// 可以從數據庫讀取出來構建DataTable數據源
 18 /// </summary>
 19 /// <returns>DataTable數據表</returns>
 20 public DataTable CreateDataTable()
 21 {
 22     DataTable dt = new DataTable();
 23     dt.Columns.Add(new DataColumn("Id", typeof(int)));
 24     dt.Columns.Add(new DataColumn("Name", typeof(string)));
 25     dt.Columns.Add(new DataColumn("EnumCol1", typeof(int)));
 26     dt.Columns.Add(new DataColumn("EnumCol2", typeof(string)));
 27     Random r = new Random();
 28     for (int i = 0; i < 50; i++)
 29     {
 30         DataRow dr = dt.NewRow();
 31         dr[0] = r.Next();
 32         dr[1] = "Name = " + r.Next();
 33         dr[2] = r.Next(1, 5);
 34         dr[3] = "EnumCol_" + r.Next(1, 5);
 35         dt.Rows.Add(dr);
 36     }
 37 
 38     return dt;
 39 }
View Code

效果圖(AutoGenerateColumns = true):
image

    在將 AutoGenerateColumns 屬性設置為 false 后,就要手動生成各列了。其中 EnumCol1 列要綁定一個枚舉類型,EnumCol2 要綁定一個字典類型(Dictionary<string, string>)。

  1 /// <summary>
  2 /// 枚舉1
  3 /// </summary>
  4 private enum EnumCol1
  5 {
  6     A = 1,
  7     B = 2,
  8     C = 3,
  9     D = 4,
 10     E = 5
 11 }
 12 /// <summary>
 13 /// 枚舉轉字典
 14 /// </summary>
 15 /// <typeparam name="T"></typeparam>
 16 /// <param name="enumType"></param>
 17 /// <returns></returns>
 18 private Dictionary<int, string> EnumToDictionary(Type enumType)
 19 {
 20     Dictionary<int, string> result = new Dictionary<int, string>();
 21     foreach (int key in Enum.GetValues(enumType))
 22     {
 23         string value = Enum.GetName(enumType, key);
 24         result.Add(key, value);
 25     }
 26 
 27     return result;
 28 }

通過上面的代碼中 EnumToDictionary 方法把枚舉類型轉換為字典類型,這樣就可以統一處理數據綁定了。

  1 /// <summary>
  2 /// 設置DataGridView視圖
  3 /// </summary>
  4 /// <param name="dt">數據源表</param>
  5 public void SetGridView(DataTable dt)
  6 {
  7     // 在放棄綁定時自動生成列,並且還未初始化DataGridView的列時
  8     // 手動生成各列
  9     if (!dataGridView.AutoGenerateColumns && dataGridView.Columns.Count == 0)
 10     {
 11         Dictionary<int, string> dic = EnumToDictionary(typeof(EnumCol1));
 12         foreach (DataColumn dc in dt.Columns)
 13         {
 14             string colName = dc.ColumnName;
 15             DataGridViewColumn dgvc = null;
 16             if (colName.StartsWith("EnumCol"))// 生成下拉列
 17             {
 18                 dgvc = new DataGridViewComboBoxColumn();
 19                 BindingSource bs = new BindingSource();
 20                 if (colName.EndsWith("1"))// 綁定枚舉1
 21                 {
 22                     bs.DataSource = dic;
 23                     dgvc.ValueType = typeof(int);
 24                 }
 25                 else if (colName.EndsWith("2"))// 綁定枚舉2
 26                 {
 27                     bs.DataSource = new Dictionary<string, string>()
 28                     {
 29                         {"EnumCol_1", "AA"},
 30                         {"EnumCol_2", "BB"},
 31                         {"EnumCol_3", "CC"},
 32                         {"EnumCol_4", "DD"},
 33                         {"EnumCol_5", "EE"}
 34                     };
 35                     dgvc.ValueType = typeof(string);
 36                 }
 37                 ((DataGridViewComboBoxColumn)dgvc).DisplayMember = "Value";
 38                 ((DataGridViewComboBoxColumn)dgvc).ValueMember = "Key";
 39                 ((DataGridViewComboBoxColumn)dgvc).DataSource = bs;
 40                 ((DataGridViewComboBoxColumn)dgvc).DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
 41                 ((DataGridViewComboBoxColumn)dgvc).FlatStyle = FlatStyle.Flat;
 42             }
 43             else// 生成普通列
 44             {
 45                 dgvc = new DataGridViewTextBoxColumn();
 46             }
 47             dgvc.Name = colName;
 48             dgvc.DataPropertyName = colName;// 保證該列的值綁定到DataTable中colName列上
 49             dataGridView.Columns.Add(dgvc);
 50         }
 51     }
 52 }
 53 

在列類型為 DataGridViewComboBoxColumn,且要綁定字典數據源(Dictionary)時,需要通過 BindingSource 。即:

BindingSource bs = new BindingSource();
bs.DataSource = dic;
((DataGridViewComboBoxColumn)dgvc).DataSource = bs;

需要特別注意的是==>

48行代碼:

dgvc.DataPropertyName = colName;  表示該下拉列的值綁定對應於數據源 DataTable 中 colName 列數據;

37行、38行代碼:

((DataGridViewComboBoxColumn)dgvc).DisplayMember = "Value";

((DataGridViewComboBoxColumn)dgvc).ValueMember = "Key";

DisplayMember 是表示下拉框顯示的值綁定於 dgvc 的數據源的某個位置(字典的Value);

ValueMember 是表示下拉框實際值綁定於 dgvc 的數據源的某個位置(字典的Key);

23行、35行代碼:

dgvc.ValueType = typeof(int);

dgvc.ValueType = typeof(string);

這兩句則是指定該列綁定數據源里該列的類型。此時,必須保證數據源 DataTable 里該列的值類型,必須和該列的 ValueMember 屬性綁定的數據源類型一致。以文中例子,即 datagridview 的列 EnumCol1 和列 EnumCol2 的數據類型必須和所綁定的 Dictionary 的 Key 類型一致(因為 dgvc 的 ValueMember 屬性綁定於 Key)。

效果圖:

image

三  追加幾句

1、SQLite 數據庫中的 INTEGER 和 INT 類型區別需要通過“Tools –> Options –> Type Mappings”來確定。

image

但是實際上,其中 INT 類型是與C#的 Int32 對應,如果將 INTEGER 類型的列綁定到 Dictionary<int, string>上,是會報如下錯誤的:

image

2、本文以 DataGridViewComboBoxColumn 列綁定 Dictionary 字典數據源為例說明具體綁定細節,當然該類型列也可以綁定於 DataTable 等其他類型數據,只要設置好綁定細節就可以了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM