C# 如何将 DataGridViewComboBoxColumn 绑定到对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/631126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to bound a DataGridViewComboBoxColumn to a object?
提问by albertein
I'm trying to bound a DataGridViewComboBoxColumn
to an instance of Foo, but when i set a value on the grid i got a ArgumentException
telling me that i can not convert from String to Foo.
我试图将 a 绑定DataGridViewComboBoxColumn
到 Foo 的一个实例,但是当我在网格上设置一个值时,我得到一个ArgumentException
告诉我我无法从 String 转换为 Foo 的消息。
var data = (from item in someTable
select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance
Am i missing something? is it possible to databind to a complex object?
我错过了什么吗?是否可以将数据绑定到复杂对象?
UPDATE:
更新:
I implemented a TypeConverter and overrided CanConvertFrom, CanConvertTo, ConvertTo, ConvertFrom. Now i'm getting
我实现了一个 TypeConverter 并覆盖了 CanConvertFrom、CanConvertTo、ConvertTo、ConvertFrom。现在我得到
FormatException: The DataGridViewComboBoxCell value is not valid
FormatException: DataGridViewComboBoxCell 值无效
Any ideas?
有任何想法吗?
采纳答案by leppie
You are missing a possible piece.
你错过了一个可能的部分。
column.DataPropertyName = "Foo";
column.DisplayMember = "SomeNameField";
column.ValueMember = "Bar"; // must do this, empty string causes it to be
// of type string, basically the display value
// probably a bug in .NET
column.DataSource = from foo in Foo select foo;
grid.DataSource = data;
UPDATE:
更新:
Actually, after reading your question again, I think you are facing that noted bug. There is unfortunately no way to make it return the bound object without using a custom TypeDescriptor/TypeConverter/BindingSource.
实际上,在再次阅读您的问题后,我认为您正面临着那个注意到的错误。不幸的是,如果不使用自定义 TypeDescriptor/TypeConverter/BindingSource,则无法使其返回绑定对象。
Answer for binding to a complex object. No by default. I wrote quite a nice one for my current project. This involves making a custom TypeDescriptor/TypeConverter/BindingSource that returns all the nested properties. Another 'bug', you cant use '.' for a member separator, I had to resort to ':' instead.
绑定到复杂对象的答案。默认没有。我为我当前的项目写了一个很好的。这涉及制作一个返回所有嵌套属性的自定义 TypeDescriptor/TypeConverter/BindingSource。另一个“错误”,您不能使用“。” 对于成员分隔符,我不得不求助于“:”。
回答by Nei
the DataGridViewComboBoxColumn should always have all the possible values at the combobox Items list or it will throw "FormatException: The DataGridViewComboBoxCell value is not valid".
DataGridViewComboBoxColumn 应始终在组合框项目列表中包含所有可能的值,否则它将抛出“FormatException:DataGridViewComboBoxCell 值无效”。
If you are trying to get back values chosen from one combobox column, you can handle the DataGridView CellParsing event, and get the selected item from DataGridView.EditingControl cause it will be set for editing control from the edited column. Here is a exemple:
如果您试图取回从一个组合框列中选择的值,您可以处理 DataGridView CellParsing 事件,并从 DataGridView.EditingControl 中获取所选项目,因为它将被设置为从编辑的列中编辑控件。这是一个例子:
private void dataGridView1_CellParsing(object sender,
DataGridViewCellParsingEventArgs e) {
if (dataGridView1.CurrentCell.OwningColumn is DataGridViewComboBoxColumn) {
DataGridViewComboBoxEditingControl editingControl =
(DataGridViewComboBoxEditingControl)dataGridView1.EditingControl;
e.Value = editingControl.SelectedItem;
e.ParsingApplied = true;
}
}
You also can customize the way your objects are show on each cell by handling the cell Formatting Event, here is a code that display toString for any object or interface.
您还可以通过处理单元格格式事件来自定义您的对象在每个单元格上的显示方式,这里是为任何对象或界面显示 toString 的代码。
private void dataGridView1_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e) {
if (e.Value != null) {
e.Value = e.Value.ToString();
e.FormattingApplied = true;
}
}
Handles this two events should be enough for show and edit data within any bussiness object and its easer then write type converters. For this work set you DataGridView and you combobox column as follow:
处理这两个事件应该足以在任何业务对象中显示和编辑数据,然后编写类型转换器。对于这项工作,您将 DataGridView 和组合框列设置为如下:
var data = (from item in someTable
select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList ();
No DisplayMember or ValueMember Property need to be set, just make sure your combobox data source list has all the possible values for Foo.
不需要设置 DisplayMember 或 ValueMember 属性,只需确保您的组合框数据源列表具有 Foo 的所有可能值。
Hope its helps.
希望它有帮助。
回答by Cyril Gandon
I was constantely hitting the same problem until I discovert that you cannot set the DisplayMember
of the DataGridViewComboBoxCell
without setting the ValueMember
too.
In the same way, setting the ValueMember
and not the DisplayMember
is a fail too, you have to define none or both.
我constantely击中了同样的问题,直到我discovert,你不能设置DisplayMember
的DataGridViewComboBoxCell
没有设置ValueMember
过。
同样,设置 theValueMember
和 not theDisplayMember
也是失败的,您必须定义 none 或两者。
Your model is Foo, and you certainly want that the Value of the ComboBox be the item itself. For doing this, the simplest way is too create a Property in your foo, returning itself.
您的模型是 Foo,您当然希望 ComboBox 的值是项目本身。为此,最简单的方法是在您的 foo 中创建一个属性,返回自身。
public class Foo
{
...
public Foo This { get {return this; } }
}
Then bindings becomes:
然后绑定变成:
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance
column.ValueMember = "This";
This should work, and the Value of the Cell should be of type Foo as expected.
这应该可以工作,并且 Cell 的 Value 应该是预期的 Foo 类型。
An interesting reference: Problems with the DataGridViewComboBoxColumn
一个有趣的参考:Problems with the DataGridViewComboBoxColumn
However, the DataGridViewComboBoxColumn doesn't work like this, although it will display the ToString value if you don't set the DisplayMember, something internally goes wrong when it tries to look up the SelectedItem, you have to set DisplayMember to a public property of your class. Even worse, the default behaviour if you don't set the ValueMember property is to return the DisplayMember, there's no way of getting actual item itself. The only work around is to add a property to your class that returns itself and set that property to the ValueMember. Of course, if your item isn't something you are able to change (such as one of the framework classes) you'll have to cludge together a container object that holds a reference to your item.
但是,DataGridViewComboBoxColumn 不是这样工作的,尽管如果您不设置 DisplayMember 它会显示 ToString 值,但是当它尝试查找 SelectedItem 时会出现内部错误,您必须将 DisplayMember 设置为公共属性你的班。更糟糕的是,如果不设置 ValueMember 属性,默认行为是返回 DisplayMember,无法获取实际项目本身。唯一的解决方法是向您的类添加一个属性,该属性返回自身并将该属性设置为 ValueMember。当然,如果您的项目不是您能够更改的(例如框架类之一),您将不得不将一个包含对您的项目的引用的容器对象拼凑在一起。
回答by ?ysy
Actually, you can use a complex type in DataGridViewComboBoxColumn
.
实际上,您可以在DataGridViewComboBoxColumn
.
For example:
例如:
DataGridViewComboBoxColumn.DataPropertyName = "ValueMode";
DataGridViewComboBoxColumn.DisplayMember = "Label";
DataGridViewComboBoxColumn.ValueMember = "Self"; *
DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem);
Self
is:
Self
是:
public ValueModeItem Self
{
get
{
return this;
}
}
Very important - need to override 'Equals' method of a complex type. In my case:
非常重要 - 需要覆盖复杂类型的 'Equals' 方法。就我而言:
public override bool Equals(object obj)
{
if (obj is ValueModeItem && obj != null)
{
if (...)
return true;
}
return false;
}