为什么 datagrid 在失去焦点时会引发异常?

Why is datagrid raising exception when loosing focus?

提问人:MatsW 提问时间:12/14/2021 最后编辑:MatsW 更新时间:12/15/2021 访问量:340

问:

我想我在 DataGrid 中发现了一个错误。我在 WPF (.net 5.0) 中遇到看似无法解释的数据网格崩溃

你能发现我做错了什么吗?我不能...我现在花了很多天的时间,代码非常清楚。

如何崩溃:

  1. 生成并运行下面给出的代码。
  2. 编辑“数据”网格单元格,将光标保留在单元格文本框中
  3. 从菜单中选择更新。(单元格将恢复为“数据”)
  4. 再次编辑“数据”网格单元格,将光标留在单元格文本框中
  5. 单击“TabItem”标题 ->异常如下所示:
System.ArgumentNullException
  HResult=0x80004003
  Message=Value cannot be null. (Parameter 'element')
  Source=PresentationCore
  StackTrace:
   at System.Windows.Automation.Peers.UIElementAutomationPeer.FromElement(UIElement element)
   at System.Windows.Controls.DataGrid.CellAutomationValueHolder.TrackValue()
   at System.Windows.Controls.DataGrid.ReleaseCellAutomationValueHolders()
   at System.Windows.Controls.DataGrid.OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
   at System.Windows.Controls.DataGrid.OnExecutedCommitEdit(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
   at System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs 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.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
   at System.Windows.Input.RoutedCommand.Execute(Object parameter, IInputElement target)
   at System.Windows.Controls.DataGrid.EndEdit(RoutedCommand command, DataGridCell cellContainer, DataGridEditingUnit editingUnit, Boolean exitEditMode)
   at System.Windows.Controls.DataGrid.OnCurrentCellChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at System.Windows.DependencyObject.SetCurrentValueInternal(DependencyProperty dp, Object value)
   at System.Windows.Controls.DataGrid.set_CurrentCellContainer(DataGridCell value)
   at System.Windows.Controls.DataGrid.set_FocusedCell(DataGridCell value)
   at System.Windows.Controls.DataGridCell.OnAnyLostFocus(Object sender, RoutedEventArgs e)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.OnLostFocus(RoutedEventArgs e)
   at System.Windows.Controls.Primitives.TextBoxBase.OnLostFocus(RoutedEventArgs e)
   at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.Controls.TextBox.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.ClearValueCommon(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata)
   at System.Windows.DependencyObject.ClearValue(DependencyPropertyKey key)
   at System.Windows.Input.FocusManager.OnFocusedElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
   at System.Windows.Input.FocusManager.SetFocusedElement(DependencyObject element, IInputElement value)
   at System.Windows.Input.KeyboardNavigation.UpdateFocusedElement(DependencyObject focusTarget)
   at System.Windows.FrameworkElement.OnGotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs 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.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.KeyboardDevice.ChangeFocus(DependencyObject focus, Int32 timestamp)
   at System.Windows.Input.KeyboardDevice.Focus(DependencyObject focus, Boolean askOld, Boolean askNew, Boolean forceToNullIfFailed)
   at System.Windows.Input.KeyboardDevice.Focus(IInputElement element)
   at System.Windows.UIElement.Focus()
   at System.Windows.Controls.TabItem.SetFocus()
   at System.Windows.Controls.TabItem.OnMouseLeftButtonDown(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 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run()
   at datagridcrashtest2.App.Main()

源代码:

using System;
using System.Windows;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;


namespace DataGridTest
{
    public class DataGridTest 
    {
      
        static string xaml = @"
<Window x:Class=""System.Windows.Window"" 
        xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
        xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
        xmlns:d=""http://schemas.microsoft.com/expression/blend/2008""
        xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006""
        mc:Ignorable=""d""
        Title=""DataGridTest"" Height=""650"" Width=""925"">
    <StackPanel >

        <Menu>
            <MenuItem Header=""File"" >
                <MenuItem Header=""Save"" Command=""{Binding UpdateCommand}"" />
                <Button Command=""{Binding UpdateCommand}"" Content=""Update"" />
            </MenuItem>
            <Button Command=""{Binding UpdateCommand}"" Content=""Update"" />
        </Menu>

        <TabControl >
            <TabItem Header=""TabItem"" Width=""150"" DataContext=""{Binding TabItemViewModel}"" >
                <DataGrid ItemsSource=""{Binding DataListViewModel}"" />
            </TabItem>
        </TabControl>

    </StackPanel>
</Window>";

        [STAThread]
        static void Main()
        {
            var window = Xaml.LoadXaml<Window>(xaml);
            window.DataContext = new MainWindowViewModel();
            window.ShowDialog();
        }
    }

    public class MainWindowViewModel : ViewModel
    {
        public MainWindowViewModel()
        {
            TabItemViewModel = new TabItemViewModel();
            UpdateCommand = new Command(Update);
        }

        public TabItemViewModel TabItemViewModel { get; set; }
        public ICommand UpdateCommand { get; set; }

        public void Update()
        {
            TabItemViewModel.Update();
        }
    }

    public class TabItemViewModel : ViewModel
    {
        public ObservableCollection<DataViewModel> DataListViewModel { get; set; } =
            new ObservableCollection<DataViewModel>();

        public TabItemViewModel()
        {
            Update();
        }
        
        public void Update()
        {
            DataListViewModel = new ObservableCollection<DataViewModel>(); 

            DataListViewModel.Add( new DataViewModel() { Name = "data" });
            OnPropertyChanged(nameof(DataListViewModel));
        }
    }

    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #region MVVM

    public class DataViewModel : ViewModel
    {
        private string name;

        public string Name
        {
            get { return name; }
            set
            {
                if (name != value)
                {
                    name = value;
                    OnPropertyChanged(nameof(this.Name));
                }
            }
        }
    }

    public class Command : ICommand
    {
        private readonly Action action;
        public Command(Action action)
        {
            this.action = action;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            action();
        }

        public event EventHandler CanExecuteChanged;
    }
    #endregion

    public class Xaml
    {
        public static T LoadXaml<T>(string xaml)
        {
            using (var stringReader = new System.IO.StringReader(xaml))
            using (var xmlReader = System.Xml.XmlReader.Create(stringReader))
                return (T)System.Windows.Markup.XamlReader.Load(xmlReader);
        }
    }

}
C# .NET WPF 异常 数据网格

评论

0赞 MatsW 1/3/2022
这是触发 stackoverflow.com/questions/68028285/ 中提到的崩溃的可靠方法......

答: 暂无答案