WPF DataGrid,添加行时应用程序崩溃

Sve*_*rik 10 wpf datagrid

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

这是堆栈跟踪:

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)
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

任何意见或建议将不胜感激.

too*_*too 9

该问题与DataGridAutomationPeer.RaiseAutomationSelectionEvents内部方法中的错误有关,简单地说,不会检查SelectedItem属性是否为null.它可以通过在Windows 7中运行"Microsoft Narrator"工具轻松复制.

因为这是一个密封的类,除了使用Reflection.Emit或任何模拟工具拦截此方法之外没有简单的方法来修复它,即使它已修复,我们也无法保证Microsoft不会更改此方法名称,签名或行为.

我通过继承DataGrid实现了"足够好"的修复,当SelectedItem为null时,它将改变DataGrid的取消方式,但仅当存在narrator/touchscreen时才会改变.

希望错误很快得到解决.如有必要,添加对UIAutomationProvider的引用.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案可防止崩溃。但它的缺点是取消选择不再正常工作,因为取消选择使用了空值。这意味着该项目如果之前被选中,则始终保持选中状态。这就是为什么我更喜欢这个解决方案:/sf/answers/1137971831/ (2认同)

yin*_*ers 6

我知道这已经很老了,但是对于遇到的这个问题有很好的解决方案。您可以使用以下IValueConverter接口定义自定义转换器:

public class SelectedItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value ?? DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (value == null || value.GetType().Name == "NamedObject") ? null : value;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将检查值是否为null,如果为,则返回DependecyProperty.UnsetValue。如文档中所述(查看方法说明):

返回值DependencyProperty.UnsetValue表示转换器未产生任何值,并且绑定使用FallbackValue(如果有)或默认值代替。

返回而不是null应该解决此问题。


DJ *_*urb 1

我会尝试检查视图模型中属性的空值。如果该属性为 null,请将 null 替换为有效值(例如 0 或空白)。

您还可以使用值转换器来执行此操作