如何将DataGridViewComboBoxColumn绑定到对象?

时间:2009-03-10 16:34:40

标签: c# winforms data-binding datagridview datagridviewcombobox

我正在尝试将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

我错过了什么吗?是否有可能将数据绑定到复杂的对象?

更新

我实现了一个TypeConverter并覆盖了CanConvertFrom,CanConvertTo,ConvertTo,ConvertFrom。现在我得到了

  

FormatException:DataGridViewComboBoxCell值无效

有什么想法吗?

4 个答案:

答案 0 :(得分:6)

你错过了一件可能的作品。

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;

更新:

实际上,在再次阅读你的问题之后,我认为你正面临着这个着名的错误。遗憾的是,如果不使用自定义的TypeDescriptor / TypeConverter / BindingSource,就无法返回绑定对象。

回答绑定到复杂对象。没有默认值。我为我当前的项目写了一篇很好的文章。这涉及制作一个返回所有嵌套属性的自定义TypeDescriptor / TypeConverter / BindingSource。另一个'错误',你不能使用'。'对于成员分隔符,我不得不求助于':'。

答案 1 :(得分:6)

DataGridViewComboBoxColumn应始终具有组合框列表中的所有可能值,否则将抛出“FormatException:DataGridViewComboBoxCell值无效”。

如果您尝试从一个组合框列中选择值,则可以处理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;
   }
}

您还可以通过处理单元格格式化事件来自定义对象在每个单元格上显示的方式,这里是一个显示任何对象或接口的toString的代码。

private void dataGridView1_CellFormatting(object sender, 
    DataGridViewCellFormattingEventArgs e) {
        if (e.Value != null) {
            e.Value = e.Value.ToString();
            e.FormattingApplied = true;
        }
    } 

处理这两个事件应该足以在任何商业对象中显示和编辑数据,然后更容易编写类型转换器。为此工作设置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 ();

不需要设置DisplayMember或ValueMember属性,只需确保您的组合框数据源列表具有Foo的所有可能值。

希望它有所帮助。

答案 2 :(得分:4)

实际上,您可以在DataGridViewComboBoxColumn中使用复杂类型。

例如:

DataGridViewComboBoxColumn.DataPropertyName = "ValueMode";
DataGridViewComboBoxColumn.DisplayMember = "Label";
DataGridViewComboBoxColumn.ValueMember = "Self"; *
DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem);

Self是:

public ValueModeItem Self
{
    get
    {
        return this;
    }
}

非常重要 - 需要覆盖复杂类型的'Equals'方法。 就我而言:

public override bool Equals(object obj)
{
    if (obj is ValueModeItem && obj != null)
    {
        if (...)
            return true;
    }
    return false;
}

答案 3 :(得分:2)

我一直在遇到同样的问题,直到我发现你不能设置DisplayMember的{​​{1}}而没有设置DataGridViewComboBoxCell。 同样,设置ValueMember而不是ValueMember也是失败的,您必须定义无或两者。

你的模型是Foo,你当然希望ComboBox的值是项目本身。为此,最简单的方法是在你的foo中创建一个Property,然后自行返回。

DisplayMember

然后绑定变为:

public class Foo
{
    ...
    public Foo This { get {return this; } }
}

这应该有效,并且Cell的值应该是Foo类型的预期值。

一个有趣的参考:Problems with the DataGridViewComboBoxColumn

  

但是,DataGridViewComboBoxColumn不能像这样工作,   虽然如果不设置,它会显示ToString值   DisplayMember,当它试图查看时内部出错   在SelectedItem中,您必须将DisplayMember设置为public   你班上的财产。更糟糕的是,如果不这样做,则为默认行为   设置ValueMember属性是为了返回DisplayMember   无法获得实际物品本身。唯一的解决方法是添加一个   返回自身并将该属性设置为的类的属性   ValueMember。当然,如果您的物品不是您能够的物品   要改变(比如其中一个框架类)你必须要修改   一起容纳对象的容器对象。