WPF ResourceDictionary Item уже был добавлен с использованием 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>
Я пытаюсь создать два разных шаблона данных для одного и того же DataType с разными 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");
}
}
Это работает, если у меня есть только один из шаблонов данных, но как только я добавляю второй, я получаю исключение, которое говорит:
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?
Есть ли способ обойти это исключение?
Спасибо Рауль
3 ответа
Если вы ссылаетесь на свой DataTemplate по ключу, не могли бы вы просто пропустить спецификацию DataType? Без DataType="{x:Type model:RequirementResourceRelation}" (который, очевидно, является ключом для добавленного элемента), ваш x:Key должен использоваться в качестве ключа.
Видимо проблема как заявлена, вроде. Порядок объявления стиля имеет значение.
Когда первым атрибутом для двух стилей для одного и того же 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, но это действительно глупая ошибка.
Переместить 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 без ошибок.