question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Exception on DataGrid selection with a particular setup

See original GitHub issue

Problem description

Under a particular set of circumstances, selecting a cell in a DataGrid causes the application crash. The circumstances include

  1. adding data to the backing ObservableCollection<> of the DataGrid by
  2. triggering an ICommand bound to an element inside a MenuItem,
  3. the SelectedItem was null before this trigger, and
  4. the set by WPF to make (the binding of) SelectedItem not null is ignored.

Steps to reproduce

My minimal reproduction is available at TysonMN/ExceptionOnDataGridSelection.

  1. Run that reproduction
  2. Click the MenuItem
  3. Click the Button
  4. Click the only cell in the only row and column of the DataGrid.

Here are some additional details in case they matter.

  • .NET Core Version:
    • Version: 5.0.201
    • Commit: a09bd5c86c
  • Windows version: 1909 (OS Build 18363.1440)
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes

Expected behavior

I expect that cell to have focus. I do not expect the cell to appear selected. I do not expect an exception to be thrown. I do not expect the application to crash.

Actual behavior

The application crashes because the exception

System.ArgumentNullException: 'Value cannot be null.
Parameter name: item'

is thrown with stack trace

PresentationFramework.dll!System.Windows.Automation.Peers.DataGridItemAutomationPeer.DataGridItemAutomationPeer(object item, System.Windows.Automation.Peers.DataGridAutomationPeer dataGridPeer)	Unknown
PresentationFramework.dll!System.Windows.Automation.Peers.DataGridAutomationPeer.CreateItemAutomationPeer(object item)	Unknown
PresentationFramework.dll!System.Windows.Automation.Peers.ItemsControlAutomationPeer.FindOrCreateItemAutomationPeer(object item)	Unknown
PresentationFramework.dll!System.Windows.Automation.Peers.DataGridAutomationPeer.RaiseAutomationSelectionEvents(System.Windows.Controls.SelectionChangedEventArgs e)	Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.OnSelectionChanged(System.Windows.Controls.SelectionChangedEventArgs e)	Unknown
PresentationFramework.dll!System.Windows.Controls.Primitives.Selector.SelectionChanger.End()	Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.MakeFullRowSelection(System.Windows.Controls.ItemsControl.ItemInfo info, bool allowsExtendSelect, bool allowsMinimalSelect)	Unknown
PresentationFramework.dll!System.Windows.Controls.DataGrid.HandleSelectionForCellInput(System.Windows.Controls.DataGridCell cell, bool startDragging, bool allowsExtendSelect, bool allowsMinimalSelect)	Unknown
PresentationFramework.dll!System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)	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.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.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
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore)	Unknown
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window)	Unknown
Project.exe!MyNamespace.App.Main()	Unknown

2021-03-12_06-58-24_557

Workarounds

  1. Remove the MenuItem but keep the Button. (This is the is the most surprising workaround to me.)
  2. Initialize the backing ObservableCollection<> with an element. Clicking on that element does not reproduce the problem. However, clicking the Button and then clicking either element still reproduces the problem.
  3. Initialize the backing ObservableCollection<> with the value 2 and change the getter of MySelectedItem to always return 2.
  4. Change MySelectedItem into an auto property.

Additional comments

I created this minimal working example based on the reproduction provided in https://github.com/elmish/Elmish.WPF/issues/371.

I think it is reasonable to consider that the backing logic of the SelectedItem could ignore the value set by WPF.

In that initial issue, the set by WPF was not being completely ignored. Instead, it was being queued with the Dispatcher for later processing via InvokeAsync. WPF calls TryGetMember after calling TrySetMember (for the same member of course), so from the perspective of WPF at that moment, it appears as though its call to TrySetMember was ignored. I decided to go back to using Invoke when handling UI events (c.f. https://github.com/elmish/Elmish.WPF/pull/374), so the present issue is not blocking us over at Elmish.WPF.

Nonetheless, I think it would be reasonable to allow the user to toggle the ability select a row in a DataGrid. When the toggle is in the “selection-not-possible state”, then the selection behavior would be the same as the reproduction that I have provided.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:17 (15 by maintainers)

github_iconTop GitHub Comments

3reactions
vasiliy-vdovichenkocommented, Mar 15, 2022

As workaround for this bug it can be possible to disable Automation Peers for DataGrid in derived class DataGridEx and using DataGridEx instead of DataGrid see details below:

    public class DataGridEx : System.Windows.Controls.DataGrid
    {
        /// <summary>
        /// Turn off UI Automation
        /// </summary>
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new CustomDataGridExAutomationPeer(this);
        }
    }

    public class CustomDataGridExAutomationPeer : FrameworkElementAutomationPeer
    {
        public CustomDataGridExAutomationPeer(FrameworkElement owner)
            : base(owner) { }

        protected override string GetNameCore()
        {
            return "DataGridExAutomationPeer";
        }

        protected override AutomationControlType GetAutomationControlTypeCore()
        {
            return AutomationControlType.DataGrid;
        }

        protected override List<AutomationPeer> GetChildrenCore()
        {
            return new List<AutomationPeer>();
        }
    }
2reactions
TysonMNcommented, Mar 12, 2021

I think this is the source code corresponding to the last five stack frames in that trace.

  1. DataGridItemAutomationPeer.DataGridItemAutomationPeer(object item, DataGridAutomationPeer dataGridPeer)
  2. DataGridAutomationPeer.CreateItemAutomationPeer(object item)
  3. ItemsControlAutomationPeer.FindOrCreateItemAutomationPeer(object item)
  4. DataGridAutomationPeer.RaiseAutomationSelectionEvents(SelectionChangedEventArgs e)
  5. DataGrid.OnSelectionChanged(SelectionChangedEventArgs e)

My best guess is that this.OwningDataGrid.SelectedItem is null on this line. This makes sense because the value of SelectedItem for my DataGrid is null. There exist an execution path in which that null is passed to constructor of DataGridItemAutomationPeer as its first argument. https://github.com/dotnet/wpf/blob/d49f8ddb889b5717437d03caa04d7c56819c16aa/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Automation/Peers/DataGridAutomationPeer.cs#L412

I would love to be able to execute my reproduction while being able to break on these lines of code, but I don’t know how to do that.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Exception when selecting row in WPF DataGrid
ArgumentException occurs when you select rows in WPF DataGrid. This article provides a resolution.
Read more >
Exception in WPF DataGrid Cell Editing
I'm getting the below error while edit the cell event in WPF DataGrid. enter image description here. Could you please help me resolve...
Read more >
DataGrid
The DataGrid component allows users to select single or multiple rows. The selectionMode attribute sets the rows selection mode.
Read more >
C# Database Basics - Page 12 - Google Books Result
ToString(); } } Once you do this, you need to set up the grid to call this procedure. ... right-click on the first...
Read more >
Configuring Data Grid Caches
If you configure a capability that is not compatible with a simple cache, Data Grid throws an exception. Simple cache configuration. XML.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found