开发者

WPF ResourceDictionary Item has already been added using ComponentResourceKey

I have the following ResourceDictionary that gets merged 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:RequirementResourceRe开发者_开发技巧lation}" 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'm trying to create two different data templates for the same DataType with different ComponentResourceKey. As you can see one of the keys has a 2 appended to it.

In my local:Resources class I have the following which is the ComponentResourceKey I'm using.

    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 in there, but once I add the second one 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 the ResourceDictionary ignores the key when adding a DataTemplate. Does the ResourceDictionary ignore the key property when it's using a ComponentRelationKey ?

Any way around this exception ?

Thanks, Raul


Apparently the issue is as stated, sort of. The order of the declaration of the style matters.

When the first attribute for two styles for the same TargetType is the TargetType e.g.

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

then you get the error. It seems to ignore the Key: attribute and as stated uses the TargetType value as the dictionary key e.g. "{x:Type TextBlock}"

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

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

Doesn't matter if you move the crap around I guess. WOrd to the wise, always start with the x:Key, but this is a really stupid error.


If you reference your DataTemplate by key, can't you just leave out the DataType-specification? Without DataType="{x:Type model:RequirementResourceRelation}" (which is apparently the key for the added item) your x:Key should be used as the key.


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

In Silverlight this worked just 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 the 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 in both WPF and Silverlight without the error.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜