Изменить общий цвет в ControlTemplate

У меня есть ControlTemplate, который использует один и тот же цвет в нескольких элементах. Для определенных триггеров (например, OnMouseOver) я хотел бы изменить этот цвет. Насколько я вижу, мне нужно определить сеттер для каждого элемента, чтобы изменить его цвет. Есть ли способ сослаться на общий ресурс в шаблоне, к которому могут получить доступ все содержащиеся элементы и который можно изменить с помощью триггера, чтобы мне не приходилось обращаться к каждому элементу?

Вот (придуманный) пример:

<ControlTemplate x:Key="myTemplate" TargetType="{x:Type Button}">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition/>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Ellipse Fill="red" Grid.Column="0"/>
    <Ellipse Fill="red" Grid.Column="1"/>
    <ContentPresenter Grid.ColumnSpan="2" VerticalAlignment="Center"/>
 </Grid>
</ControlTemplate>

Когда элемент управления отключен, я хочу, чтобы эллипсы были серыми, не устанавливая их оба явно, например. Я не хочу писать

<Trigger Property="IsEnabled" Value="False">
  <Setter TargetName="_ellipse1" Property="Fill" Value="Grey"/>
  <Setter TargetName="_ellipse2" Property="Fill" Value="Grey"/>
</Trigger>

но установите цвет обоих эллипсов с помощью одного сеттера.


person Thomas Freudenberg    schedule 07.08.2009    source источник


Ответы (2)


Поместите триггер на стиль многоточия (многоточие?) вместо кнопки. IsEnabled будет распространяться вниз, если вы установите IsEnabled = false на кнопке.

<ControlTemplate x:Key="myTemplate" TargetType="{x:Type Button}">
    <ControlTemplate.Resources>
        <Style TargetType="{x:Type Ellipse}">
            <Setter Property="Fill" Value="Red" />
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Fill" Value="Gray" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ControlTemplate.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Ellipse Grid.Column="0"/>
        <Ellipse Grid.Column="1"/>
        <ContentPresenter Grid.ColumnSpan="2" VerticalAlignment="Center"/>
    </Grid>
</ControlTemplate>
person Bryce Kahle    schedule 08.08.2009
comment
Это сделало трюк самым простым способом, спасибо. (хотя мне пришлось выяснить, что вы не должны определять цвет в ControlTemplate, а исключительно в стиле.) - person Thomas Freudenberg; 09.08.2009
comment
Спасибо - именно тот синтаксис, который мне был нужен - person Mark Pim; 10.05.2010

Я думаю, что лучший способ сделать это с преобразователем значений. Тогда вы можете вообще избежать грязного триггера. Вот ваш пример, но с добавленным преобразователем.

<Window.Resources>
  <local:EnabledToColorConverter x:Key="enabledToColorConverter"/>
  <ControlTemplate x:Key="myTemplate" TargetType="{x:Type Button}">
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <Ellipse Name="_ellipse1" Fill="{TemplateBinding IsEnabled, Converter={StaticResource enabledToColorConverter}}" Grid.Column="0"/>
      <Ellipse Name="_ellipse2" Fill="{TemplateBinding IsEnabled, Converter={StaticResource enabledToColorConverter}}" Grid.Column="1"/>
      <ContentPresenter Grid.ColumnSpan="2" VerticalAlignment="Center"/>
    </Grid>
  </ControlTemplate>
</Window.Resources>

<StackPanel>
  <Button Template="{StaticResource myTemplate}">Enabled Button</Button>
  <Button Template="{StaticResource myTemplate}" IsEnabled="False">Disabled Button</Button>
</StackPanel>

А вот конвертер:

public class EnabledToColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool isEnabled = (bool)value;
        return isEnabled ?
            Brushes.Red :
            Brushes.Gray;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
person Charlie    schedule 07.08.2009
comment
Это довольно уродливое решение, потому что цвета жестко закодированы в преобразователе значений (к сожалению, IValueConverter.Convert принимает только один параметр), но это может помочь. Я попробую это. - person Thomas Freudenberg; 08.08.2009
comment
Нет, вы можете использовать ConverterParameter для привязки и передавать разные цвета. Или вы можете определить цвета статически и таким образом получить к ним доступ. - person Charlie; 08.08.2009