Wednesday, August 12, 2015

'Sorting' is not allowed during an AddNew or EditItem transaction

Recently I resolved one WPF GUI bug related with the exception:
'Sorting' is not allowed during an AddNew or EditItem transaction.

This stackoverflow discussion has the correct answer to my issue, but it isn't marked as the answer for now.  So I would like to list it here and explain a bit, and hope this can help somebody out.

Background

We had a datagrid in a customized control, which is used to select files.  The control
has a ViewModel class as its DataContext and can load different ViewModel classes.  The control itself will stay in memory, but the ViewModel will get disposed every time the view is closed.  

It works fine most of the time.  However, if users sort the datagrid by clicking a column header and then select a file by double click, and next time when the view is opened, the exception:
'Sorting' is not allowed during an AddNew or EditItem transaction.
will be thrown.

I checked the stack trace of the exception and saw the exception came from System.Windows.Data.ListCollectionView.SortDescriptionsChanged().  When using ILSpy to check ListCollectionView class, we can see this code in
SortDescriptionsChanged()
            if (this.IsAddingNew || this.IsEditingItem)
            {
                throw new InvalidOperationException(Resx.GetString("CollectionView_MemberNotAllowedDuringAddOrEdit", new object[]
                {
                    "Sorting"
                }));
            }
 

Solutions

ptsivakumar listed 2 solutions which both are good in my case.  I listed the solutions here in case that thread is not accessable.

1)  Add CommitNew() and CommitEdit()
This should be put in a proper place suitable for your specific case.  In my case, I put it in the view Close event handler:

            var dataView = (ListCollectionView)CollectionViewSource.GetDefaultView(DataGrid_Files.ItemsSource);
            if (dataView.IsEditingItem)
                dataView.CommitEdit();
            if (dataView.IsAddingNew)
                dataView.CommitNew();

2)  Add IsReadOnly="True" to the datagrid control, also remember to add CanUserAddRows="False"


Both solutions are working well.  The reason is when the datagrid is double clicked, it will enter the edit mode, but the sorting feature doesn't allow the datagrid in Adding New or Editing mode when a sorting event happens.  So the first solution will commit changes and bring the datagrid to a normal mode.  The second solution works because the settings will keep the datagrid always in a normal mode.  Double click is ignored.