Crash in WPF DataGrid when EditTriggers contains CellIsCurrent and removing an item

Crash in WPF DataGrid when EditTriggers contains CellIsCurrent and removing an item

Recently we upgraded our Xceed packages from 7.1.22553.1044 to 7.2.24171.1009 and we've noticed a couple changes in behavior.

First is that the grid no longer allows removing something from the view when the row is being edited. It now throws an error "An attempt was made to remove an item while an item is being edited or added." Was this an intentional change? I was able to get around it by checking IsEditingItem and then calling CancelEdit() before the remove.

The second, I believe, is a bug. Attached is a simple example project that repeats the issue. When you run the program you should see a grid with three entries and a "Remove" button at the top.
  1. The "Low" item will be selected by default
  2. Click Remove and notice it is deleted with no issue
  3. Click on any cell in the "Medium" row so that editing is triggered
  4. Click Remove
  5. The program bombs with the message "An attempt was made to change the selection while a selection-change process is already in progress."
I was able to step into your code (that VS decompiled) and determine what is happening. On the initial remove there is nothing currently selected in the grid and the remove works. However, once I click on a cell then in your code there is a currentContext.CurrentColumn in your code that is now set. When I call Remove and your code attempts to SetCurrent, it selects the row, then finds the current column in the newly current row, then it checks the EditTriggers and sees that CellIsCurrent is set, then it tries to put things in edit mode and that leads it down a path to the error. 

If I remove CellIsCurrent from my DataGrid.EditTriggers then the crash goes away. I believe this is a bug, but let me know if there is something wrong with my sample project that is producing the issue.

Specifically it seems like this changed in version 7.2.23519.141, because prior to that it works, after that it bombs.

If you remove the CellIsCurrent from MainWindow.xaml the issue goes away:


Here is the full exception detail for your reference, though it should be easy to repeat with my code.

System.InvalidOperationException
  HResult=0x80131509
  Message=An attempt was made to change the selection while a selection-change process is already in progress.
  Source=Xceed.Wpf.DataGrid
  StackTrace:
   at Xceed.Wpf.DataGrid.SelectionManager.Begin() in Xceed.Wpf.DataGrid\SelectionManager.cs:line 87
   at Xceed.Wpf.DataGrid.SelectionManager.UpdateSelectionAfterSourceCollectionChanged(DataGridContext dataGridContext, NotifyCollectionChangedEventArgs e) in Xceed.Wpf.DataGrid\SelectionManager.cs:line 390
   at Xceed.Wpf.DataGrid.DataGridContext.UpdateSelectionAfterSourceCollectionChanged(NotifyCollectionChangedEventArgs e) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 1291
   at Xceed.Wpf.DataGrid.DataGridContext.DeferSelectionChangedOnItemsCollectionChangedDisposable.Dispose(Boolean disposing) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 116
   at Xceed.Wpf.DataGrid.DataGridContext.DeferSelectionChangedOnItemsCollectionChangedDisposable.Dispose() in Xceed.Wpf.DataGrid\DataGridContext.cs:line 100
   at Xceed.Wpf.DataGrid.DataGridContext.OnReceiveWeakEvent(Type managerType, Object sender, EventArgs e) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 3527
   at Xceed.Wpf.DataGrid.DataGridContext.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 3461
   at System.Windows.WeakEventManager.ListenerList.DeliverEvent(Listener& listener, Object sender, EventArgs args, Type managerType) in System.Windows\WeakEventManager.cs:line 259
   at System.Windows.WeakEventManager.ListenerList.DeliverEvent(Object sender, EventArgs args, Type managerType) in System.Windows\WeakEventManager.cs:line 242
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) in System.Windows\WeakEventManager.cs:line 617
   at Xceed.Wpf.DataGrid.PostBatchCollectionChangedEventManager.OnEventRaised(Object sender, EventArgs e) in Xceed.Wpf.DataGrid\PostBatchCollectionChangedEventManager.cs:line 49
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.RaisePostBatchCollectionChanged() in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 1912
   at Xceed.Wpf.DataGrid.DeferredOperationManager.Process(Boolean processAll) in Xceed.Wpf.DataGrid\DeferredOperationManager.cs:line 456
   at Xceed.Wpf.DataGrid.DeferredOperationManager.Process() in Xceed.Wpf.DataGrid\DeferredOperationManager.cs:line 291
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.DeferRefreshHelper.ProcessDispose(DataGridCollectionViewBase collectionView) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 86
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.DeferRefreshHelper.Dispose(Boolean disposing) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 64
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.DeferRefreshHelper.System.IDisposable.Dispose() in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 53
   at System.Windows.Controls.ItemCollection.EndDefer()
   at System.Windows.Controls.ItemCollection.DeferHelper.Dispose()
   at Xceed.Wpf.DataGrid.Row.EndEdit() in Xceed.Wpf.DataGrid\Row.cs:line 2219
   at Xceed.Wpf.DataGrid.DataGridContext.SetCurrent(Object item, Row containerRow, Nullable`1 sourceDataItemIndex, ColumnBase column, Boolean forceFocus, Boolean isCancelable, Boolean synchronizeSelectionWithCurrent, AutoScrollCurrentItemSourceTriggers trigger) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 2098
   at Xceed.Wpf.DataGrid.SelectionManager.UpdateCurrentToSelection() in Xceed.Wpf.DataGrid\SelectionManager.cs:line 1290
   at Xceed.Wpf.DataGrid.SelectionManager.End(Boolean allowCancelingOfSelection, Boolean allowSynchronizeSelectionWithCurrent, Boolean isClearing) in Xceed.Wpf.DataGrid\SelectionManager.cs:line 131
   at Xceed.Wpf.DataGrid.SelectionManager.UpdateSelectionAfterSourceCollectionChanged(DataGridContext dataGridContext, NotifyCollectionChangedEventArgs e) in Xceed.Wpf.DataGrid\SelectionManager.cs:line 480
   at Xceed.Wpf.DataGrid.DataGridContext.UpdateSelectionAfterSourceCollectionChanged(NotifyCollectionChangedEventArgs e) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 1291
   at Xceed.Wpf.DataGrid.DataGridContext.Items_CollectionChanged(Object sender, NotifyCollectionChangedEventArgs e) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 1277
   at Xceed.Wpf.DataGrid.DataGridContext.OnReceiveWeakEvent(Type managerType, Object sender, EventArgs e) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 3472
   at Xceed.Wpf.DataGrid.DataGridContext.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) in Xceed.Wpf.DataGrid\DataGridContext.cs:line 3461
   at System.Windows.WeakEventManager.ListenerList.DeliverEvent(Listener& listener, Object sender, EventArgs args, Type managerType) in System.Windows\WeakEventManager.cs:line 259
   at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType) in System.Windows\WeakEventManager.cs:line 376
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) in System.Windows\WeakEventManager.cs:line 617
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) in System.Collections.Specialized\CollectionChangedEventManager.cs:line 104
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.ItemCollection.OnViewCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType) in System.Windows\WeakEventManager.cs:line 372
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) in System.Windows\WeakEventManager.cs:line 617
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) in System.Collections.Specialized\CollectionChangedEventManager.cs:line 104
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.OnCollectionChanged(NotifyCollectionChangedEventArgs args) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 2004
   at Xceed.Wpf.DataGrid.DataGridCollectionView.RemoveRawItemInGroup(RawItem rawItem) in Xceed.Wpf.DataGrid\DataGridCollectionView.cs:line 1820
   at Xceed.Wpf.DataGrid.DataGridCollectionView.RemoveSourceItem(Int32 startIndex, Int32 count) in Xceed.Wpf.DataGrid\DataGridCollectionView.cs:line 1174
   at Xceed.Wpf.DataGrid.DataGridCollectionView.ExecuteSourceItemOperation(DeferredOperation deferredOperation, Boolean& refreshForced) in Xceed.Wpf.DataGrid\DataGridCollectionView.cs:line 868
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.ExecuteOrQueueSourceItemOperation(DeferredOperation deferredOperation) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 1975
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.OnItemsSourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 981
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.OnReceiveWeakEvent(Type managerType, Object sender, EventArgs e) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 2363
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 2341
   at System.Windows.WeakEventManager.ListenerList.DeliverEvent(Listener& listener, Object sender, EventArgs args, Type managerType) in System.Windows\WeakEventManager.cs:line 259
   at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType) in System.Windows\WeakEventManager.cs:line 376
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) in System.Windows\WeakEventManager.cs:line 617
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) in System.Collections.Specialized\CollectionChangedEventManager.cs:line 104
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e) in f:\dd\NDP\fx\src\compmod\system\collections\objectmodel\observablecollection.cs:line 286
   at System.Collections.ObjectModel.ObservableCollection`1.RemoveItem(Int32 index) in f:\dd\NDP\fx\src\compmod\system\collections\objectmodel\observablecollection.cs:line 203
   at System.Collections.ObjectModel.Collection`1.RemoveAt(Int32 index)
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.InternalRemoveAt(Int32 sourceIndex) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 1570
   at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.Remove(Object item) in Xceed.Wpf.DataGrid\DataGridCollectionViewBase.cs:line 2800
   at XceedRemoteItemIssue.MainViewModel.RemoveThreshold() in C:\Users\JamesPike\Downloads\XceedRemoteItemIssue\MainViewModel.cs:line 59
   at Xceed.Wpf.DataGrid.ThemePack.Common.RelayCommand.<>c__DisplayClass7_0.<.ctor>b__0(Object p)
   at Xceed.Wpf.DataGrid.ThemePack.Common.RelayCommand.Execute(Object parameter)
   at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) in MS.Win32\HwndWrapper.cs:line 221
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) in MS.Win32\HwndSubclass.cs:line 253
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) in System.Windows.Threading\ExceptionWrapper.cs:line 73
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) in System.Windows.Threading\ExceptionWrapper.cs:line 24
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) in System.Windows.Threading\Dispatcher.cs:line 1021
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) in MS.Win32\HwndSubclass.cs:line 207
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) in System.Windows.Threading\Dispatcher.cs:line 1329
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) in System.Windows.Threading\Dispatcher.cs:line 484
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at XceedRemoteItemIssue.App.Main()