XAML Designer design view shows
An Exception was thrown
ArgumentNullException: Value cannot be null.
Parameter name: key
StackTrace (see after photo)
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.
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).
So, this is what is shown on the design view
at System.Collections.Generic.Dictionary
2.FindEntry(TKey key) at System.Collections.Generic.Dictionary
2.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, List
1& 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()
Sample project source code
MyViewModelbase.cs (this is my generic view model base)
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 string type)
namespace BugProof.ViewModels
{
public class MyExtendedViewModel : MyViewModelBase<string>
{
public MyExtendedViewModel()
{
}
}
}
MainWindow.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)
using System.Windows;
namespace BugProof
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
Complementary details:
Setting IsDesignTimeCreatable=True on MainWindows.xaml did the trick, although it requires special care implementing view model's parameters-less constructor, checking whether code is running in design-time or not.
According to Microsoft, setting IsDesignTimeCreatable=True, "specifies that the design instance is created from your type, instead of a designer-generated substitute type".
Surprisingly, also according to Microsoft, if IsDesignTimeCreatable is not set or set to False, "all the design tool does is parse the class for its bindable properties".
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 IsDesignTimeCreatable is set to default False value, whenever it finds a collection (IEnumerable) property
Until proof otherwise, this is a WPF DataGrid control bug when ItemsSource is binded to a generic collection source and IsDesignTimeCreatable=False, since this issue does not arise if we replace DataGrid control by ListBox, ListView or ItemsControls.
Fixed this issue with the following:
FYI I am using Visual Studio 2019.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With