简体   繁体   English

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

[英]How do I bind a DataGridViewComboBoxColumn to a property/method of an object that returns a list?

I have a custom object with several properties, one of which returns a list. 我有一个具有多个属性的自定义对象,其中一个属性返回一个列表。 This is the code for the object: 这是对象的代码:

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

I also have a DataGridViewComboBoxColumn that I want to bind to the Tags property. 我还有一个DataGridViewComboBoxColumn ,我想绑定到Tags属性。 Basically, each SearchResult object will be displayed in its own row, and I want the List<String> in the Tags property of each object to be displayed in a ComboBox cell in that row. 基本上,每个SearchResult对象都将显示在它自己的行中,我希望每个对象的Tags属性中的List<String>显示在该行的ComboBox单元格中。 This is the code I have so far for my DataGridView : 这是我到目前为止我的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;

I derived this code from a tutorial I found online , and it works perfectly. 我从在线发现的教程中导出了这个代码,它运行得很好。

I've been trying to bind the Tags property of SearchResult to a DataGridViewComboBoxColumn , but I'm not sure how. 我一直在尝试将SearchResultTags属性绑定到DataGridViewComboBoxColumn ,但我不确定如何。 I've been looking at this question , which provides this code: 我一直在看这个问题 ,它提供了这个代码:

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;

The reason I'm having trouble is because of a few nuances of the linked question that I don't understand. 我遇到麻烦的原因是由于我不理解的链接问题的一些细微差别。

  1. According to the documentation and the linked question, DisplayMember should be linked to the property that "contains a description of the instance", but since SearchResult objects are added dynamically and don't have any description associated with them, should I just leave it blank? 根据文档和链接的问题, DisplayMember应链接到“包含实例描述”的属性,但由于SearchResult对象是动态添加的,并且没有任何与之关联的描述,我应该将其留空?
  2. ValueMember is giving me similar problems, since I'm unsure what to put even after reading its documentation . ValueMember给了我类似的问题,因为我不确定即使在阅读其文档后还要放什么。
  3. In the linked question, the accepted answer binds the entire datagrid at once using LINQ. 在链接的问题中,接受的答案使用LINQ立即绑定整个数据网格。 Is that how I should be doing this? 我应该这样做吗? I'm not sure how to modify that code for my situation, but I thought it would be something along these lines. 我不知道如何根据我的情况修改代码,但我认为这将是这些问题。

:

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

I also presume I should have a line that sets the DataSource for the column, eg 我还假设我应该有一行为列设置DataSource ,例如

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

but I don't know because the only mostly relevant C# source I've been able to find is that question. 但我不知道,因为我能找到的唯一最相关的C#源是那个问题。

UPDATE: 更新:

I did find a second question that suggests code similar to this for data binding: 我确实找到了第二个问题 ,建议与数据绑定类似的代码:

// 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

Based on that, I a) added the GetTags() method to SearchResult and added this code into my DataGridView initialisation code: 基于此,我a)将GetTags()方法添加到SearchResult并将此代码添加到我的DataGridView初始化代码中:

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

However, Visual Studio gives me an error on the second line when I try to run this: 但是,当我尝试运行它时,Visual Studio在第二行给出了一个错误:

An object reference is required for the non-static field, method, or property 'SearchResult.GetTags()'

UPDATE 2: 更新2:

I'm still searching around for this without success. 我仍在寻找这个没有成功的事情。 I don't understand how with other properties (eg EventId ) I can simply declare the data property name as EventId , and it will display in the table, but I cannot do this with ComboBox columns. 我不明白如何与其他属性(例如EventId )我可以简单地将数据属性名称声明为EventId ,它将显示在表中,但我无法使用ComboBox列。

Since the objects are instantiated in a separate class and put in a list, it doesn't seem to make sense to me that I should have to loop through the entire array of objects (of which there may be several hundred) to bind the Tags property to the ComboBox column for each instance, when I don't need to loop through the list of SearchResult objects to bind other properties, eg EventId . 由于对象是在一个单独的类中实例化并放入一个列表中,因此对我来说似乎没有意义我应该遍历整个对象数组(其中可能有几百个)来绑定Tags每个实例的ComboBox列的属性,当我不需要遍历SearchResult对象列表来绑定其他属性时,例如EventId

Why does this binding-properties-by-name only work for some properties and not others? 为什么这个按名称绑定的属性仅适用于某些属性而不适用于其他属性?

I don't quite understand why you want to use DataGridViewComboBoxColumn to display a list of elements. 我不太明白为什么要使用DataGridViewComboBoxColumn来显示元素列表。 This column kind is designed to allow user to select one of many possibilities. 此列类型旨在允许用户选择多种可能性之一。 It seams it is not your case because you don't have public string SelectedTag{get;set;} property to store it. 它接缝不是你的情况,因为你没有public string SelectedTag{get;set;}属性来存储它。 As I understand your model you have many tags already selected for your SearchResult and you want to display them in grid. 据我了解您的模型,您已经为SearchResult选择了许多标签,并且您希望将它们显示在网格中。

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

Getting or setting this [ DataSource ] property gets or sets the DataSource property of the object returned by the CellTemplate property. 获取或设置此[ DataSource ]属性可获取或设置CellTemplate属性返回的对象的DataSource属性。 Setting this property also sets the DataSource property of every cell in the column and refreshes the column display. 设置此属性还会设置列中每个单元格的DataSource属性并刷新列显示。 To override the specified value for individual cells, set the cell values after you set the column value. 要覆盖单个单元格的指定值,请在设置列值后设置单元格值。

DataGridViewComboBoxColumn simply does not have capability to bind items property to data source because it assumes that there is only one list of elements that is used as data source for all rows of data grid. DataGridViewComboBoxColumn根本无法将items属性绑定到数据源,因为它假定只有一个元素列表用作所有数据网格行的数据源。

I also assume that you would set ReadOnly = true property for this column as you have for all other. 我还假设您将为此列设置ReadOnly = true属性,就像您拥有所有其他属性一样。 If so it would prevent user form seeing list of tags because drop down list would never be displayed. 如果是这样,它将阻止用户表单查看标签列表,因为永远不会显示下拉列表。

If you wand to display list of strings in read only mode I would suggest to flatten this list of tags to single string: 如果您想以只读模式显示字符串列表,我建议将此标记列表展平为单个字符串:

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

and display it in text column. 并将其显示在文本列中。

For the error , i can suggest you to make an instance of the class and then call the method as its not static or you can make your method static. 对于错误,我可以建议您创建类的实例,然后将该方法称为非静态方法,或者可以使方法保持静态。

Moreover As you needs the comboboxcolumn , 此外,您需要组合柱,

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

Mostly we have dropdowns for objects like Country(id,name) so DisplayMember = name will be shown as text in dropdown while ValueMember = id will be used in the referencing tables in database.But this is not your case. 大多数情况下,我们有像Country(id,name)这样的对象的下拉列表,因此DisplayMember = name将在下拉列表中显示为文本,而ValueMember = id将在数据库中的引用表中使用。但这不是您的情况。

Here you have a list of strings to show in dropdown , so you don't need to set them. 这里有一个要在下拉列表中显示的字符串列表,因此您无需设置它们。 As written here 正如这里所写

If the DataSource property is set to a string array, then ValueMember and DisplayMember do not need to be set because each string in the array will be used for both value and display. 如果将DataSource属性设置为字符串数组,则不需要设置ValueMember和DisplayMember,因为数组中的每个字符串都将用于值和显示。

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

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