This issue has been moved from a ticket on Developer Community.
When changing a field in a DataGrid that is of type DataGridComboBoxColumn, and then changing focus, an ArgumentOutOfRange exception is thrown from within WPF.
This only occurs with .NET Framework 4.8. Using an earlier version of the framework, no exception is thrown.
To reproduce:
- Load the attached project into Visual Studio 2017 or later.
- Ensure you have .NET Framework 4.8 installed.
- Start the sample application.
- In the drop-down for "First Status" for "Widget 1", select "Disabled".
- Move focus off the combo box by clicking on the "Second Status" column of "Widget 2".
- The exception is thrown.
I think the problem is related to the fact that when the FirstStatus property is changed on Widget1, we make a call to Reload in the WidgetsVM, which rebuilds the Widgets collection (which is the collection the DataGrid is bound to). Doing this looks like it might be invalidating something WPF was holding on to, so that when it tries to find the object again, it gets a negative index, and the exception is thrown.
Is it legal to rebuild the collection a DataGrid is bound to during an update? The only two options I can currently think of are:
- This is a bug introduced in .NET Framework 4.8
- We were relying on undefined behaviour before that just happened to work, and some change in .NET Framework 4.8 has meant this is no longer works.
Any feedback would be greatly appreciated, as this issue is causing just about all versions of our product to crash for customers who have installed .NET Framework 4.8 (either specifically or as part of Windows 1903).
Note that we are using this "DataContextSpy" approach as our original code was written before .NET Framework 4.0 was released, when the DataGrid was not a type of FrameworkElement.
wpfapp1.zip
The call stack at the point of the exception is:
> mscorlib.dll!System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument argument, System.ExceptionResource resource) Unknown
mscorlib.dll!System.Collections.Generic.List<System.Windows.Data.BindingExpressionBase>.this[int].get(int index) Unknown
PresentationFramework.dll!System.Windows.Data.BindingGroup.UpdateValues() Unknown
PresentationFramework.dll!System.Windows.Data.BindingGroup.UpdateAndValidate(System.Windows.Controls.ValidationStep validationStep) Unknown
PresentationFramework.dll!System.Windows.Data.BindingGroup.CommitEdit() Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.OnExecutedCommitEdit(System.Windows.Input.ExecutedRoutedEventArgs e) Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.OnExecutedCommitEdit(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown
PresentationCore.dll!System.Windows.Input.CommandBinding.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown
PresentationCore.dll!System.Windows.Input.CommandManager.ExecuteCommandBinding(object sender, System.Windows.Input.ExecutedRoutedEventArgs e, System.Windows.Input.CommandBinding commandBinding) Unknown
PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute) Unknown
PresentationCore.dll!System.Windows.Input.CommandManager.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown
PresentationCore.dll!System.Windows.UIElement.OnExecutedThunk(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown
PresentationCore.dll!System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(System.Delegate genericHandler, object target) Unknown
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown
PresentationCore.dll!System.Windows.Input.RoutedCommand.ExecuteImpl(object parameter, System.Windows.IInputElement target, bool userInitiated) Unknown
PresentationCore.dll!System.Windows.Input.RoutedCommand.Execute(object parameter, System.Windows.IInputElement target) Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.EndEdit(System.Windows.Input.RoutedCommand command, System.Windows.Controls.DataGridCell cellContainer, System.Windows.Controls.DataGridEditingUnit editingUnit, bool exitEditMode) Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.OnCurrentCellChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e) Unknown
WindowsBase.dll!System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown
WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args) Unknown
WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown
WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) Unknown
WindowsBase.dll!System.Windows.DependencyObject.SetCurrentValueInternal(System.Windows.DependencyProperty dp, object value) Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.CurrentCellContainer.set(System.Windows.Controls.DataGridCell value) Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.FocusedCell.set(System.Windows.Controls.DataGridCell value) Unknown
PresentationFramework.dll!System.Windows.Controls.DataGridCell.OnAnyGotFocus(object sender, System.Windows.RoutedEventArgs e) Unknown
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.OnGotFocus(System.Windows.RoutedEventArgs e) Unknown
PresentationCore.dll!System.Windows.UIElement.IsFocused_Changed(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e) Unknown
WindowsBase.dll!System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown
WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args) Unknown
WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown
WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) Unknown
WindowsBase.dll!System.Windows.DependencyObject.SetValue(System.Windows.DependencyPropertyKey key, object value) Unknown
PresentationCore.dll!System.Windows.Input.FocusManager.OnFocusedElementChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e) Unknown
WindowsBase.dll!System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown
WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args) Unknown
WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown
WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) Unknown
PresentationCore.dll!System.Windows.Input.FocusManager.SetFocusedElement(System.Windows.DependencyObject element, System.Windows.IInputElement value) Unknown
PresentationFramework.dll!System.Windows.Input.KeyboardNavigation.UpdateFocusedElement(System.Windows.DependencyObject focusTarget) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.OnGotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e) Unknown
PresentationCore.dll!System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() Unknown
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) Unknown
PresentationCore.dll!System.Windows.Input.KeyboardDevice.ChangeFocus(System.Windows.DependencyObject focus, int timestamp) Unknown
PresentationCore.dll!System.Windows.Input.KeyboardDevice.TryChangeFocus(System.Windows.DependencyObject newFocus, System.Windows.Input.IKeyboardInputProvider keyboardInputProvider, bool askOld, bool askNew, bool forceToNullIfFailed) Unknown
PresentationCore.dll!System.Windows.Input.KeyboardDevice.Focus(System.Windows.DependencyObject focus, bool askOld, bool askNew, bool forceToNullIfFailed) Unknown
PresentationCore.dll!System.Windows.Input.KeyboardDevice.Focus(System.Windows.IInputElement element) Unknown
PresentationCore.dll!System.Windows.UIElement.Focus() Unknown
PresentationFramework.dll!System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) Unknown
PresentationFramework.dll!System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDownThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) Unknown
PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown
PresentationCore.dll!System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args, System.Windows.RoutedEvent newEvent) Unknown
PresentationCore.dll!System.Windows.UIElement.OnMouseDownThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) Unknown
PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) Unknown
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() Unknown
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) Unknown
PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) Unknown
PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) Unknown
PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, MS.Internal.Interop.WindowMessage msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown
PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Unknown
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Unknown
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) Unknown
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) Unknown
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) Unknown
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) Unknown
PresentationFramework.dll!System.Windows.Application.Run() Unknown
WpfApp1.exe!WpfApp1.App.Main() Unknown
Original Comments
Visual Studio Feedback System on 8/19/2019, 00:46 AM:
We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.
Sam Bent [MSFT] on 8/19/2019, 05:37 PM:
@Michael Priestman asked:
Is it legal to rebuild the collection a DataGrid is bound to during an update? The only two options I can currently think of are:
- This is a bug introduced in .NET Framework 4.8
- We were relying on undefined behaviour before that just happened to work, and some change in .NET Framework 4.8 has meant this is no longer works.
I'm afraid it's more complex. It's unclear what should happen when you rebuild the collection during an update. A row in a DataGrid typically displays several properties of the underlying data item, many of which might be "dirty" when you commit the row (e.g. by clicking in a different row). WPF updates the dirty properties one at a time, but if updating property A causes your app to replace the DataGrid's collection, what should happen to property B? Two possible answers (at least), both with about the same claim to correctness:
- Ignore the pending change to B. The DataGrid is no longer connected to the data item - it shouldn't make any more changes.
- Update property B (on the original data item). The DataGrid started to update the data item, and should finish the job before fully disconnecting.
It gets even weirder if an update encounters an error - failed validation rule, exception thrown by property-setter, etc. The departing data item could be left in a bad state with no opportunity for the user to fix it, or even know that it happened.
So the behavior is undefined, Your simple example (with only one dirty property) happened to work, but I suspect a more elaborate scenario with multiple dirty properties and errors in the pending values would send us into an endless discussion about what it even means for it to "work".
While WPF doesn't specify a behavior in this case, "crash" is not a helpful one, at least not without a message that helps you identify the problem. You were close about the cause of the crash. It turns out to involve the list of bindings corresponding to the columns. When commit a row, WPF iterates over this list to update any "dirty" properties. Updating one such property causes your app to rebuild the collection, which now (as of 4.8) removes all (or most) bindings from the list. When the iteration continues, it crashes. The iteration code anticipated that the current binding might get removed, but not all bindings. (This was changed in 4.8 to fix memory leaks and aliasing problems that arose from keeping bindings alive after the DataGridRow was disconnected from its data item.)
For .NETCore we'll consider fixing the iteration code to survive your re-entrant change. With no promises about the actual behavior, beyond "don't crash". If you need the crash fixed in .NET 4.8, you should work with CSS to get a servicing request opened; that will require some business justification. It's probably simpler to fix your app to avoid the re-entrant change. Your sample repro replaces the collection with another that contains identical items (or at least equivalent items), which seems unnecessary, but obviously I don't know what your real app does.
Michael Priestman on 8/20/2019, 04:57 AM:
Thanks for your very detailed reply. I had a feeling that rebuilding the entire collection might not be the cleverest idea. I don't know why it does it like this (I have only just inherited the source from some long-departed employees), but it feels like we should be able to fix it on the product side.
Sam Bent [MSFT] on 8/21/2019, 02:51 PM:
This is essentially the user’s bug. The app changes the DataGrid’s source collection re-entrantly, while the DataGrid is committing changes to one of its data items. This is not supported, nor can it be supported in any meaningful way (see my earlier comments).
Original Solutions
(no solutions)
This issue has been moved from a ticket on Developer Community.
When changing a field in a DataGrid that is of type DataGridComboBoxColumn, and then changing focus, an ArgumentOutOfRange exception is thrown from within WPF.
This only occurs with .NET Framework 4.8. Using an earlier version of the framework, no exception is thrown.
To reproduce:
I think the problem is related to the fact that when the FirstStatus property is changed on Widget1, we make a call to Reload in the WidgetsVM, which rebuilds the Widgets collection (which is the collection the DataGrid is bound to). Doing this looks like it might be invalidating something WPF was holding on to, so that when it tries to find the object again, it gets a negative index, and the exception is thrown.
Is it legal to rebuild the collection a DataGrid is bound to during an update? The only two options I can currently think of are:
Any feedback would be greatly appreciated, as this issue is causing just about all versions of our product to crash for customers who have installed .NET Framework 4.8 (either specifically or as part of Windows 1903).
Note that we are using this "DataContextSpy" approach as our original code was written before .NET Framework 4.0 was released, when the DataGrid was not a type of FrameworkElement.
wpfapp1.zip
The call stack at the point of the exception is:
> mscorlib.dll!System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument argument, System.ExceptionResource resource) Unknown mscorlib.dll!System.Collections.Generic.List<System.Windows.Data.BindingExpressionBase>.this[int].get(int index) Unknown PresentationFramework.dll!System.Windows.Data.BindingGroup.UpdateValues() Unknown PresentationFramework.dll!System.Windows.Data.BindingGroup.UpdateAndValidate(System.Windows.Controls.ValidationStep validationStep) Unknown PresentationFramework.dll!System.Windows.Data.BindingGroup.CommitEdit() Unknown PresentationFramework.dll!System.Windows.Controls.DataGrid.OnExecutedCommitEdit(System.Windows.Input.ExecutedRoutedEventArgs e) Unknown PresentationFramework.dll!System.Windows.Controls.DataGrid.OnExecutedCommitEdit(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.CommandBinding.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.CommandManager.ExecuteCommandBinding(object sender, System.Windows.Input.ExecutedRoutedEventArgs e, System.Windows.Input.CommandBinding commandBinding) Unknown PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute) Unknown PresentationCore.dll!System.Windows.Input.CommandManager.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown PresentationCore.dll!System.Windows.UIElement.OnExecutedThunk(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(System.Delegate genericHandler, object target) Unknown PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown PresentationCore.dll!System.Windows.Input.RoutedCommand.ExecuteImpl(object parameter, System.Windows.IInputElement target, bool userInitiated) Unknown PresentationCore.dll!System.Windows.Input.RoutedCommand.Execute(object parameter, System.Windows.IInputElement target) Unknown PresentationFramework.dll!System.Windows.Controls.DataGrid.EndEdit(System.Windows.Input.RoutedCommand command, System.Windows.Controls.DataGridCell cellContainer, System.Windows.Controls.DataGridEditingUnit editingUnit, bool exitEditMode) Unknown PresentationFramework.dll!System.Windows.Controls.DataGrid.OnCurrentCellChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e) Unknown WindowsBase.dll!System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args) Unknown WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) Unknown WindowsBase.dll!System.Windows.DependencyObject.SetCurrentValueInternal(System.Windows.DependencyProperty dp, object value) Unknown PresentationFramework.dll!System.Windows.Controls.DataGrid.CurrentCellContainer.set(System.Windows.Controls.DataGridCell value) Unknown PresentationFramework.dll!System.Windows.Controls.DataGrid.FocusedCell.set(System.Windows.Controls.DataGridCell value) Unknown PresentationFramework.dll!System.Windows.Controls.DataGridCell.OnAnyGotFocus(object sender, System.Windows.RoutedEventArgs e) Unknown PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e) Unknown PresentationFramework.dll!System.Windows.FrameworkElement.OnGotFocus(System.Windows.RoutedEventArgs e) Unknown PresentationCore.dll!System.Windows.UIElement.IsFocused_Changed(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e) Unknown WindowsBase.dll!System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args) Unknown WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) Unknown WindowsBase.dll!System.Windows.DependencyObject.SetValue(System.Windows.DependencyPropertyKey key, object value) Unknown PresentationCore.dll!System.Windows.Input.FocusManager.OnFocusedElementChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e) Unknown WindowsBase.dll!System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e) Unknown WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args) Unknown WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) Unknown WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal) Unknown PresentationCore.dll!System.Windows.Input.FocusManager.SetFocusedElement(System.Windows.DependencyObject element, System.Windows.IInputElement value) Unknown PresentationFramework.dll!System.Windows.Input.KeyboardNavigation.UpdateFocusedElement(System.Windows.DependencyObject focusTarget) Unknown PresentationFramework.dll!System.Windows.FrameworkElement.OnGotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() Unknown PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) Unknown PresentationCore.dll!System.Windows.Input.KeyboardDevice.ChangeFocus(System.Windows.DependencyObject focus, int timestamp) Unknown PresentationCore.dll!System.Windows.Input.KeyboardDevice.TryChangeFocus(System.Windows.DependencyObject newFocus, System.Windows.Input.IKeyboardInputProvider keyboardInputProvider, bool askOld, bool askNew, bool forceToNullIfFailed) Unknown PresentationCore.dll!System.Windows.Input.KeyboardDevice.Focus(System.Windows.DependencyObject focus, bool askOld, bool askNew, bool forceToNullIfFailed) Unknown PresentationCore.dll!System.Windows.Input.KeyboardDevice.Focus(System.Windows.IInputElement element) Unknown PresentationCore.dll!System.Windows.UIElement.Focus() Unknown PresentationFramework.dll!System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) Unknown PresentationFramework.dll!System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDownThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args, System.Windows.RoutedEvent newEvent) Unknown PresentationCore.dll!System.Windows.UIElement.OnMouseDownThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) Unknown PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) Unknown PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) Unknown PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) Unknown PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) Unknown PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) Unknown PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() Unknown PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) Unknown PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) Unknown PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) Unknown PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, MS.Internal.Interop.WindowMessage msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Unknown WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Unknown WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Unknown WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) Unknown WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Unknown WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Unknown [Native to Managed Transition] [Managed to Native Transition] WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Unknown WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) Unknown PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) Unknown PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) Unknown PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) Unknown PresentationFramework.dll!System.Windows.Application.Run() Unknown WpfApp1.exe!WpfApp1.App.Main() UnknownOriginal Comments
Visual Studio Feedback System on 8/19/2019, 00:46 AM:
We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.
Sam Bent [MSFT] on 8/19/2019, 05:37 PM:
@Michael Priestman asked:
Is it legal to rebuild the collection a DataGrid is bound to during an update? The only two options I can currently think of are:
I'm afraid it's more complex. It's unclear what should happen when you rebuild the collection during an update. A row in a DataGrid typically displays several properties of the underlying data item, many of which might be "dirty" when you commit the row (e.g. by clicking in a different row). WPF updates the dirty properties one at a time, but if updating property A causes your app to replace the DataGrid's collection, what should happen to property B? Two possible answers (at least), both with about the same claim to correctness:
It gets even weirder if an update encounters an error - failed validation rule, exception thrown by property-setter, etc. The departing data item could be left in a bad state with no opportunity for the user to fix it, or even know that it happened.
So the behavior is undefined, Your simple example (with only one dirty property) happened to work, but I suspect a more elaborate scenario with multiple dirty properties and errors in the pending values would send us into an endless discussion about what it even means for it to "work".
While WPF doesn't specify a behavior in this case, "crash" is not a helpful one, at least not without a message that helps you identify the problem. You were close about the cause of the crash. It turns out to involve the list of bindings corresponding to the columns. When commit a row, WPF iterates over this list to update any "dirty" properties. Updating one such property causes your app to rebuild the collection, which now (as of 4.8) removes all (or most) bindings from the list. When the iteration continues, it crashes. The iteration code anticipated that the current binding might get removed, but not all bindings. (This was changed in 4.8 to fix memory leaks and aliasing problems that arose from keeping bindings alive after the DataGridRow was disconnected from its data item.)
For .NETCore we'll consider fixing the iteration code to survive your re-entrant change. With no promises about the actual behavior, beyond "don't crash". If you need the crash fixed in .NET 4.8, you should work with CSS to get a servicing request opened; that will require some business justification. It's probably simpler to fix your app to avoid the re-entrant change. Your sample repro replaces the collection with another that contains identical items (or at least equivalent items), which seems unnecessary, but obviously I don't know what your real app does.
Michael Priestman on 8/20/2019, 04:57 AM:
Thanks for your very detailed reply. I had a feeling that rebuilding the entire collection might not be the cleverest idea. I don't know why it does it like this (I have only just inherited the source from some long-departed employees), but it feels like we should be able to fix it on the product side.
Sam Bent [MSFT] on 8/21/2019, 02:51 PM:
This is essentially the user’s bug. The app changes the DataGrid’s source collection re-entrantly, while the DataGrid is committing changes to one of its data items. This is not supported, nor can it be supported in any meaningful way (see my earlier comments).
Original Solutions
(no solutions)