Change Image OnMouseOver in ControlTemplate - wpf

Here is my XAML:
<Style x:Key="ExpanderStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="IsEnabled" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Image Source="/Images/SHCalendarLeftArrow.tiff" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So how can I add a Trigger to that OnMouseOver the image in the ControlTemplate changes to a different image.

Try using a Trigger inside your template:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Image x:Name="PART_img" Source="/Images/SHCalendarLeftArrow.tiff" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_img"
Property="Source"
Value="/Images/SomeOtherImage.tiff" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>

Related

WPF "IsMouseOver" Trigger not Displaying Button Correctly

I have two png images, triple-checked to make sure they are properly transparent. Here is the button style code:
<Window.Resources>
<Style x:Key="TrackingButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Style.Triggers>
<!--Default Base-->
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image Source="Resources/Start_Base.png"/>
</Setter.Value>
</Setter>
</Trigger>
<!--Hover-->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="Resources/Start_Hover.png"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
<!--Default Style-->
<Style.Setters>
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Transparent"/>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="Transparent"/>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Window.Resources>
Here is the default state of the button: DefaultState
But when hovered over, the button loses its transparency and a white border appears around the areas that are supposed to be transparent: HoveredOver
I'm not sure what's going on here..
If you want to get rid of the chrome, you could define your own custom ControlTemplate:
<Style x:Key="TrackingButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image x:Name="img" Source="Resources/Start_Base.png"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="img" Property="Source" Value="Resources/Start_Hover.png" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF Button Style Background Image Swap on IsEnabled

We use a custom image for buttons in our project. We apply this via a style but now have a need to 'disable' the buttons and are trying to swap out the image for a new one.
The first Trigger works 100% as expected. When the button's IsEnabled == True, the button is 'green'. When the button's IsEnabled == False, the Green is removed and the Foreground color changes BUT the Grey image will not load up.
Am I missing something???
<Style TargetType="{x:Type Button}" x:Key="GreenGreyButton">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="..\Images\UI\Buttons\green.png"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#FFA30046"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="..\Images\UI\Buttons\grey.png"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</Style.Triggers>
</Style>
It's a pity that when the IsEnabled is false, the native style will override all settings (with the default gray background). You can however re-template the button like this:
<Style TargetType="{x:Type Button}" x:Key="GreenGreyButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}"
Margin="{TempateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="..\Images\UI\Buttons\green.png"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#FFA30046"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="..\Images\UI\Buttons\grey.png"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</Style.Triggers>
</Style>
Add the image as content to the button & use DatatTrigger instead, like this:
<Button...
>
<StackPanel>
<Image>
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="True">
<Setter Property="Source" Value="..\Images\UI\Buttons\green.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="False">
<Setter Property="Source" Value="..\Images\UI\Buttons\grey.png"/>
<Setter Property="Foreground" Value="Gray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>
</Button>
You need to set default values for your properties
<Style TargetType="{x:Type Button}" x:Key="GreenGreyButton">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="..\Images\UI\Buttons\green.png"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#FFA30046"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="..\Images\UI\Buttons\grey.png"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</Style.Triggers>

WPF Datagrid Selected Row Color and Centered Text

I have a simple DataGrid where I want to Style the selected row and center the text. I have tried the following and it does not work:
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Blue" />
<Setter Property="Foreground" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
Why will the above not work together? If I remove the trigger, it will center but the color I want will not be used.
Try add Grid to the ControlTemplate of DataGridCell style:
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter Margin="2"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>

Style expander buttons of TreeView

Here is my XAML:
<Style x:Key="ExpanderStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="IsEnabled" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Image Source="/Images/SHCalendarLeftArrow.tiff" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So what I want is so that if the item is expanded, then display a different image.
Nevermind. I used a trigger
<Trigger Property="ToggleButton.IsChecked" Value="False">
<Setter x:Name="Expander_Expanded"
TargetName="Expander_Normal" Property="Source"
Value="/Images/SHCalendarLeftArrow.tiff" />
</Trigger>

WPF Binding & Converters

I've been recently playing with WPF and I've come across a number of problems that I can't solve. I have the following code in my generic.xaml:
<Style TargetType="{x:Type local:ClearButton}">
<Style.Resources>
<con:ValueConverter x:Key="converter" />
</Style.Resources>
<Setter Property="Width" Value="20" />
<Setter Property="Height" Value="20" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ClearButton}">
<Grid>
<Image Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="/WPF-Libraries;component/Resources/ClearEnabled.png" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect Opacity="0.5" GlowColor="Red" GlowSize="3" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Source"
Value="/WPF-Libraries;component/Resources/ClearDisabled.png" />
</Trigger>
<!--Binding #1-->
<Trigger Property="{TemplateBinding local:ClearButton.IsPressed}" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<!--Binding #2-->
<ScaleTransform CenterX="CONVERTER BINDING:PASS WIDTH TO CONVERTER" CenterY="CONVERTER BINDING:PASS HEIGHT TO CONVERTER" ScaleX="0.75" ScaleY="0.75" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I can't get Binding #1 to work. I want to bind the trigger to the IsPressed property of the button, what should the binding be? Also what should the binding be for Binding #2 if I want to pass the button's Width and Height to the converter?
Also I could set the trigger this way instead:
<Style TargetType="{x:Type local:ClearButton}">
<Style.Resources>
<con:ValueConverter x:Key="converter" />
</Style.Resources>
<Setter Property="Width" Value="20" />
<Setter Property="Height" Value="20" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ClearButton}">
<!--Abbreviated-->
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<!--Binding #1-->
<Trigger Property="{TemplateBinding local:ClearButton.IsPressed}" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<!--Binding #2-->
<ScaleTransform CenterX="CONVERTER BINDING" CenterY="CONVERTER BINDING" ScaleX="0.75" ScaleY="0.75" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Which one is better and what would the binding be for Binding #1 and #2?
Both approaches are a little bit off. Your first approach is struggling to reach the IsPressed property using binding, however the Property property of the Trigger object is not a DependencyProperty so it doesn't support binding.
Your second approach is closer to the mark but still wrong, again uses binding on the Property property of the Trigger.
Check this out instead:
<Style TargetType="Button" x:Key="ClearButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<TextBlock
Name="x"
Text="I will change my color when ou press me"
TextAlignment="Center"
VerticalAlignment="Center"
Foreground="Red"
TextWrapping="Wrap"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter
TargetName="x"
Property="Foreground"
Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Notice that I put the trigger logic on the control template level (specifying the target element), not on the individual element (the TextBlock in this case).

Resources