WPF ResourceDictionary Element Already Added Using ComponentResourceKey

I have the following ResourceDictionary that merges into my Themes / Generic.xaml file

<DataTemplate DataType="{x:Type model:RequirementResourceRelation}" x:Key="{x:Static local:Resources.RequirementResourceRelationListTemplateKey}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock MinWidth="35" HorizontalAlignment="Left" Padding="3,0" Text="{Binding Resource.Name, TargetNullValue=Loading...}" /> <TextBlock Grid.Column="1" Text="-" /> <TextBlock Grid.Column="2" MinWidth="35" HorizontalAlignment="Left" Padding="3,0" Text="{Binding Path=RelationType, TargetNullValue=Loading...}" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" /> </Grid> </DataTemplate> <DataTemplate DataType="{x:Type model:RequirementResourceRelation}" x:Key="{x:Static local:Resources.RequirementResourceRelationListTemplate2Key}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock MinWidth="35" HorizontalAlignment="Left" Padding="3,0" Text="{Binding Requirement.Name, TargetNullValue=Loading...}" /> <TextBlock Grid.Column="1" Text="-" /> <TextBlock Grid.Column="2" MinWidth="35" HorizontalAlignment="Left" Padding="3,0" Text="{Binding Path=RelationType, TargetNullValue=Loading...}" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" /> </Grid> </DataTemplate> 

I am trying to create two different data patterns for the same DataType with a different ComponentResourceKey. As you can see, one of the keys has 2 applications to it.

In my local: resource class, I have the following: ComponentResourceKey, which I use.

  public static ComponentResourceKey RequirementResourceRelationListTemplateKey { get { return new ComponentResourceKey(typeof(Resources), "RequirementResourceRelationListTemplate"); } } public static ComponentResourceKey RequirementResourceRelationListTemplate2Key { get { return new ComponentResourceKey(typeof(Resources), "RequirementResourceRelationListTemplate2"); } } 

This works if I have only one of the DataTemplates, but as soon as I add a second, I get an exception that says:

 Item has already been added. Key in dictionary: 'DataTemplateKey(HR.TrackingTool.Model.RequirementResourceRelation)' Key being added: 'DataTemplateKey(HR.TrackingTool.Model.RequirementResourceRelation)' at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add) at System.Collections.Hashtable.Add(Object key, Object value) at System.Windows.ResourceDictionary.SetKeys(IList`1 keyCollection, IServiceProvider serviceProvider) at System.Windows.ResourceDictionary.SetDeferrableContent(DeferrableContent deferrableContent) at System.Windows.Baml2006.WpfSharedBamlSchemaContext.<Create_BamlProperty_ResourceDictionary_DeferrableContent>b__168(Object target, Object value) at System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(Object instance, Object value) at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember member, Object obj, Object value) at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value) 

It seems that ResourceDictionary is ignoring the key when adding a DataTemplate. Does the ResourceDictionary resource ignore the key property when using the ComponentRelationKey?

How to get around this exception?

Thanks Raul

+4
source share
3 answers

If you reference your DataTemplate by key, can you just leave the DataType specification? Without DataType = "{x: Model Type: RequireResourceRelation}" (which, apparently, is the key to the added item), your x: key should be used as the key.

+4
source

Apparently, the problem is as indicated, sort of. The style declaration procedure matters.

When the first attribute for two styles for the same TargetType is TargetType , for example.

 <Style TargetType="{x:Type TextBlock}" x:Key="_defaultRuleTextBlockStyle"> <Style TargetType="{x:Type TextBlock}" x:Key="_tinySourceCodeTextBlockStyle"> 

then you will get an error. It seems to ignore the Key: attribute and, as indicated, uses the TargetType value as a dictionary key, for example. "{x: Type TextBlock}"

When the first element of two styles for the same TargetType is x: Key , then you will not do this, as shown below.

 <Style x:Key="_defaultRuleTextBlockStyle" TargetType="{x:Type TextBlock}"> <Style x:Key="_tinySourceCodeTextBlockStyle" TargetType="{x:Type TextBlock}"> 

It doesn't matter if you move the shit around, I think. WOrd to the wise, always start with x: Key , but this is a really stupid mistake.

+8
source

Move the DataTemplate (s) inside the <Resources> element of another control.

In Silverlight, this worked fine:

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <!--Template 1--> <DataTemplate DataType="VMType" x:Key="Template1"> ... </DataTemplate> <!--Template 2--> <DataTemplate DataType="VMType" x:Key="Template2"> ... </DataTemplate> <!--Control Style, references the two templates above--> <Style TargetType="ControlType"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ControlType"> <Grid Background="White" Margin="0"> ... </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> 

BUT in WPF I had to move 3 templates inside the control:

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <Style TargetType="ControlType"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ControlType"> <Grid Background="White" Margin="0"> <!--MOVED HERE INSTEAD OF THE ROOT--> <Grid.Resources> <!--Template 1--> <DataTemplate DataType="VMType" x:Key="Template1"> ... </DataTemplate> <!--Template 2--> <DataTemplate DataType="VMType" x:Key="Template2"> ... </DataTemplate> </Grid.Resources> ... </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> 

Now it works both in WPF and in Silverlight without errors.

+1
source

All Articles