【问题标题】:WPF DataGrid, application crash when adding a rowWPF DataGrid,添加行时应用程序崩溃
【发布时间】:2013-01-16 06:36:41
【问题描述】:

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

这是堆栈跟踪:

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>

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

【问题讨论】:

  • 你能把这个异常发生的逻辑的代码贴出来吗?
  • 您的网格是否绑定到特定属性?你的 xaml 是什么样的?与 xaml 相关的属性是什么?
  • @ryadavilli 我们的代码中没有发生异常。这是 WPF DataGrid 内部的东西。
  • WPF 数据网格不会自行引发异常。只有在滥用时才会这样做。最后,您似乎正在尝试将空值分配给 XAML 中使用的某个属性。我建议调试并弄清楚。
  • @DJ Burb 编辑:在操作中添加 xaml。

标签: wpf datagrid


【解决方案1】:

问题与DataGridAutomationPeer.RaiseAutomationSelectionEvents 内部方法中的一个错误有关,简单地说,它不会检查 SelectedItem 属性是否为空。在 Windows 7 中运行“Microsoft Narrator”工具即可轻松重现。

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

我通过从 DataGrid 继承实现了一个“足够好”的修复,这将改变当 SelectedItem 为空时取消选择 DataGrid 的方式,但前提是存在叙述者/触摸屏。

希望该错误将很快得到修复。如有必要,添加对 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);
    }
}

【讨论】:

  • 此解决方案可防止崩溃。但它的缺点是取消选择不再正常工作,因为取消选择使用了一个空值。这意味着如果之前选择过该项目,则始终保持选中状态。这就是为什么我更喜欢这个解决方案:stackoverflow.com/a/16256740/4424024
【解决方案2】:

我知道这已经很老了,但是我遇到了这个问题的一个很好的解决方案。您可以使用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;
    }
}

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

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

返回这个而不是 null 应该可以解决问题。

【讨论】:

  • 在你写的Convert方法return value != null ? DependencyObject.UnsetValue : value,不应该是:return value == null ? DependencyObject.UnsetValue : value
  • 谢谢!你为我节省了几个小时。
【解决方案3】:

不需要转换器或使用派生类。 只需确保您为 SelectedItem 绑定的属性已使用 DependencyProperty.UnsetValue 进行初始化。不要将其设置为或保留默认值为 null。

应该在不久的将来修复潜在的错误,顺便说一句: https://developercommunity.visualstudio.com/content/problem/575165/vs-1604-ide-crash-argumentnullexception.html

【讨论】:

  • 这为我解决了问题。我正在使用转换器来确保我的 SelectedItem 的强类型,当没有选择任何内容时它返回 null。我让它返回DependencyProperty.UnsetValue,它似乎已经解决了这个问题。
【解决方案4】:

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

您也可以使用值转换器来做到这一点

【讨论】:

    【解决方案5】:

    我只在触摸屏上遇到了同样的问题。 我有一个工作正常的 WPF 应用程序,直到我连接了为该应用程序构建的触摸屏。

    当 DataGrid 选定项绑定到为空的对象时会出现此问题;

    我是这样解决的:

    DataGrid Xaml 有这一行:

    SelectedItem="{Binding SelItem}"
    

    XVVM 看起来像:

    public MyViewModel SelItem
    {
    
        get
        {
            if (m_selected == null)
                 return new MyViewModel();
            else
                 return m_selected;
        }
    }
    

    【讨论】:

      【解决方案6】:

      我也有同样的问题。当用户双击 DataGrid 中的第一行(只有一行)时,它会在 Datagrid 上发生。这只发生在带触摸屏的索尼笔记本电脑上。 Sony 软件为 WINFOWS Explorer 中的每个文件添加了复选框。我认为这个问题与索尼软件有关。

      【讨论】:

        【解决方案7】:

        我不知道 - 它会帮助别人吗,因为我是新手。

        我在执行此操作时遇到了同样的问题:

                    collectionView = Application.Current.MainWindow.TryFindResource("InputElements") as CollectionViewSource;
                    if (collectionView != null && collectionView.View != null) collectionView.View.Refresh();
        

        第二次以这种方式在我的 DataGrid 中添加一些元素后发生崩溃:

        1. DataGrid 中没有元素
        2. 通过更改元素属性“UseInDataGrid”= true 将元素添加到 DataGrid;
        3. 从 DataGrid 中删除元素并更改元素属性 "UseInDataGrid" = false;
        4. 通过更改元素属性“UseInDataGrid”= true 将相同元素添加到 DataGrid; -> 崩溃!

        我的 DataGrid ItemSource 已绑定到 StaticResource CollectionViewSource ,后者已通过元素绑定到 ObservableCollection。

        对于我的元素,有一个 PropertyChanged 方法,当某些属性发生更改时,我使用了上面的方法 (View.Refresh())。

        在更改了一些逻辑之后,我让集合视图在没有 View.Refresh() 的情况下刷新,这个问题就消失了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-15
          • 1970-01-01
          • 2011-01-01
          • 2012-11-19
          • 1970-01-01
          • 2018-05-27
          • 1970-01-01
          相关资源
          最近更新 更多