代码之家  ›  专栏  ›  技术社区  ›  albertein

如何将DataGridViewComboBoxColumn绑定到对象?

  •  4
  • albertein  · 技术社区  · 15 年前

    DataGridViewComboBoxColumn 到Foo的一个实例,但是当我在网格上设置一个值时,我得到了一个 ArgumentException 告诉我我不能从字符串转换为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
    

    更新:

    FormatException:DataGridViewComboxCell值无效

    有什么想法吗?

    4 回复  |  直到 11 年前
        1
  •  6
  •   leppie    15 年前

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

    处理这两个事件应该足以显示和编辑任何业务对象及其easer中的数据,然后写入类型转换器。对于此工作,请按如下方式设置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 ();
    

    希望它能有所帮助。

        2
  •  6
  •   Nei    13 年前

    你错过了一个可能的片段。

    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;
    

    更新:

    事实上,在再次阅读您的问题之后,我认为您正面临着那个著名的bug。不幸的是,如果不使用自定义TypeDescriptor/TypeConverter/BindingSource,就无法让它返回绑定对象。

    回答绑定到复杂对象的问题。默认情况下没有。我为我当前的项目写了一篇很好的文章。这涉及到创建一个自定义TypeDescriptor/TypeConverter/BindingSource,返回所有嵌套属性。另一个“bug”,你不能使用“.”作为成员分隔符,我不得不使用“:”来代替。

        3
  •  5
  •   Jimi    6 年前

    实际上,您可以在中使用复杂类型 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;
    }
    
        4
  •  3
  •   Cyril Gandon niktrs    11 年前

    我不断地遇到同样的问题,直到我发现你不能设置 DisplayMember DataGridViewComboBoxCell 不设置 ValueMember
    同样,设置 而不是 显示值 也是一个失败,你必须定义没有或两者都没有。

    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类型。

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

    尽管如果不设置 在SelectedItem上,必须将DisplayMember设置为公共 设置ValueMember属性是为了返回DisplayMember,有 无法获取实际项目本身。唯一的解决办法是添加一个 属性,并将该属性设置为 价值观成员。当然,如果你的物品不是你能做的 要更改(例如某个框架类),您必须使用clude 一个容器对象,其中包含对项目的引用。