[WinForm] DataGridView绑定DataTable,ComboBox列绑定Dictionary

一  需求介绍

一般像枚举类型的数据,我们在数据库里存储着诸如(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 }

效果图(AutoGenerateColumns = true):

在将 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)。

效果图:

三  追加几句

1、SQLite 数据库中的 INTEGER 和 INT 类型区别需要通过“Tools –> Options –> Type Mappings”来确定。

但是实际上,其中 INT 类型是与C#的 Int32 对应,如果将 INTEGER 类型的列绑定到 Dictionary<int, string>上,是会报如下错误的:

2、本文以 DataGridViewComboBoxColumn 列绑定 Dictionary 字典数据源为例说明具体绑定细节,当然该类型列也可以绑定于 DataTable 等其他类型数据,只要设置好绑定细节就可以了。

3、至于楼主在网上查找相关资源时,有不少人(All Most)提到要在绑定 DataGridViewComboBoxColumn 的数据源之后再绑定 datagridview 的数据源就可以解决上面那个异常,而且这种答案粘贴的满网络都是,可是楼主当初尝试了无论哪个在前哪个在后都是不行,害的楼主怀疑了老半天自己的智商,⊙︿⊙!最后还是用GoogleFQ查到一个英文论坛里一段英文回复才晓得哪里才是这个异常的关键!怎么说呢,这种未经验证的解决方案在中文网络里传的到处都是,而且一看就知道是那种粘贴复制过来的,也没有其他注解说明。

有句话说的不无道理,程序员本来就挺辛苦的,经常加班熬夜啥的,我们程序员自己又何必为难程序员呢?你给别人挖一个坑,别人也给你挖一个坑,好吧,我们这个行业就在这里玩跳坑,爬坑的弱智游戏吧,然后让其他行业嘲笑鄙视我们吧!何必呢!还是希望在发布或者转发一个解决方案时,能先验证它的正确性,再加以自己的注释说明,至少要对得起这份职业,对得起其他的程序员,少给别人挖坑,别人也给你少挖坑,这样何愁啥bug解决不了,何愁多费那么多无用功去解决一个别人已经解决好的问题呢?

四  资源下载

样例工程: http://files.cnblogs.com/files/memento/DataGridView_ComboBoxColumnSample.zip

时间: 2024-07-29 09:21:12

[WinForm] DataGridView绑定DataTable,ComboBox列绑定Dictionary的相关文章

Winform DataGridView鼠标右键选择列

1.设置DataGridView 的属性 SelectionMode SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; 2.设置事件CellMouseDown private void dgvResult_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e) { if (e.RowIndex == -1 || e.Col

C#WinForm datagridview控件改变列标题的名字

1 2 3

DataTable绑定到ComboBox

我们从数据库中查询出来的数据存放在Datatable中 1.DataTable绑定到ComboBox上 cmbRole.DataSource = datatable; cmbRole.DisplayMember = "RoleName"; cmbRole.ValueMember = "RoleID"; 2.根据选择的结果,取得需要的数据信息 DataRowView dv = cmbRole.Items[cmbRole.SelectedIndex] as DataRo

C# Winform 关于ListView控件绑定DataTable

今天用到ListView控件,这里总结一下ListView控件绑定DataTable的方法 下面需要特别注意的是,绑定的过程中实现绑定控件的column的属性,再进行item的绑定. 与DataGridView不同的是,不能直接使用DataSourse绑定, 再者,绑定第一个Items的时候一定要实例化一个Item进行单独绑定,因为第一个Item与后面的不用即Item与SubItem的区别,下面的代码中也给出了相应的注释 [csharp] view plain copy private void

C#.Net 给DataGridView列绑定数据和显示列名的方法

选择DataGridView控件,在属性中选择Colums属性项点击,编辑DataGridView控件的列,可以通过列编辑器添加多个列项,其中列属性的中HeadText是对外显示的,即向用户呈现的,Name是用于命名列对象的,而DataPropertyName是用于指定你将数据源的那一列绑定到该列上的,就是这个列属性可以DataGridView中的列绑定指定的数据,具体只需要将DataPropertyName列属性指定为数据源的某个列名即可,例如:数据源中一列为“UserName”,则将Data

datagridview 绑定 datatable

if (dt != null) { DataGridViewColumn dgvc = null; this.dataGridView1.DataSource = null; this.dataGridView1.Columns.Clear(); foreach (DataColumn dc in dt.Columns) { dgvc = new DataGridViewColumn(); dgvc.Name = dc.ColumnName; dgvc.HeaderText = dc.Colum

[转]WinForm DataGridView 绑定泛型List(List&lt;T&gt;)/ArrayList不显示的原因和解决

背景:无意间遇到了一个不大不小的问题,希望对一些遇到的人有所帮助! 一.问题 WinForm DataGridView 绑定泛型List (List<T>)/ArrayList不显示,UI 代码如下: using System; using System.Collections.Generic; using System.Data; using System.Data.OleDb; using System.IO; using System.Windows.Forms; namespace W

C# 控制datagridview的combox属性的列绑定数据

//datagridvie列绑定list的数据 List<User> listChange = GetChange();//查询数据库内容,保存到list this.datagridview1.AutoGenerateColumns = false;//禁止生成不需要的列 this.datagridview1.DataSource = listChange;//list的内容绑定到datagridview Gender.DataSource = listChange;//list的内容绑定到d

C# datagridview列绑定类中类的属性

datagridview编辑列时,对于类中类的属性绑定,尝试了一下”类名.属性名“ 并没有正确绑定,后又尝试了几次无果,只能利用Linq来解决了, 首先,datagridview要绑定的是学生类(Student),而学生类里有老师类(Teacher) 1 public class Student 2 { 3 public int Id; 4 public Teacher teacher; 5 } 6 7 public class Teacher 8 { 9 public string Name;