【问题标题】:WPF ResourceDictionary Item has already been added using ComponentResourceKey已使用 ComponentResourceKey 添加 WPF ResourceDictionary Item
【发布时间】:2010-07-29 21:49:33
【问题描述】:

我将以下 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 创建两个不同的数据模板。如您所见,其中一个键附加了一个 2。

在我的 local: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 属性?

有什么办法可以解决这个异常?

谢谢, 劳尔

【问题讨论】:

    标签: wpf exception resourcedictionary componentresourcekey


    【解决方案1】:

    显然问题如上所述。样式声明的顺序很重要。

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

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

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

    当同一个TargetType的两个样式的第一个元素是x:Key,那么就不用了,如下图。

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

    我猜,如果你移动垃圾也没关系。聪明人的话,总是以 x:Key 开头,但这是一个非常愚蠢的错误。

    【讨论】:

    • IMO 中的最佳答案。让我停留了一段时间,怀疑我对 WPF 的全部理解。没有意识到 XAML 中参数的顺序会有所不同,但显然确实如此。
    • 我永远无法自己解决这个问题。干得好!
    • 不错的发现。属性顺序应该不重要(应该)?没想到我做错了什么。
    【解决方案2】:

    如果您通过键引用您的 DataTemplate,您就不能省略 DataType 规范吗? 没有 DataType="{x:类型模型:RequirementResourceRelation}" (这显然是添加项目的关键)您的 x:Key 应该用作关键。

    【讨论】:

    • 很棒的解决方法。我已将此作为错误提交给 Microsoft。 connect.microsoft.com/VisualStudio/feedback/details/581761/…
    • 这个错误仍然存​​在。极好的!!我正在将 TextBlock 的两种样式添加到应用程序资源字典中。卡住了这个错误。完全,完全令人沮丧。我想用我的键盘砸我的屏幕。微软打击。期间。
    • 话虽如此,this 已为我修复了它。我掉头发太多了。
    【解决方案3】:

    DataTemplate(s) 移动到另一个控件的&lt;Resources&gt; 元素内。

    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 中都可以正常工作,而不会出现错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-20
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      • 2012-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多