Multi row edit in Eto GridView

Hello,
I’m finding some troubles with editing multiple selected rows of an Eto GridView in one go.

The setup

I’m using a binding with a proper data model, like so:

internal class DataModel : INotifyPropertyChanged
{
  private string m_myProperty;

  public event PropertyChangedEventHandler PropertyChanged;

  public string MyProperty
  {
    get {
      return m_myProperty;
    }
    set {
      m_size = value;
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProperty)));
    }
  }

  public DataModel(string value)
  {
    m_myProperty = value;
  }
}

I’m creating a column with

m_dataGrid.Columns.Add(new GridColumn() {
  DataCell = new TextBoxCell("MyProperty"),
  HeaderText = I18n.Tr("MyProperty"),
  Editable = true,
  Resizable = false,
  Sortable = false,
  AutoSize = true
});

and finally setting the m_dataGrid.DataStore with an ObservableCollection<DataModel> object.

What I want to achieve

When multiple rows are selected, I want to change a cell value and apply the same value to all other selected cells.

I tried to subscribe the GridView’s OnCellEdited, obtaining the modified value and setting the same value on the DataStored items corresponding to the selected rows indices, but the change is not reflected in the grid.

I thought a ReloadData() method should be invoked on the GridView, but invoking that inside the OnCellEdited method raises an exception (Refresh not allowed during an AddNew or EditItem transaction), which basically states that (despite the OnCellEditED method name suggests), the editing is not finished yet.

Maybe there is a simpler and smarter solution that I don’t see, to achieve the same result.
Any suggestions?

1 Like

@curtisw can you please provide some advice? Thank you :slight_smile:

A simple solution would be to just invoke asynchronously the ReloadData() method. E.g.

Application.Instance.AsyncInvoke(() => myGrid.ReloadData());

Alternatively, trigger a INotifyCollectionChanged.CollectionChanged event on your collection for the modified row(s). This would require subclassing ObservableCollection<T>.

Hope this helps!

Thanks @curtisw

Actually the AsyncInvoke() causes the application to raise the same exception.
I also tried to subclass ObservableCollection<T> and trigger the CollectionChanged for the modified rows but the grid did not refresh nonetheless.

Strangely, I managed to obtain the result I wanted with a hack, which I don’t know if it’s “licit”, that is re-setting the DataStore on the grid in a brutal way, every time a cell is edited and I update other items of the collection:

private void OnCellEdited(object sender, GridViewCellEventArgs e) {
  var ds = m_dataGrid.DataStore;

  // Do stuff with edited value and update 
  // other DataStore items corresponding to selected rows...

  // Hack!
  m_dataGrid.DataStore = null;
  m_dataGrid.DataStore = ds;
}