wpf 值不能为空。参数名称:key(仅在 XAML 设计器的设计视图中发生)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42810814/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 14:02:39  来源:igfitidea点击:

Value cannot be null. Parameter name: key (only happens on XAML Designer's design view)

c#wpfxamldatagriddesigner

提问by Julio Nobre

XAML Designerdesign view shows

XAML 设计器设计视图显示

An Exception was thrown

抛出异常

ArgumentNullException: Value cannot be null.

ArgumentNullException:值不能为空。

Parameter name: key

参数名称:key

StackTrace (see after photo)

StackTrace(见后图)

InnerException: None

内部异常:无

I have been struggling for few days on the following issue, which prevents me from using XAML Designer's design view on every affected view.

我已经在以下问题上苦苦挣扎了几天,这使我无法在每个受影响的视图上使用XAML Designer 的设计视图。

Yesterday, I eventually managed to isolate this odd behaviour which it particulary hard to trace, since it happens only at design-time, and that seems a conflit between generic type and DataGrid's ItemsSource property (System.Windows.Controls).

昨天,我最终设法隔离了这种特别难以追踪的奇怪行为,因为它只发生在设计时,这似乎是泛型类型和DataGrid的 ItemsSource 属性(System.Windows.Controls)之间的冲突。

So, this is what is shown on the design view

所以,这就是设计视图中显示的内容

enter image description here

在此处输入图片说明

at System.Collections.Generic.Dictionary2.FindEntry(TKey key) at System.Collections.Generic.Dictionary2.TryGetValue(TKey key, TValue& value) at System.Windows.Controls.DataGridItemAttachedStorage.TryGetValue(Object item, DependencyProperty property, Object& value) at System.Windows.Controls.DataGridRow.RestoreAttachedItemValue(DependencyObject objectWithProperty, DependencyProperty property) at System.Windows.Controls.DataGridRow.SyncProperties(Boolean forcePrepareCells) at System.Windows.Controls.DataGridRow.PrepareRow(Object item, DataGrid owningDataGrid) at System.Windows.Controls.DataGrid.PrepareContainerForItemOverride(DependencyObject element, Object item) at System.Windows.Controls.ItemsControl.MS.Internal.Controls.IGeneratorHost.PrepareItemContainer(DependencyObject container, Object item) at System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.Primitives.IItemContainerGenerator.PrepareItemContainer(DependencyObject container) at System.Windows.Controls.VirtualizingStackPanel.InsertContainer(Int32 childIndex, UIElement container, Boolean isRecycled) at System.Windows.Controls.VirtualizingStackPanel.AddContainerFromGenerator(Int32 childIndex, UIElement child, Boolean newlyRealized, Boolean isBeforeViewport) at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Double& computedUniformOrAverageContainerPixelSize, Boolean& computedAreContainersUniformlySized, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean& hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable1& lastPageSafeOffset, List1& previouslyMeasuredOffsets, Nullable`1& lastPagePixelSize, Boolean remeasure) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint) at System.Windows.Controls.Primitives.DataGridRowsPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.ContextLayoutManager.UpdateLayout() at System.Windows.UIElement.UpdateLayout()

在 System.Collections.Generic.Dictionary2.FindEntry(TKey key) at System.Collections.Generic.Dictionary2.TryGetValue(TKey key, TValue& value) at System.Windows.Controls.DataGridItemAttachedStorage.TryGetValue(Object item, DependencyProperty property, Object& value) at System.Windows.Controls.DataGridRow.RestoreAttachedItemValue(DependencyObject objectWithProperty, DependencyProperty property) at System. Windows.Controls.DataGridRow.SyncProperties(Boolean forcePrepareCells) at System.Windows.Controls.DataGridRow.PrepareRow(Object item, DataGrid owningDataGrid) at System.Windows.Controls.DataGrid.PrepareContainerForItemOverride(DependencyObject element, Object item) at System.Windows。 Controls.ItemsControl.MS.Internal.Controls.IGeneratorHost.PrepareItemContainer(DependencyObject 容器,对象项目)在 System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.Primitives。IItemContainerGenerator.PrepareItemContainer(DependencyObject container) at System.Windows.Controls.VirtualizingStackPanel.InsertContainer(Int32 childIndex, UIElement container, Boolean isRecycled) at System.Windows.Controls.VirtualizingStackPanel.AddContainerFromGenerator(Int32 childIndex, UIElement child, Boolean newBeRealized, Boolean isRecycled)在 System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double&calculatedUniformOrAverageContainerSize, Double&computedUniformSizeOrAverageContainerSize,Double&computedUniformSizeOrAverageContainers,IcontainItemStorage&itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItemitem、IList&children、Int32&childIndex、Boolean&visualOrderChanged、Boolean&isHorizo​​ntal、Size&childConstraint、Rect&视口、VirtualizationCacheLength&cacheSize、VirtualizationCacheLengthUnit&cacheUnit、Boolean&foundFirstItemInViewport、Double&firstItemInViewportOffset、Size&stackPixelSize、Size&stackPixelSize&isHorizo​​ntal、大小&viewport、VirtualizationCacheLength&cacheSize、 Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean&hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren) 在 System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable)1& lastPageSafeOffset, List1& previousMeasuredOffsets, Nullable`1& lastPagePixelSize, Boolean remeasure) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint) at System.Windows.Controls.Primitives.DataGridRowsPresenter.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureCore( Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.ContextLayoutManager.UpdateLayout() at System.Windows.UIElement.UpdateLayout()

Sample project source code

示例项目源代码

MyViewModelbase.cs(this is my generic view model base)

MyViewModelbase.cs(这是我的通用视图模型库)

namespace BugProof.ViewModels
{
    using System.Collections.Generic;

    public class MyViewModelBase<TItem> where TItem : class
    {
        public List<TItem> Items { get; set; }
        public MyViewModelBase() { }
    }
}

MyExtendedViewModel.cs(this my extended view model, which will be based upon a stringtype)

MyExtendedViewModel.cs(这是我的扩展视图模型,将基于字符串类型)

namespace BugProof.ViewModels
{
    public class MyExtendedViewModel : MyViewModelBase<string>
    {
        public MyExtendedViewModel()
        {
        }
    }
}

MainWindow.xaml

主窗口.xaml

<Window x:Class="BugProof.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:BugProof.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BugProof"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance {x:Type vm:MyExtendedViewModel}, IsDesignTimeCreatable=False}"                  
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock>This is what you should se in the designer</TextBlock>
        <!--Try replacing following DataGrid by a ListBox or ListView-->
        <DataGrid ItemsSource="{Binding Items}"/>
    </StackPanel>
</Window>

MainWindow.xaml.cs(MainWindow's code behind)

MainWindow.xaml.cs(后面的 MainWindow 代码)

using System.Windows;

namespace BugProof
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Complementary details:

补充资料:

  • The behaviour does not occur if one replaces DataGridcontrol by a Listbox, ListViewor ItemsControl
  • I am using Visual Studio 2015, Version 14.0.25431.01 Update 3
  • Project is targeted to .Net Framework 4.5
  • 如果用ListboxListViewItemsControl替换DataGrid控件,则不会发生该行为
  • 我使用的是Visual Studio 2015,版本 14.0.25431.01 更新 3
  • 项目面向.Net Framework 4.5

回答by Julio Nobre

Setting IsDesignTimeCreatable=Trueon MainWindows.xamldid the trick, although it requires special care implementing view model's parameters-less constructor, checking whether code is running in design-time or not.

MainWindows.xaml上设置IsDesignTimeCreatable=True 可以解决问题,尽管它需要特别注意实现视图模型的无参数构造函数,检查代码是否在设计时运行。

According to Microsoft, setting IsDesignTimeCreatable=True, "specifies that the design instance is created from your type, instead of a designer-generated substitute type".

根据 Microsoft 的说法,设置IsDesignTimeCreatable=True,“指定设计实例是根据您的类型创建的,而不是设计器生成的替代类型”。

Surprisingly, also according to Microsoft, if IsDesignTimeCreatableis not set or set to False, "all the design tool does is parse the class for its bindable properties".

令人惊讶的是,同样根据 Microsoft 的说法,如果IsDesignTimeCreatable未设置或设置为False,“所有设计工具所做的就是解析类的可绑定属性”。

I guess we have got two opposite truths. This may even be the case that both are really true, depending upon context. May be, the second source was not aware, at documentation writing time, the 3 samples that XAML Designer automatically generates once IsDesignTimeCreatableis set to default Falsevalue, whenever it finds a collection (IEnumerable) property

我想我们有两个相反的事实。这甚至可能是两种情况都正确的情况,具体取决于上下文。可能是,第二个来源不知道,在编写文档时,XAML 设计器在将IsDesignTimeCreatable设置为默认False值时自动生成的 3 个示例,只要它找到集合 (IEnumerable) 属性

Until proof otherwise, this is a WPF DataGridcontrol bug when ItemsSourceis binded to a generic collection source and IsDesignTimeCreatable=False, since this issue does not arise if we replace DataGrid control by ListBox, ListViewor ItemsControls.

除非另有证明,否则当ItemsSource绑定到通用集合源且IsDesignTimeCreatable=False时,这是WPF DataGrid控件错误,因为如果我们将 DataGrid 控件替换为ListBoxListViewItemsControls,则不会出现此问题。

回答by Axel Samyn

Another solution is simply to remove the "d:DataContext" attribute which will disable Datacontext related autocomplete.

另一种解决方案是简单地删除“d:DataContext”属性,这将禁用与 Datacontext 相关的自动完成。

I had to use this solution since the "IsDesignTimeCreatable" attribute, suggested by Julio, did not worked for me :/

我不得不使用这个解决方案,因为 Julio 建议的“IsDesignTimeCreatable”属性对我不起作用:/