zoukankan      html  css  js  c++  java
  • [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 等其他类型数据,只要设置好绑定细节就可以了。

  • 相关阅读:
    WPF游戏摘记地图编辑器(1)
    图片和视频操作核心代码
    WPF游戏摘记地图编辑器(2)
    序言
    Asp.Net 请求处理机制
    C#正则表达式
    ActiveX控件打包成Cab实现浏览器自动下载安装
    ios数据存储
    ARC 学习
    Ray's Learn Cocos2d 笔记(一)
  • 原文地址:https://www.cnblogs.com/memento/p/4677698.html
Copyright © 2011-2022 走看看