DataGridView doesn't update Enum in BindingLis

2019-08-08 21:14发布

问题:

The DataSource of my DataGridView is a BindingList<Filter> which contains an enum. The gridview contains only two columns: a regular textbox column for a string, and a combobox (drop down) column for the enum. If I bind the combobox column to the enum variable of my object I get an error. Here is the code for my objects:

public class FilterProfile
{
   public FilterProfile()
   {
      filters = new BindingList<Filter>();  // the list that gets bound to gridview
   }
   public string name { get; set; }
   public BindingList<Filter> filters { get; set; }
}

public class Filter
{
  public string keyword { get; set; }
  public FilterType type { get; set; }  // the enum in question
}

public enum FilterType : int
{
  SESSION = 1,
  ORDER = 2,
  SHIPMENT = 3
}

I have a form where the user selects a FilterProfile from a dropdown menu and then I find the appropriate FilterProfile from a global list and bind it:

foreach (PlvFilterProfile filterProfile in _filterProfiles)
     {  
        // find the correct filter profile
        if (filterProfile.name.Equals(lstFilterProfiles.Text))
        {
           // bind it
           grdFilters.DataSource = filterProfile.filters;
           break;
        }
     }

In order for the changes made in the DataGridView to be reflected in filterProfile.filters I need to set the DataPropertyName attribute of both columns to their respective variable (either keyword or type). This works correctly for the keyword string, but not with the type enum.

If I keep the line colFilterType.DataPropertyName = "type"; I get the error below whenever a new row is created or whenever I put my mouse over the dropdown. If I get rid of it, the type of every newly created Filter is set to 0 and never updated.

I'm not sure what causes the DataError event so don't know how to handle it or where to breakpoint.

回答1:

The problem is when you focus on the new row (prepare to add a new row), a new object is required in the underlying list, this object is default by null, that value is bound to the new row and of course the ComboBoxCell can't accept that null value, causing the exception as you encountered. The solution is very simple indeed, we just need to handle the event AddingNew of the BindingList, set the default new object in there to a valid value and then it works just fine:

public FilterProfile()
{
  filters = new BindingList<Filter>();  // the list that gets bound to gridview
  filters.AddingNew += (s,e) => {
    //the default value of FilterType is up to you.
    e.NewObject = new Filter {type = FilterType.SESSION };
  };
}