Suma
Suma

Reputation: 34463

Editable DataGridView bound to a List

I have a DataGridView bound to a list. The values show fine, when I click on a value, it starts editing, however when I press Enter, the change is ignored, no data are ever changed. When I place a breakpoint in the Value setter, I can see it is executed after the edit, but no changed data are ever shown. My binding code looks like this:

namespace DataGridViewList
{
  public partial class Form1 : Form
  {
    public struct LocationEdit
    {
      public string Key { get; set; }
      private string _value;
      public string Value { get { return _value; } set { _value = value; } }
    };

    public Form1()
    {
      InitializeComponent();
      BindingList<LocationEdit> list = new BindingList<LocationEdit>();
      list.Add(new LocationEdit { Key = "0", Value = "Home" });
      list.Add(new LocationEdit { Key = "1", Value = "Work" });
      dataGridView1.DataSource = list;
    }
  }
}

The project is a basic Windows Forms project, with a DataGrid created in a designer, with columns called Key and Value and set DataPropertyName to Key / Value respectively. No values are set to Read Only.

Is there some step I am missing? Do I need to implement INotifyPropertyChanged, or something else?

Upvotes: 4

Views: 7646

Answers (1)

King King
King King

Reputation: 63387

The problem is your are using a struct as the BindingList item type. The solution is you should change struct to class and it works GREAT. However if you want to keep using struct, I have an idea to make it works, of course it requires more code than simply changing struct to class. The whole idea is every time a cell has its value changed, the underlying item (which is a struct) should be assigned to a totally new struct item. That's the only way you can use to change the underlying value, otherwise the cell value after committing change won't be changed. I've found that the event CellParsing is the one suitable for this case to add custom code, and here is my code:

namespace DataGridViewList
{
   public partial class Form1 : Form
   {
     public struct LocationEdit
     {
       public string Key { get; set; }
       private string _value;
       public string Value { get { return _value; } set { _value = value; } }
     };

     public Form1()
     {
       InitializeComponent();
       BindingList<LocationEdit> list = new BindingList<LocationEdit>();
       list.Add(new LocationEdit { Key = "0", Value = "Home" });
       list.Add(new LocationEdit { Key = "1", Value = "Work" });
       dataGridView1.DataSource = list;
     }
     //CellParsing event handler for dataGridView1
     private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e){
        LocationEdit current = ((BindingList<LocationEdit>)dataGridView1.DataSource)[e.RowIndex];
        string key = current.Key;
        string value = current.Value;
        string cellValue = e.Value.ToString()
        if (e.ColumnIndex == 0) key = cellValue;
        else value = cellValue;
        ((BindingList<LocationEdit>)dataGridView1.DataSource)[e.RowIndex] = new LocationEdit {Key = key, Value = value};
     }
   }
}

I don't think it's a good idea to keep using struct that way, class would be better.

Upvotes: 4

Related Questions