PowerShell WPF DataGrid:提交空行引发异常

发布于 2024-07-16 11:05:19 字数 5722 浏览 5 评论 0原文

我在尝试提交 DataGrid 行时遇到异常。

System.NullReferenceException: Object reference not set to an instance of an object.
   at MS.Internal.Data.PropertyPathWorker.DetermineWhetherDBNullIsValid()
   at MS.Internal.Data.PropertyPathWorker.get_IsDBNullValidForUpdate()
   at MS.Internal.Data.ClrBindingWorker.get_IsDBNullValidForUpdate()
   at System.Windows.Data.BindingExpression.ConvertProposedValue(Object value)
   at System.Windows.Data.BindingExpressionBase.UpdateValue()
   at System.Windows.Data.BindingExpression.Update(Boolean synchronous)
   at System.Windows.Data.BindingExpression.UpdateSource()
   at Microsoft.Windows.Controls.DataGridHelper.UpdateSource(FrameworkElement element, DependencyProperty dp)
   at Microsoft.Windows.Controls.DataGridTextColumn.CommitCellEdit(FrameworkElement editingElement)
   at Microsoft.Windows.Controls.DataGridColumn.CommitEdit(FrameworkElement editingElement)
   at Microsoft.Windows.Controls.DataGridCell.CommitEdit()
   at Microsoft.Windows.Controls.DataGrid.OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
   at Microsoft.Windows.Controls.DataGrid.OnExecutedCommitEdit(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
   at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
   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.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
   at System.Windows.Input.RoutedCommand.Execute(Object parameter, IInputElement target)
   at Microsoft.Windows.Controls.DataGrid.EndEdit(RoutedCommand command, DataGridCell cellContainer, DataGridEditingUnit editingUnit, Boolean exitEditMode)
   at Microsoft.Windows.Controls.DataGrid.CommitEdit(DataGridEditingUnit editingUnit, Boolean exitEditingMode)
   at Microsoft.Windows.Controls.DataGrid.CommitAnyEdit()
   at Microsoft.Windows.Controls.DataGrid.OnEnterKeyDown(KeyEventArgs e)
   at Microsoft.Windows.Controls.DataGrid.OnKeyDown(KeyEventArgs e)
   at System.Windows.UIElement.OnKeyDownThunk(Object sender, KeyEventArgs e)
   at System.Windows.Input.KeyEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawKeyboardActions actions, Int32 scanCode, Boolean isExtendedKey, Boolean isSystemKey, Int32 virtualKey)
   at System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
   at System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
   at System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
Exception calling "Run" with "1" argument(s): "Object reference not set to an instance of an object."

重现步骤:

  • 转到“新行”
  • 按 F2
  • 按 ENTER

这可以正常工作:

  • 转到“新行”
  • 按 F2
  • 按 ESC

以及:

  • 转到“新行”
  • 按 F2
  • 输入“sdfdsf”
  • 按 ENTER

可以找到源 此处

我发现了两篇似乎与此问题相关的帖子:

  1. Exception in .Net 3.5 SP1
  2. WPF 数据绑定、类类型、无命名空间异常

此外,我在 C# 中尝试了类似的代码,并且运行良好。

我该如何解决这个问题?

I get exception trying to commit empty DataGrid row.

System.NullReferenceException: Object reference not set to an instance of an object.
   at MS.Internal.Data.PropertyPathWorker.DetermineWhetherDBNullIsValid()
   at MS.Internal.Data.PropertyPathWorker.get_IsDBNullValidForUpdate()
   at MS.Internal.Data.ClrBindingWorker.get_IsDBNullValidForUpdate()
   at System.Windows.Data.BindingExpression.ConvertProposedValue(Object value)
   at System.Windows.Data.BindingExpressionBase.UpdateValue()
   at System.Windows.Data.BindingExpression.Update(Boolean synchronous)
   at System.Windows.Data.BindingExpression.UpdateSource()
   at Microsoft.Windows.Controls.DataGridHelper.UpdateSource(FrameworkElement element, DependencyProperty dp)
   at Microsoft.Windows.Controls.DataGridTextColumn.CommitCellEdit(FrameworkElement editingElement)
   at Microsoft.Windows.Controls.DataGridColumn.CommitEdit(FrameworkElement editingElement)
   at Microsoft.Windows.Controls.DataGridCell.CommitEdit()
   at Microsoft.Windows.Controls.DataGrid.OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
   at Microsoft.Windows.Controls.DataGrid.OnExecutedCommitEdit(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
   at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
   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.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
   at System.Windows.Input.RoutedCommand.Execute(Object parameter, IInputElement target)
   at Microsoft.Windows.Controls.DataGrid.EndEdit(RoutedCommand command, DataGridCell cellContainer, DataGridEditingUnit editingUnit, Boolean exitEditMode)
   at Microsoft.Windows.Controls.DataGrid.CommitEdit(DataGridEditingUnit editingUnit, Boolean exitEditingMode)
   at Microsoft.Windows.Controls.DataGrid.CommitAnyEdit()
   at Microsoft.Windows.Controls.DataGrid.OnEnterKeyDown(KeyEventArgs e)
   at Microsoft.Windows.Controls.DataGrid.OnKeyDown(KeyEventArgs e)
   at System.Windows.UIElement.OnKeyDownThunk(Object sender, KeyEventArgs e)
   at System.Windows.Input.KeyEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawKeyboardActions actions, Int32 scanCode, Boolean isExtendedKey, Boolean isSystemKey, Int32 virtualKey)
   at System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
   at System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
   at System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
Exception calling "Run" with "1" argument(s): "Object reference not set to an instance of an object."

Steps to reproduce:

  • Goto "new row"
  • Press F2
  • Press ENTER

This works ok:

  • Goto "new row"
  • Press F2
  • Press ESC

As well as:

  • Goto "new row"
  • Press F2
  • Type "sdfdsf"
  • Press ENTER

Sources can be found here.

I have found two posts that seems to be related to this problem:

  1. Exception in .Net 3.5 SP1
  2. WPF Databinding, Class Types, No Namespace Exception

Also, I tried similar code in C#, and it worked fine.

How can I fix this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清风疏影 2024-07-23 11:05:19

这似乎是 Microsoft WPF DataGrid 中的一个错误。 如果您还没有这样做,您绝对应该通过 Microsoft Connect 报告此问题。

作为解决方法,您可以在绑定上使用值转换器,以阻止绑定目标上的 NULL 值传输到绑定源,否则会导致 NullReferenceException。 下面是此类转换器的一个示例:

// NullToUnsetConverter.cs    

using System;
using System.Windows;
using System.Windows.Data;
using System.Globalization;

namespace MyProject.Controls.Converters
{
    /// <summary>
    /// Converts <c>null</c> values to <see cref="DependencyProperty.UnsetValue"/>.
    /// <remarks>
    /// This converter is intented for use in situations when the binding target
    /// does not correctly handle <c>null</c> values. This is the case for example
    /// with some WPF UI controls.
    /// </remarks>
    /// </summary>
    public class NullToUnsetConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return DependencyProperty.UnsetValue;
            }
            else
            {
                // No conversion applied
                return value;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // No conversion applied
            return value;
        }
    }
}

为了将转换器应用到您的绑定,您必须像这样修改您的 XAML:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:cnv="clr-namespace:MyProject.Controls.Converters"
  xmlns:sys="clr-namespace:System;assembly=mscorlib"
  xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
  >

  <Window.Resources>
    <x:Array x:Key="people" Type="sys:Object" />
    <cnv:NullToUnsetConverter x:Key="NullToUnsetConverter" />
  </Window.Resources>

  <StackPanel>
    <dg:DataGrid ItemsSource="{DynamicResource people}" CanUserAddRows="True" AutoGenerateColumns="False">
      <dg:DataGrid.Columns>

        <dg:DataGridTextColumn Header="First" Binding="{Binding First, Converter={StaticResource NullToUnsetConverter}}" />
        <dg:DataGridTextColumn Header="Last" Binding="{Binding Last, Converter={StaticResource NullToUnsetConverter}}" />

      </dg:DataGrid.Columns>
    </dg:DataGrid>
  </StackPanel>
</Window>

或者,您可以修改 NullToUnsetConverter.Convert 方法以返回空字符串 当输入值是字符串时,就像您的情况一样。

This seems to be a bug in the Microsoft WPF DataGrid. You should definitely report it through Microsoft Connect, if you haven't already done so.

As a workaround, you could use a value converter on your bindings, to stop NULL values on the binding target from being transferred to the binding source, which will cause the NullReferenceException. Here is an example of such a converter:

// NullToUnsetConverter.cs    

using System;
using System.Windows;
using System.Windows.Data;
using System.Globalization;

namespace MyProject.Controls.Converters
{
    /// <summary>
    /// Converts <c>null</c> values to <see cref="DependencyProperty.UnsetValue"/>.
    /// <remarks>
    /// This converter is intented for use in situations when the binding target
    /// does not correctly handle <c>null</c> values. This is the case for example
    /// with some WPF UI controls.
    /// </remarks>
    /// </summary>
    public class NullToUnsetConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return DependencyProperty.UnsetValue;
            }
            else
            {
                // No conversion applied
                return value;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // No conversion applied
            return value;
        }
    }
}

In order to apply the converter to your bindings, you'll have to modify your XAML like this:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:cnv="clr-namespace:MyProject.Controls.Converters"
  xmlns:sys="clr-namespace:System;assembly=mscorlib"
  xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
  >

  <Window.Resources>
    <x:Array x:Key="people" Type="sys:Object" />
    <cnv:NullToUnsetConverter x:Key="NullToUnsetConverter" />
  </Window.Resources>

  <StackPanel>
    <dg:DataGrid ItemsSource="{DynamicResource people}" CanUserAddRows="True" AutoGenerateColumns="False">
      <dg:DataGrid.Columns>

        <dg:DataGridTextColumn Header="First" Binding="{Binding First, Converter={StaticResource NullToUnsetConverter}}" />
        <dg:DataGridTextColumn Header="Last" Binding="{Binding Last, Converter={StaticResource NullToUnsetConverter}}" />

      </dg:DataGrid.Columns>
    </dg:DataGrid>
  </StackPanel>
</Window>

Alternatively, you could modify the NullToUnsetConverter.Convert method to return an empty string when the input value is a string, like in your case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文