I want to have a GeometryDrawing
inside a Button
that changes it's Geometry
when the mouse is over the Button
:
<Style TargetType="{x:Type Button}">
<Setter Property="Content">
<Setter.Value>
<Rectangle>
<Rectangle.Fill>
<DrawingBrush>
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<!-- This Binding works -->
<GeometryDrawing Brush="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Geometry="M8,8 1,8 1,3 8,3z M9,9 0,9 0,0 9,0z" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Content">
<Setter.Value>
<Rectangle>
<Rectangle.Fill>
<DrawingBrush>
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<!-- This Binding does not work -->
<GeometryDrawing Brush="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
Geometry="M6,9 1,9 1,5 6,5z M7,10 0,10 0,3 7,3z M10,7 7,7 7,6 9,6 9,2 4,2 4,3 3,3 3,0 10,0z" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
However, it gives me this error
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.Button', AncestorLevel='1''.
and I do not know why, since the Binding does work in the Style
's Setter
, but not in the Style
's Trigger
's Setter
.
I have no idea why it does not work in the latter or how to solve it.
Any help is greatly appreciated!
EDIT:
I also tried {TemplateBinding Button.Foreground}
and {RelativeSource = {RelativeSource TemplatedParent}}
, which both did not work, so the question now is: how can I bind to a property on the Style
's target in a Trigger
?
Changing the Content
from Style
Setters
and Triggers
is bad practice, it allows all kinds of issues with the style caching elements and using the same element as the content for multiple buttons in your case, which is not allowed in wpf.
The Binding
from the Triggers
cannot work since it's not in the same visual tree as the button at the moment of creation. This is what the data error is telling you.
What you really want is to change the ControlTemplate
of the button. The difference is that new elements from ControlTemplate
is created for each button that has this style.
Control template sample:
<ControlTemplate x:Key="ButtonBaseControlTemplate1" TargetType="{x:Type ButtonBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<Rectangle x:Name="normalIcon">
//same as before
</Rectangle>
<Rectangle x:Name="mouseOverIcon" Visibility="Collapsed">
//same as before
</Rectangle>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
//other triggers from default template
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFBEE6FD"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
<Setter Property="Visibility" TargetName="normalIcon" Value="Collapsed"/>
<Setter Property="Visibility" TargetName="mouseOverIcon" Value="Visible"/>
</Trigger>
//other triggers from default template
</ControlTemplate.Triggers>