WPF DataGrid,添加行时应用程序崩溃 [英] WPF DataGrid, application crash when adding a row

查看:75
本文介绍了WPF DataGrid,添加行时应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WPF数据网格绑定到TrackableCollection。在少数情况下,并且只有少数选定的用户,当用户通过输入底部空白行添加新记录时,应用程序将崩溃。
我无法重现该问题,而我所拥有的只是抛出异常的堆栈跟踪。
有人看到过这样的东西吗?我对Automationpeer类的了解有限,但是我可以确认我们在应用程序中没有使用它们。

I have a wpf datagrid bound to a TrackableCollection. In some rare occations, and for only a few selected users, the application will crash when the user adds a new record by entering the bottom blank row. I have not been able to reproduce the issue, and all I have is a stacktrace of the exception thrown. Has anyone seen anything like this? I have limited knowledge about the automationpeer-classes, but I can confirm that we are not using any of them in our application.

这里是stacktrace:

Here's the stacktrace:

System.ArgumentNullException: Value cannot be null.
Parameter name: item
   at System.Windows.Automation.Peers.DataGridAutomationPeer.CreateItemAutomationPeer(Object item)
   at System.Windows.Automation.Peers.ItemsControlAutomationPeer.FindOrCreateItemAutomationPeer(Object item)
   at System.Windows.Automation.Peers.DataGridAutomationPeer.RaiseAutomationSelectionEvents(SelectionChangedEventArgs e)
   at System.Windows.Controls.DataGrid.OnSelectionChanged(SelectionChangedEventArgs e)
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
   at System.Windows.Controls.DataGrid.MakeFullRowSelection(Object dataItem, Boolean allowsExtendSelect, Boolean allowsMinimalSelect)
   at System.Windows.Controls.DataGrid.HandleSelectionForCellInput(DataGridCell cell, Boolean startDragging, Boolean allowsExtendSelect, Boolean allowsMinimalSelect)
   at System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDown(MouseButtonEventArgs e)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   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.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   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.Input.InputManager.ProcessStagingArea()
   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)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

XAML:

<DataGrid Name="OrdreSLinjeGrid" 
          AutoGenerateColumns="False"
          CanUserResizeRows="False"
          CanUserAddRows="{Binding KanLeggeTilOrdreLinjer}"
          HorizontalScrollBarVisibility="Disabled" 
          VerticalScrollBarVisibility="Visible" 
          ItemsSource="{Binding Order.OrderLines, Mode=TwoWay}" CanUserSortColumns="False"
          SelectedItem="{Binding ValgtOrdreLinje}" >
    <DataGrid.Columns>           
        <DataGridTextColumn
            Header="{t:Translate Antall}" 
            TextAlignment="Right" 
            Width="50" 
            HeaderStyle="{StaticResource HøyrejustertColumnHeader}" 
            Binding="{Binding Antall, UpdateSourceTrigger=LostFocus}" />

        <DataGridTextColumn 
            Header="{t:Translate Pris}" 
            Width="60" 
            HeaderStyle="{StaticResource HøyrejustertColumnHeader}" 
            Binding="{Binding Pris, UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True}" 
             />
    </DataGrid.Columns>
</DataGrid>

任何输入或建议都会受到赞赏。

Any input or suggestions will be appreciated.

推荐答案

该问题与 DataGridAutomationPeer.RaiseAutomationSelectionEvents 内部方法中的错误有关,该内部方法仅检查不检查SelectedItem属性是否为null或不。可以通过在Windows 7中运行 Microsoft Narrator工具来轻松地重现它。

The problem is related to a bug in DataGridAutomationPeer.RaiseAutomationSelectionEvents internal method which simply speaking does not check if SelectedItem property is null or not. It can easily be reproduced by running "Microsoft Narrator" tool in Windows 7.

由于这是一个密封的类,因此没有简单的方法来修复它,除非使用Reflection.Emit或任何模拟工具,即使它已修复,我们也不能保证微软不会更改此方法的名称,签名或行为。

Because this is a sealed class there is no easy way to fix it except intercepting this method using Reflection.Emit or any mocking tool out there and even if it's fixed we have no guarantee that Microsoft won't change this method name, signature or behaviour.

我实现了一个通过继承DataGrid进行足够好修复,它将改变SelectedItem为null时(但仅当存在叙述者/触摸屏时)未选择DataGrid的方式。

I implemented a "good enough" fix by inheriting from DataGrid which will change the way DataGrid is unselected when the SelectedItem is null but only if narrator/touchscreen is present.

希望该错误将很快修复。

Hopefully the bug will be fixed soon. Add reference to UIAutomationProvider if necessary.

using System.Windows.Automation.Peers;
using System.Windows.Controls;

public class TooDataGrid: DataGrid
{
    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        if(AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementSelected) ||
            AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementAddedToSelection) ||
            AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementRemovedFromSelection))
        {
            if(SelectedItem == null)
            {
                return;
            }
        }
        base.OnSelectionChanged(e);
    }
}

这篇关于WPF DataGrid,添加行时应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆