如何将DataGridViewComboBoxColumn绑定到返回列表的对象的属性/方法?

时间:2012-06-29 20:26:38

标签: c# winforms data-binding datagridview

我有一个包含多个属性的自定义对象,其中一个属性返回一个列表。这是对象的代码:

public class SearchResult
{
    private int eventId;
    private String eventTitle;
    private int startDate;
    private List<String> tags;

    // Properties
    public int EventId { get { return this.eventId; } }

    public String EventTitle { get { return this.eventTitle; } }

    public int StartDate { get { return this.startDate; } }

    public List<String> Tags { get { return this.tags; } }

    public SearchResult(int eventId, String eventTitle, int startDate, List<String> tags)
    {
        // Constructor code
    }

    public List<String> GetTags()
    {
        return this.tags;
    }
}

我还想要DataGridViewComboBoxColumn绑定到Tags属性。基本上,每个SearchResult对象都会显示在自己的行中,我希望每个对象的List<String>属性中的Tags显示在ComboBox单元格中行。这是我到目前为止DataGridView

的代码
BindingList<SearchResult> results = new BindingList<SearchResult>();
results.Add(new SearchResult(1, "This is a title", 2012, new List<String> { "Tag1", "Tag with a long name1" }));
results.Add(new SearchResult(2, "The quick brown fox", 2012, new List<String> { "Stack", "Overflow" }));
results.Add(new SearchResult(3, "In this tutorial, you create a class that is the type for each object in the object collection. ", 2012, new List<String> { "NYSE", "FTSE" }));
results.Add(new SearchResult(4, "another long piece of title text", -999, new List<String> { "Rabbits", "Chickens" }));

MyDataGrid.AutoGenerateColumns = false;
MyDataGrid.AllowUserToAddRows = false;
MyDataGrid.AllowUserToDeleteRows = false;
MyDataGrid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.None;
MyDataGrid.BackgroundColor = System.Drawing.SystemColors.Control;
MyDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
MyDataGrid.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
MyDataGrid.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.DisplayedCells;
MyDataGrid.DefaultCellStyle.WrapMode = DataGridViewTriState.True;

DataGridViewTextBoxColumn eventIdColumn = new DataGridViewTextBoxColumn();
eventIdColumn.DataPropertyName = "EventId";
eventIdColumn.HeaderText = "Event ID";
eventIdColumn.ReadOnly = true;
eventIdColumn.Width = 84;

DataGridViewTextBoxColumn eventTitleColumn = new DataGridViewTextBoxColumn();
eventTitleColumn.DataPropertyName = "EventTitle";
eventTitleColumn.HeaderText = "Event Title";
eventTitleColumn.ReadOnly = true;
eventTitleColumn.Width = 368;

DataGridViewTextBoxColumn startDateColumn = new DataGridViewTextBoxColumn();
startDateColumn.DataPropertyName = "StartDate";
startDateColumn.HeaderText = "Start Date";
startDateColumn.ReadOnly = true;
startDateColumn.Width = 130;

//I think I need to insert the code for the tags column here, but I'm not sure

MyDataGrid.Columns.Add(eventIdColumn);
MyDataGrid.Columns.Add(eventTitleColumn);
MyDataGrid.Columns.Add(startDateColumn);
//MyDataGrid.Columns.Add(tagsColumn);

MyDataGrid.DataSource = results;

我从a tutorial I found online派生了这个代码,它完美无缺。

我一直在尝试将Tags的{​​{1}}属性绑定到SearchResult,但我不确定如何。我一直在查看this question,它提供了以下代码:

DataGridViewComboBoxColumn

我遇到麻烦的原因是由于我不理解的链接问题的一些细微差别。

  1. 根据the documentation和关联的问题,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; 应链接到“包含实例说明”的属性,但由于DisplayMember对象是动态添加的,因此我有任何与他们相关的描述,我应该留空吗?
  2. SearchResult给了我类似的问题,因为我不确定即使在阅读its documentation后还要放什么。
  3. 在链接的问题中,接受的答案使用LINQ立即绑定整个数据网格。我应该这样做吗?我不确定如何根据我的情况修改代码,但我认为这将是这些内容。
  4. ValueMember

    我还假设我应该有一行为列设置tagsColumn.DataPropertyName = "Tags"; tagsColumn.DisplayMember = ""; // I'm unsure of what to put here tagsColumn.ValueMember = ""; // Once again, I don't know what to set this to ,例如

    DataSource

    但我不知道,因为我能找到的唯一最相关的C#源是那个问题。

    更新:

    我确实发现a second question建议使用与此类似的代码进行数据绑定:

    tagsColumn.DataSource = <some LINQ query, perhaps?>
    

    基于此,我a)将// reference the combobox column DataGridViewComboBoxColumn cboBoxColumn = (DataGridViewComboBoxColumn)dataGridView1.Columns[0]; cboBoxColumn.DataSource = Choice.GetChoices(); cboBoxColumn.DisplayMember = "Name"; // the Name property in Choice class cboBoxColumn.ValueMember = "Value"; // ditto for the Value property 方法添加到GetTags()并将此代码添加到我的SearchResult初始化代码中:

    DataGridView

    然而,当我尝试运行时,Visual Studio在第二行给出了错误:

            DataGridViewComboBoxColumn tagsColumn = new DataGridViewComboBoxColumn();
            tagsColumn.DataSource = SearchResult.GetTags(); // ERROR 
            tagsColumn.DisplayMember = ""; // Still not sure
            tagsColumn.ValueMember = ""; // ??
    

    更新2:

    我仍然没有成功地四处寻找。我不明白如何使用其他属性(例如An object reference is required for the non-static field, method, or property 'SearchResult.GetTags()' )我可以简单地将数据属性名称声明为EventId,它将显示在表中,但我无法使用{{1}执行此操作} 列。

    由于对象在一个单独的类中实例化并放入一个列表中,因此对我来说似乎没有意义我应该遍历整个对象数组(其中可能有几百个)到将EventId属性绑定到每个实例的ComboBox列,当我不需要遍历Tags个对象列表来绑定其他属性时,例如ComboBox

    为什么这个按名称绑定的属性仅适用于某些属性而不适用于其他

    属性?

2 个答案:

答案 0 :(得分:3)

我不太明白为什么要使用DataGridViewComboBoxColumn来显示元素列表。此列类型旨在允许用户选择多种可能性之一。它接缝不是你的情况,因为你没有public string SelectedTag{get;set;}属性来存储它。据我了解您的模型,您已为SearchResult选择了许多标签,并希望将它们显示在网格中。

正如文件所述:  http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcomboboxcolumn.datasource

  

获取或设置此[ DataSource ]属性可获取或设置CellTemplate属性返回的对象的DataSource属性。设置此属性还会在列中设置每个单元格的DataSource属性,并刷新列显示。要覆盖单个单元格的指定值,请在设置列值后设置单元格值。

DataGridViewComboBoxColumn根本无法将items属性绑定到数据源,因为它假定只有一个元素列表用作所有数据网格行的数据源。

我还假设您将为此列设置ReadOnly = true属性,就像您拥有所有其他属性一样。如果是这样,它将阻止用户表单查看标签列表,因为永远不会显示下拉列表。

如果您想以只读模式显示字符串列表,我建议将此标记列表展平为单个字符串:

public string Tags { get { return string.Join(", ", tags); } }

并将其显示在文本列中。

答案 1 :(得分:1)

对于错误,我建议您创建类的实例,然后将该方法称为非静态方法,或者可以使方法静态。

此外,您需要组合框,

DataGridViewComboBoxColumn tagsColumn = new DataGridViewComboBoxColumn();
        tagsColumn.DataSource = SearchResult.GetTags(); // ERROR 
        tagsColumn.DisplayMember = ""; // Still not sure
        tagsColumn.ValueMember = ""; // ??

大多数情况下,我们有像Country(id,name)这样的对象的下拉列表,因此DisplayMember = name将在下拉列表中显示为文本,而ValueMember = id将在数据库中的引用表中使用。但这不是您的情况。

这里有一个要在下拉列表中显示的字符串列表,因此您无需设置它们。 正如here

所写
  

如果DataSource属性设置为字符串数组,则为ValueMember   因为每个字符串都不需要设置和DisplayMember   数组将用于值和显示。