Reputation: 5078
I have a ControlTemplate which uses the same color in multiple elements. On certain triggers (e.g. OnMouseOver) I'd like to change that color. As far as I can see I have to define a setter for every element to change its color. Is there a way to reference a shared resource in the template that all contained elements can access, and which can be changed by a trigger, so I don't have to address each and every element?
Here's an (made up) example:
<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>
When the control is disabled, I want the ellipses to be grey, without setting both of them explicitly, e.g. I don't want to write
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="_ellipse1" Property="Fill" Value="Grey"/>
<Setter TargetName="_ellipse2" Property="Fill" Value="Grey"/>
</Trigger>
but set the color of both ellipses with just one setter.
Upvotes: 0
Views: 1215
Reputation: 8227
Place the trigger on a style for the ellipses (ellipsi?) instead of the button. IsEnabled will propagate down if you set IsEnabled = false on the Button.
<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>
Upvotes: 2
Reputation: 15247
I think the best way to do this is with a value converter. Then you can avoid a messy trigger altogether. Here is your example, but with a converter added.
<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>
And here is the converter:
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();
}
}
Upvotes: 1