title: How do I bind a DataGridViewComboBoxColumn to a property/method of an object that returns a list?
body: <p>I have a custom object with several properties, one of which returns a list. This is the code for the object:</p>
  
  <pre><code>public class SearchResult
  {
      private int eventId;
      private String eventTitle;
      private int startDate;
      private List&lt;String&gt; 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&lt;String&gt; Tags { get { return this.tags; } }
  
      public SearchResult(int eventId, String eventTitle, int startDate, List&lt;String&gt; tags)
      {
          // Constructor code
      }
  
      public List&lt;String&gt; GetTags()
      {
          return this.tags;
      }
  }
  </code></pre>
  
  <p>I also have a <code>DataGridViewComboBoxColumn</code> that I want to bind to the <code>Tags</code> property. Basically, each <code>SearchResult</code> object will be displayed in its own row, and I want the <code>List&lt;String&gt;</code> in the <code>Tags</code> property of each object to be displayed in a <code>ComboBox</code> cell in that row. This is the code I have so far for my <code>DataGridView</code>:</p>
  
  <pre><code>BindingList&lt;SearchResult&gt; results = new BindingList&lt;SearchResult&gt;();
  results.Add(new SearchResult(1, "This is a title", 2012, new List&lt;String&gt; { "Tag1", "Tag with a long name1" }));
  results.Add(new SearchResult(2, "The quick brown fox", 2012, new List&lt;String&gt; { "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&lt;String&gt; { "NYSE", "FTSE" }));
  results.Add(new SearchResult(4, "another long piece of title text", -999, new List&lt;String&gt; { "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;
  </code></pre>
  
  <p>I derived this code from <a href="http://www.switchonthecode.com/tutorials/csharp-tutorial-binding-a-datagridview-to-a-collection" rel="nofollow noreferrer">a tutorial I found online</a>, and it works perfectly. </p>
  
  <p>I've been trying to bind the <code>Tags</code> property of <code>SearchResult</code> to a <code>DataGridViewComboBoxColumn</code>, but I'm not sure how. I've been looking at <a href="https://stackoverflow.com/questions/631126/how-to-bound-a-datagridviewcomboboxcolumn-to-a-object">this question</a>, which provides this code:</p>
  
  <pre><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;
  </code></pre>
  
  <p>The reason I'm having trouble is because of a few nuances of the linked question that I don't understand.</p>
  
  <ol>
  <li>According to <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcomboboxcolumn.displaymember.aspx" rel="nofollow noreferrer">the documentation</a> and the linked question, <code>DisplayMember</code> should be linked to the property that "contains a description of the instance", but since <code>SearchResult</code> objects are added dynamically and don't have any description associated with them, should I just leave it blank?</li>
  <li><code>ValueMember</code> is giving me similar problems, since I'm unsure what to put even after reading <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcomboboxcolumn.valuemember.aspx" rel="nofollow noreferrer">its documentation</a>. </li>
  <li>In the linked question, the accepted answer binds the entire datagrid at once using 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.</li>
  </ol>
  
  <p>:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>I also presume I should have a line that sets the <code>DataSource</code> for the column, e.g.</p>
  
  <pre><code>tagsColumn.DataSource = &lt;some LINQ query, perhaps?&gt;
  </code></pre>
  
  <p>but I don't know because the only mostly relevant C# source I've been able to find is that question. </p>
  
  <h1>UPDATE:</h1>
  
  <p>I did find <a href="https://stackoverflow.com/questions/1390462/datagridviewcomboboxcolumn-name-value-how">a second question</a> that suggests code similar to this for data binding:</p>
  
  <pre><code>// 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
  </code></pre>
  
  <p>Based on that, I a) added the <code>GetTags()</code> method to <code>SearchResult</code> and added this code into my <code>DataGridView</code> initialisation code:</p>
  
  <pre><code>        DataGridViewComboBoxColumn tagsColumn = new DataGridViewComboBoxColumn();
          tagsColumn.DataSource = SearchResult.GetTags(); // ERROR 
          tagsColumn.DisplayMember = ""; // Still not sure
          tagsColumn.ValueMember = ""; // ??
  </code></pre>
  
  <p>However, Visual Studio gives me an error on the second line when I try to run this:</p>
  
  <pre><code>An object reference is required for the non-static field, method, or property 'SearchResult.GetTags()'
  </code></pre>
  
  <h1>UPDATE 2:</h1>
  
  <p>I'm still searching around for this without success. I don't understand how with other properties (e.g. <code>EventId</code>) I can simply declare the data property name as <code>EventId</code>, and it will display in the table, but I cannot do this with <code>ComboBox</code> columns. </p>
  
  <p>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 <code>Tags</code> property to the <code>ComboBox</code> column for each instance, when <em>I don't need to loop through the list of <code>SearchResult</code> objects to bind other properties, e.g. <code>EventId</code></em>.</p>
  
  <p>Why does this binding-properties-by-name only work for <em>some</em> properties and not others?</p>