I'd like to define a WPF ControlTemplate
for a "color swatch" button. Essentially, I want to be able to use the template like this:
<Button Template="{StaticResource SwatchButtonTemplate}" Background="{Binding ActiveColor}">
Where ActiveColor
is a Color
property in the data context. I've been able to achieve that with this template:
<ControlTemplate x:Key="SwatchButtonTemplate" TargetType="{x:Type Button}">
<Border Name="OuterBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource BorderBrush}" Background="{TemplateBinding Background}">
<Border Name="InnerBorder" BorderThickness="0" BorderBrush="White" Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="OuterBorder" Property="BorderThickness" Value="1"/>
<Setter TargetName="InnerBorder" Property="BorderThickness" Value="1"/>
<Setter TargetName="OuterBorder" Property="BorderBrush" Value="{StaticResource MouseOverAccentBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
But now what I'd like to do is use a special brush for the button background if the color is transparent (e.g. display a red "X" in the background if the color is transparent).
I can't seem to figure out how to set up a trigger in the template that checks the background color, and if it is transparent, use a different brush for the Background property. I've tried adding a DataTrigger to the template:
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
...
</Trigger>
<DataTrigger Binding="{TemplateBinding Background}" Value="#00000000">
<Setter TargetName="InnerBorder" Property="Background" Value="{StaticResource transparent_swatch_brush}"/>
</DataTrigger>
</ControlTemplate.Triggers>
But I get a XamlParseException when using this.
Edit: The full usage of this template is in a list of swatch buttons, and the source of the list is bound to an ObservableCollection<Brush>
called ColorList
populated with SolidColorBrushes
(one of which is transparent)
<ItemsControl ItemsSource="{Binding ColorList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button x:Name="button" Background="{Binding}"
Template="{StaticResource SwatchButtonTemplate}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Height="20" Rows="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
And the full template definition:
<ControlTemplate x:Key="SwatchButtonTemplate" TargetType="{x:Type Button}">
<Border Name="OuterBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource BorderBrush}" Background="{TemplateBinding Background}">
<Border Name="InnerBorder" BorderThickness="0" BorderBrush="White" Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="OuterBorder" Property="BorderThickness" Value="1"/>
<Setter TargetName="InnerBorder" Property="BorderThickness" Value="1"/>
<Setter TargetName="OuterBorder" Property="BorderBrush" Value="{StaticResource MouseOverAccentBrush}"/>
</Trigger>
<DataTrigger Binding="{Binding Background, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="#00ffffff">
<Setter TargetName="InnerBorder" Property="Background" Value="{StaticResource transparent_swatch_brush}"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Thanks to @EdPlunkett for the suggestion to avoid "{TemplateBinding ...}" in the data trigger. The solution (XAML only) is to use a "Self" relative source:
<ControlTemplate x:Key="SwatchButtonTemplate" TargetType="{x:Type Button}">
<Border Name="OuterBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{StaticResource BorderBrush}" Background="{TemplateBinding Background}">
<Border Name="InnerBorder" BorderThickness="0" BorderBrush="White" Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="InnerBorder" Property="BorderThickness" Value="1" />
</Trigger>
<DataTrigger Binding="{Binding Path=Background.Color, RelativeSource={RelativeSource Self}}" Value="#00ffffff">
<Setter TargetName="InnerBorder" Property="Background" Value="{StaticResource transparent_swatch_brush}" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
(also note that Colors.Transparent is #00ffffff, not #00000000 as I thought).