设置 DisplayMember 时 DataGridViewComboBoxColumn 会发生啥?
Posted
技术标签:
【中文标题】设置 DisplayMember 时 DataGridViewComboBoxColumn 会发生啥?【英文标题】:What happen to DataGridViewComboBoxColumn when DisplayMember is set?设置 DisplayMember 时 DataGridViewComboBoxColumn 会发生什么? 【发布时间】:2013-11-08 14:27:21 【问题描述】:当我有一个充满绑定值的DataGridViewComboBoxColumn
,并且如果我设置了DisplayMember
属性,我会得到DataError
引发的FormatException
事件:
DataGridViewComboBoxCell 值无效
如果未设置DisplayMember
,则视图显示.ToString()
的结果,则一切正常。
这是一个完整的例子:
public partial class Form1 : Form
public Form1() InitializeComponent();
private void Form1_Load(object sender, EventArgs e)
var categories = new[] CustomerCategory.Cat1, CustomerCategory.Cat2, CustomerCategory.Cat3 ;
this.dataGridView1.AutoGenerateColumns = false;
this.dataGridView1.DataError += new DataGridViewDataErrorEventHandler(dataGridView1_DataError);
this.dataGridView1.CellParsing += new DataGridViewCellParsingEventHandler(dataGridView1_CellParsing);
this.dataGridView1.Columns.Add(new DataGridViewComboBoxColumn()
DataSource = categories,
HeaderText = "Category",
DataPropertyName = "Category",
DisplayMember = "Name" // if we omit this line, there is not DataError event raised
);
this.dataGridView1.DataSource = new[]
new Customer() Category = CustomerCategory.Cat1
, new Customer() Category = CustomerCategory.Cat2
, new Customer() Category = CustomerCategory.Cat3
.ToList();
void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
var value = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
var type = value != null ? value.GetType() : null;
string message = "Error"
+ Environment.NewLine + " - Column : " + e.ColumnIndex
+ Environment.NewLine + " - Line : " + e.RowIndex
+ Environment.NewLine + " - Value : " + Convert.ToString(value) + " (" + type + ")"
+ Environment.NewLine + " - Exception : " + e.Exception.Message;
Debug.Fail(message);
void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
//http://***.com/questions/631126/how-to-bound-a-datagridviewcomboboxcolumn-to-a-object
if (this.dataGridView1.CurrentCell.OwningColumn is DataGridViewComboBoxColumn)
var editingControl = (DataGridViewComboBoxEditingControl)this.dataGridView1.EditingControl;
e.Value = editingControl.SelectedItem;
e.ParsingApplied = true;
型号:
public class CustomerCategory
public static readonly CustomerCategory Cat1 = new CustomerCategory Name = "Cat1" ;
public static readonly CustomerCategory Cat2 = new CustomerCategory Name = "Cat2" ;
public static readonly CustomerCategory Cat3 = new CustomerCategory Name = "Cat3" ;
public string Name get; set;
public override string ToString() return this.Name;
public class Customer public CustomerCategory Category get; set;
如何指定我自己的DisplayMember
而不引发这个烦人的DataError
事件?
问题只出现在DataGridViewComboBoxColumn
上,而不是普通的ComboBox
。
编辑:经过几次测试,我可以说:
[DisplayMember + Not ValueMember] = FAIL
[Not DisplayMember + ValueMember] = FAIL
[DisplayMember + ValueMember] = WIN
所以我的问题可以改写为:是否有任何文档可以准确解释什么可行,什么不可行?以及DisplayMember
+ ValueMember
是如何链接在一起的?
重新编辑:
一个有趣的参考:Problems with the DataGridViewComboBoxColumn
但是,DataGridViewComboBoxColumn 不能这样工作, 虽然如果你不设置它会显示 ToString 值 DisplayMember,尝试查看时出现内部问题 上 SelectedItem,您必须将 DisplayMember 设置为公共 你班级的财产。更糟糕的是,如果你不这样做,默认行为 设置ValueMember属性就是返回DisplayMember,有 无法获得实际物品本身。唯一的解决方法是添加一个 属性到您的类,该类返回自身并将该属性设置为 价值成员。当然,如果你的物品不是你能做的 要更改(例如框架类之一),您必须坚持 一个包含对您的项目的引用的容器对象。
有人有关于内部出现问题部分的任何信息吗?
【问题讨论】:
什么是 Exception.Message?如果您使用 DisplayMember,我认为您还必须设置 ValueMember。 对不起。你有没有 -1ed 我的答案?你能解释一下原因吗? 告诉我你无法理解的确切点:有一个一维数据源,你不需要引用任何列(只要只有 1 列);如果要引用列,请使用带有列的 2D 数据源。请告诉我哪一部分让你感到困惑。 您现在可以删除这个问题(这就是你们人们的行为方式,不是吗?):您已经拥有信息(1D 和 2D 数据源之间的差异;如果发现 DataGridView 存在问题依赖DataTable;类的属性名称不能被视为列(MSDN 可以松散地引用属性,但如前所述,真正支持列和DataGridViews)),您可以在需要其他内容时返回并返回。 【参考方案1】:以下逻辑可能会帮助您解决问题。
我认为问题出在代码行的顺序上。在分配显示成员属性后分配数据源可能会导致错误。
改变这一行;
this.dataGridView1.Columns.Add(new DataGridViewComboBoxColumn()
DataSource = categories,
HeaderText = "Category",
DataPropertyName = "Category",
DisplayMember = "Category" // if we omit this line, there is not DataError event raised
);
到
DataGridViewComboBoxColumn col = new DataGridViewComboBoxColumn();
col.HeaderText = "Category";
col.DataSource = categories;
col.DisplayMember = "Category";
col.DataPropertyName = "Category";
this.dataGridView1.Columns.Add(col);
必须在 DisplayMember 和 ValueMember 之前分配数据源。
【讨论】:
以上是关于设置 DisplayMember 时 DataGridViewComboBoxColumn 会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
ComboBox.ValueMember 和 DisplayMember
easyui------设置datagrid('getEditor')时焦点问题
ComboBox 中 DisplayMember 和 ValueMember有何区别
CheckedListbox Displaymember 和 ValueMember
具有 Datagridviewcombobox 列的单元格显示 ValueMember 而不是 DisplayMember