WPF Trigger Not Working As Intended - wpf

I want a red button that turns black when the mouse hovers over it.
<Button Content="Hover me" Grid.Column="3" Grid.Row="3">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
However, my problem is that when I hover over the button, it turns into the default Windows style with a gradient gray appearance.

Try it
<Window.Resources>
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter x:Name="PART_Content"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}"></ContentPresenter> </Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
and apply the custom Style as following
<Button Content="Hover me" Style="{StaticResource MyButtonStyle}" Height="30" Width="100"/>
The reason is the default Aero style of a Button. It has a chrome defined in ControlTemplate, which has it own behavior on various mouse events. So That over write your trigger call.
So you must override default ControlTemplate of Button to achieve your desired result.

Related

How to change border color using triggers in WPF?

I need to change border color of one text box when mouse hover him, but with solution i write it does not work. Is there mistake in my code?
Background color changes, but border no.
Code below is my idea.
<Style x:Key="BorderColor" TargetType="TextBox">
<Setter Property="FontStyle" Value="Normal"/>
<Style.Triggers>
<Trigger Property="TextBox.IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</Style.Triggers>
A quick and easy way to do this is to simply set the TextBox border thickness to 0 and encapsulate it in a parent border:
<Border BorderThickness="1" Width="500" Height="20" >
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="Black" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBox x:Name="theTextBox" BorderThickness="0" />
</Border>
The "proper" way to do this is to template the entire control:
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Color of button border is controlled by template triggers of a button via button (Templated Parent) properties. Since priority of such triggers is almost the top most, you need to redefine control template of a button.
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-property-value-precedence

Changing the background of a WPF button to a solid color when mouse is rolled over? [duplicate]

My problem is that in WPF, whenever I try and change the colour of a button's background using triggers or animations, the default mouseover effect (of being grey with that orange glow) seems to take priority.
After extensive searches I'm clueless as to how to remove this effect.
This is similar to the solution referred by Mark Heath but with not as much code to just create a very basic button, without the built-in mouse over animation effect. It preserves a simple mouse over effect of showing the button border in black.
The style can be inserted into the Window.Resources or UserControl.Resources section for example (as shown).
<UserControl.Resources>
<!-- This style is used for buttons, to remove the WPF default 'animated' mouse over effect -->
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
BorderThickness="1"
Padding="4,2"
BorderBrush="DarkGray"
CornerRadius="3"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<!-- usage in xaml -->
<Button Style="{StaticResource MyButtonStyle}">Hello!</Button>
Just to add a very simple solution, that was good enough for me, and I think addresses the OP's issue. I used the solution in this answer except with a regular Background value instead of an image.
<Style x:Key="SomeButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
No re-templating beyond forcing the Background to always be the Transparent background from the templated button - mouseover no longer affects the background once this is done. Obviously replace Transparent with any preferred value.
You need to create your own custom button template to have full control over the appearance in all states. Here's a tutorial.
The Muffin Man had a very simple answer which worked for me.
To add a little more specific direction, at least for VS 2013:
Right-click the control
Select Edit Template => Edit a copy...
I selected 'Application' for where to save the style
From here you can directly edit App.xaml and see the intuitively named properties. For my purposes, I just set RenderMouseOver="False"
Then, in the MainWindow.xaml or wherever your GUI is, you can paste the new style at the end of the Button tag, e.g. ... Style="{DynamicResource MouseOverNonDefault}"/>
This Link helped me alot
http://www.codescratcher.com/wpf/remove-default-mouse-over-effect-on-wpf-buttons/
Define a style in UserControl.Resources or Window.Resources
<Window.Resources>
<Style x:Key="MyButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Then add the style to your button this way Style="{StaticResource MyButton}"
<Button Name="btnSecond" Width="350" Height="120" Margin="15" Style="{StaticResource MyButton}">
<Button.Background>
<ImageBrush ImageSource="/Remove_Default_Button_Effect;component/Images/WithStyle.jpg"></ImageBrush>
</Button.Background>
</Button>
If someone doesn't want to override default Control Template then here is the solution.
You can create DataTemplate for button which can have TextBlock and then you can write Property trigger on IsMouseOver property to disable mouse over effect. Height of TextBlock and Button should be same.
<Button Background="Black" Margin="0" Padding="0" BorderThickness="0" Cursor="Hand" Height="20">
<Button.ContentTemplate>
<DataTemplate>
<TextBlock Text="GO" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextDecorations="Underline" Margin="0" Padding="0" Height="20">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property ="IsMouseOver" Value="True">
<Setter Property= "Background" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</Button.ContentTemplate>
</Button>
An extension on dodgy_coder's answer which adds support for..
Maintaining WPF button style
Adds support for IsSelected and hover, i.e. a toggled button
<Style x:Key="Button.Hoverless" TargetType="{x:Type ButtonBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border Name="border"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="Selector.IsSelected" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="#FFBEE6FD" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="Selector.IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="#BB90EE90" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="False" />
<Condition Property="Selector.IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="LightGreen" />
</MultiTrigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Opacity" Value="0.95" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
examples..
<Button Content="Wipe On" Selector.IsSelected="True" />
<Button Content="Wipe Off" Selector.IsSelected="False" />
Using a template trigger:
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="White"></Setter>
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Change Border Thickness by Xaml, `wpf`

Please keep in mind i am new with WPF, I am trying to give my Button a border thickness value via .Xaml templates, However, its not working, Here is my .Xaml:
<Button>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#FFFFFFFF" />
<Setter Property="Foreground" Value="#FFF01F1F" />
<Setter Property="BorderBrush" Value="#FFF01F1F" />
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="#FFF01F1F" />
<Setter Property="Foreground" Value="#FFFFFFFF" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Thanks in Advance.
Update:::
I have tried the Change Thickness answer, however now it disables my IsMouseOver property,
You set your own custom template which doesn't use the BorderThickness property of the button itself, so it should be:
<Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
Or you can set it to 5 directly on the template.

Setting border size on button on mouse over in WPF

I am trying to set the border colour property on a button when user hovers on it. Currently I am using following XAML.
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#FF0081a7"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="2,2,2,2"/>
<Setter Property="Foreground" Value="#FFffffff"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#ccCCCCCC"/>
<Setter Property="BorderBrush" Value="Gold"/>
<Setter Property="BorderThickness" Value="2,2,2,2"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
This works fine only for colour changes. Border on the other hand is not displayed at all. I am sure, I am missing something very simple, only thing is I can't find what it is.
You're not actually utilising the BorderBrush and BorderThickness properties... you need to actually do something with them from inside your ControlTemplate. Try this:
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding
BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>

How to remove default mouse-over effect on WPF buttons?

My problem is that in WPF, whenever I try and change the colour of a button's background using triggers or animations, the default mouseover effect (of being grey with that orange glow) seems to take priority.
After extensive searches I'm clueless as to how to remove this effect.
This is similar to the solution referred by Mark Heath but with not as much code to just create a very basic button, without the built-in mouse over animation effect. It preserves a simple mouse over effect of showing the button border in black.
The style can be inserted into the Window.Resources or UserControl.Resources section for example (as shown).
<UserControl.Resources>
<!-- This style is used for buttons, to remove the WPF default 'animated' mouse over effect -->
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
BorderThickness="1"
Padding="4,2"
BorderBrush="DarkGray"
CornerRadius="3"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<!-- usage in xaml -->
<Button Style="{StaticResource MyButtonStyle}">Hello!</Button>
Just to add a very simple solution, that was good enough for me, and I think addresses the OP's issue. I used the solution in this answer except with a regular Background value instead of an image.
<Style x:Key="SomeButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
No re-templating beyond forcing the Background to always be the Transparent background from the templated button - mouseover no longer affects the background once this is done. Obviously replace Transparent with any preferred value.
You need to create your own custom button template to have full control over the appearance in all states. Here's a tutorial.
The Muffin Man had a very simple answer which worked for me.
To add a little more specific direction, at least for VS 2013:
Right-click the control
Select Edit Template => Edit a copy...
I selected 'Application' for where to save the style
From here you can directly edit App.xaml and see the intuitively named properties. For my purposes, I just set RenderMouseOver="False"
Then, in the MainWindow.xaml or wherever your GUI is, you can paste the new style at the end of the Button tag, e.g. ... Style="{DynamicResource MouseOverNonDefault}"/>
This Link helped me alot
http://www.codescratcher.com/wpf/remove-default-mouse-over-effect-on-wpf-buttons/
Define a style in UserControl.Resources or Window.Resources
<Window.Resources>
<Style x:Key="MyButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Then add the style to your button this way Style="{StaticResource MyButton}"
<Button Name="btnSecond" Width="350" Height="120" Margin="15" Style="{StaticResource MyButton}">
<Button.Background>
<ImageBrush ImageSource="/Remove_Default_Button_Effect;component/Images/WithStyle.jpg"></ImageBrush>
</Button.Background>
</Button>
If someone doesn't want to override default Control Template then here is the solution.
You can create DataTemplate for button which can have TextBlock and then you can write Property trigger on IsMouseOver property to disable mouse over effect. Height of TextBlock and Button should be same.
<Button Background="Black" Margin="0" Padding="0" BorderThickness="0" Cursor="Hand" Height="20">
<Button.ContentTemplate>
<DataTemplate>
<TextBlock Text="GO" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextDecorations="Underline" Margin="0" Padding="0" Height="20">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property ="IsMouseOver" Value="True">
<Setter Property= "Background" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</Button.ContentTemplate>
</Button>
An extension on dodgy_coder's answer which adds support for..
Maintaining WPF button style
Adds support for IsSelected and hover, i.e. a toggled button
<Style x:Key="Button.Hoverless" TargetType="{x:Type ButtonBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border Name="border"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="Selector.IsSelected" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="#FFBEE6FD" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="Selector.IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="#BB90EE90" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="False" />
<Condition Property="Selector.IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="LightGreen" />
</MultiTrigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Opacity" Value="0.95" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
examples..
<Button Content="Wipe On" Selector.IsSelected="True" />
<Button Content="Wipe Off" Selector.IsSelected="False" />
Using a template trigger:
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="White"></Setter>
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources