2016-03-04 5 views
0

У меня есть элемент ItemsControl и хочу, чтобы каждый элемент задавал свою цветную тему на основе содержащихся в ней данных. У меня есть 2 ресурсных словаря для 2 возможных тем (красный и синий) и DataTemplate, который определяет, как применять эти цвета. Как назначить текущий словарь ресурсов для каждой строки?Как применить различные цвета к каждому элементу в ItemsControl?

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfApplication1" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <ResourceDictionary> 
      <!-- 2 dictionaries with style colors --> 
      <ResourceDictionary x:Key="RedStyle"> 
       <SolidColorBrush x:Key="BorderBrush" Color="Red" /> 
       <SolidColorBrush x:Key="TextBrush" Color="Red" /> 
      </ResourceDictionary> 

      <ResourceDictionary x:Key="BlueStyle"> 
       <SolidColorBrush x:Key="BorderBrush" Color="Blue" /> 
       <SolidColorBrush x:Key="TextBrush" Color="Blue" /> 
      </ResourceDictionary> 

     </ResourceDictionary> 
    </Window.Resources> 
    <Grid> 
     <ItemsControl ItemsSource="{Binding list}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <Border BorderBrush="{StaticResource BorderBrush}"> 
         <TextBlock Text="{Binding}" Foreground="TextBrush" /> 
        </Border> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl>   
    </Grid> 
</Window> 

Update: DataTemplate и кисти наборы намного больше в моем реальном проекте. Я пытаюсь избежать дублирования кода макета DataTemplate, сохраняя при этом два разных стиля цвета.

+0

Вы желая присвоить цвет, основываясь на некотором атрибуте данных, которые шаблонного? Индекс? Что-то еще? –

+0

Да элементы содержат атрибут, который можно преобразовать в имя стиля – Poma

ответ

0

Документы, касающиеся вашей задачи, вы можете применить DataTriggers, как показано в следующем примере:

<ItemsControl.Style> 
    <Style> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding Items.TheAttribute}" Value="AttributeValue1"> 
       <Setter Property="BorderBrush" Value="Red"/> 
       <Setter Property="TextBrush" Value="Red"/> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Items.TheAttribute}" Value="AttributeValue2"> 
       <Setter Property="BorderBrush" Value="Blue"/> 
       <Setter Property="TextBrush" Value="Blue"/> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</ItemsControl.Style> 

В этом примере, вам не нужен Styles, указанный в вашем ResourceDictionary.

В качестве альтернативы вы можете использовать <Style.Triggers>, чтобы установить Style на ваш ResourceDictionary, а не устанавливать значения отдельных свойств.

Надеюсь, это поможет.

0

Примечание: Вы не можете применять ResourceDictionary условно, используя триггеры.

У вас есть четыре варианта в вашем распоряжении.

  1. Поместите свой DataTemplate в одном словаре ресурсов, или соответствующие DataTemplate с в отдельных словарей.

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
            xmlns:sys="clr-namespace:System;assembly=mscorlib"> 
    
    <DataTemplate DataType="{x:Type sys:String}"> 
        <TextBlock Text="{Binding .}"> 
         <TextBlock.Style> 
          <Style TargetType="TextBlock"> 
           <Style.Triggers> 
            <Trigger Property="Text" Value="Name1"> 
             <Setter Property="Background" Value="Red"/> 
            </Trigger> 
           </Style.Triggers> 
          </Style> 
         </TextBlock.Style> 
        </TextBlock> 
    </DataTemplate> 
    
    </ResourceDictionary> 
    

    Использование:

    <ItemsControl.Resources>    
          <ResourceDictionary Source="RedStyle.xaml"/> 
        </ItemsControl.Resources>    
    
  2. Использование DataTemplateSelector применить какую-то сложную логику и назначить DataTemplates соответственно. На этом есть хорошие tutorials.

  3. Используйте Blend Behaviors для этого, используя чистый XAML.

  4. Использование Loaded Событие управления, присутствующее в DataTemplate, для загрузки словаря Res Resurs с использованием кода. Самый простой подход!

     <DataTemplate> 
          <TextBlock Loaded="TextBlock_Loaded" Text="{Binding .}"/> 
         </DataTemplate> 
    

    Код:

    private void TextBlock_Loaded(object sender, RoutedEventArgs e) 
        { 
         TextBlock tb = sender as TextBlock; 
         if (tb.Text == "Name123") 
          tb.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("RedStyle.xaml", UriKind.Relative) }); 
        } 
    
+0

Я не понимаю некоторые части. Вы пишете примеры, как если бы у меня было несколько DataTemplates. У меня есть только 1 DataTemplate и 2 набора кистей. Я пытаюсь избежать дублирования кода макета DataTemplate, потому что один в моем реальном проекте довольно большой. – Poma

+0

@Poma Я предлагаю способы сделать. Потому что то, что вы пытаетесь сделать, невозможно. Условное обновление словаря Слова невозможно без кода. См. Мою последнюю часть, или обновите свой вопрос. – AnjumSKhan