WPF资源字典项已使用ComponentResourceKey添加

6
我有以下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。如您所见,其中一个键附加了2。
在我的本地:Resources类中,我有以下内容,这是我正在使用的ComponentResourceKey。
    public static ComponentResourceKey RequirementResourceRelationListTemplateKey {
        get {
            return new ComponentResourceKey(typeof(Resources), "RequirementResourceRelationListTemplate");
        }
    }

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

如果我只有一个DataTemplate,这个方法是可行的,但是一旦我添加第二个,就会出现异常,提示如下:

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时忽略了键值。当使用ComponentRelationKey时,ResourceDictionary是否忽略键属性?

有没有解决这个异常的方法?

谢谢, Raul

3个回答

13

显然问题就像所说的那样,有点道理。 样式声明的顺序很重要。

当同一目标类型的两个样式的第一个属性是 目标类型 时,如下:

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

那么你会收到错误。它似乎忽略了Key属性,并使用TargetType的值作为字典键,例如"{x:Type TextBlock}"。

当同一目标类型的两个样式的第一个元素是时,您将不会出现上述问题,如下所示。

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

我猜移动这些垃圾无所谓吧。聪明人的建议是,始终从x:Key开始,但这是一个非常愚蠢的错误。


在我看来,这是最佳答案。它曾让我卡住了一段时间,并且怀疑我的整个WPF理解。我以前从未意识到XAML中的参数顺序会有影响,但显然确实会产生影响。 - apc
2
我绝对不可能自己搞清楚这个问题。做得好! - Steztric
不错的发现。属性顺序不应该有影响(是吗)?我没想到我做错了什么。 - apc

5
如果您通过关键字引用DataTemplate,是否可以省略DataType规范?没有 DataType="{x:Type model:RequirementResourceRelation}" (显然是添加项的关键字),则应使用x:Key作为关键字。

1
很棒的解决方案。我已将此作为错误提交给了微软。https://connect.microsoft.com/VisualStudio/feedback/details/581761/resource-dictionary-ignores-componentresourcekey-when-adding-a-datatemplate?wa=wsignin1.0 - HaxElit
1
这个 bug 仍然存在。太不可思议了!我正在将两种样式添加到应用程序资源字典中的 TextBlock 中。被这个 bug 卡住了。完全、彻底地令人沮丧。我想用键盘砸屏幕。微软真是太差劲了。没商量。 - h.alex
话虽如此,对我来说这个解决了问题。我已经掉太多头发了。 - h.alex

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中正常工作,没有错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接