繁体   English   中英

如何将 DataGridViewComboBoxColumn 绑定到 object?

[英]How to bound a DataGridViewComboBoxColumn to a object?

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

我错过了什么吗? 是否可以将数据绑定到复杂的 object?

更新:

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

FormatException:DataGridViewComboBoxCell 值无效

有任何想法吗?

你错过了一个可能的部分。

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,就无法让它返回绑定的 object。

绑定到复杂的 object 的答案。 默认没有。 我为我当前的项目写了一个相当不错的。 这涉及制作一个返回所有嵌套属性的自定义 TypeDescriptor/TypeConverter/BindingSource。 另一个“错误”,您不能使用“。” 对于成员分隔符,我不得不求助于“:”。

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

如果您试图取回从 combobox 列中选择的值,您可以处理 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;
   }
}

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

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

处理这两个事件应该足以显示和编辑任何业务 object 及其轻松然后编写类型转换器中的数据。 对于这项工作,您可以设置 DataGridView 和 combobox 列,如下所示:

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 属性,只需确保您的 combobox 数据源列表具有 Foo 的所有可能值。

希望它有所帮助。

实际上,您可以在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;
}

我一直在遇到同样的问题,直到我发现如果不设置ValueMember就无法设置DataGridViewComboBoxCellDisplayMember
同样,设置ValueMember而不是DisplayMember也是失败的,您必须定义 none 或两者都定义。

您的 model 是 Foo,您当然希望 ComboBox 的值是项目本身。 为此,最简单的方法是在您的 foo 中创建一个属性,然后返回自身。

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

然后绑定变为:

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";

这应该可以工作,并且单元格的值应该是 Foo 类型,如预期的那样。

一个有趣的参考: DataGridViewComboBoxColumn 的问题

但是,DataGridViewComboBoxColumn 不是这样工作的,尽管如果您不设置 DisplayMember,它将显示 ToString 值,但当它尝试查找 SelectedItem 时出现内部问题,您必须将 DisplayMember 设置为的公共属性你的 class。 更糟糕的是,如果您不设置 ValueMember 属性,则默认行为是返回 DisplayMember,无法获取实际项目本身。 唯一的解决方法是向 class 添加一个属性,该属性返回自身并将该属性设置为 ValueMember。 当然,如果您的项目不是您能够更改的东西(例如框架类之一),您将不得不将一个包含对您的项目的引用的容器 object 聚集在一起。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM