已使用ComponentResourceKey添加了WPF ResourceDictionary项

时间:2010-07-29 21:49:33

标签: wpf exception resourcedictionary componentresourcekey

我将以下ResourceDictionary合并到我的Themes / Generic.xaml文件

<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>

我正在尝试使用不同的ComponentResourceKey为相同的DataType创建两个不同的数据模板。正如您所看到的,其中一个键附加了一个。

在我的本地:Resources类我有以下是我正在使用的ComponentResourceKey。

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

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

如果我只有一个DataTemplates,那么这是有效的,但是一旦我添加了第二个,我会得到一个例外情况:

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)

似乎ResourceDictionary在添加DataTemplate时忽略了该键。 ResourceDictionary在使用ComponentRelationKey时是否忽略key属性?

有什么办法绕过这个例外吗?

谢谢, 劳尔

3 个答案:

答案 0 :(得分:9)

显然这个问题与所说的有关。风格宣言的顺序很重要。

当同一 TargetType 的两个样式的第一个属性为 TargetType 时,例如

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

然后你得到错误。它似乎忽略了Key:属性,并且如上所述使用TargetType值作为字典键,例如“{x:输入TextBlock}”

当同一 TargetType 的两个样式的第一个元素是 x:Key 时,则不会,如下所示。

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

如果你把垃圾移动到我想是无关紧要的。对明智的人来说,总是从 x:Key 开始,但这是一个非常愚蠢的错误。

答案 1 :(得分:5)

如果您按键引用DataTemplate,那么您不能忽略DataType规范吗? 没有      DataType =“{x:Type model:RequirementResourceRelation}” (这显然是添加项目的关键)你的x:Key应该用作关键。

答案 2 :(得分:1)

DataTemplate(s)移到另一个控件的<Resources>元素内。

Silverlight 中,这工作正常:

<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>

但是在 WPF 中,我不得不移动控件中的3个模板:

<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>

现在它可以在WPF和Silverlight中运行而不会出现错误。