Issue with Button Hover Image in WPF - wpf

I am attempting to change a button image when there is a mouse hover over in and I cant seem to get it to work. I have accomplished to get the blue hue to not appear when the button is hovered over but cannot get the image to change now. I have read numerous posts on it here and followed other examples but cant make it work. When I use the code below and hover over the button the image remains the same and doesn't change to the new one specified. Thoughts?
Blue Hue Removal
<Window.Resources>
<Style x:Key="ButtonStyleNoHighlighting" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Button Hover Image
<Button x:Name="btnCloseApp"
Click="Application_Close"
Style="{StaticResource ButtonStyleNoHighlighting}">
<Button.Background>
<ImageBrush ImageSource="Resources/BTN_Close.png"/>
</Button.Background>
<Button.Resources>
<ControlTemplate x:Key="BackgroundButton" TargetType="Button">
<Border Name="border" BorderThickness="1" BorderBrush="Black" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Resources/BTN_Close_Hover.png" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Resources>
</Button>
Any help would be greatly appreciated!

Related

WPF Button to CheckBoxTemplate

I am trying to give checkBox controltemplate to Button seeing an example in WPF Unleashed Text Book.
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Grid>
<Rectangle Width="20" Height="20" x:Name="outerCircle" Stroke="Black" StrokeThickness="0.5">
</Rectangle>
<Rectangle Width="10" Height="10" x:Name="InnerCircle">
</Rectangle>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter TargetName="outerCircle" Property="Stroke" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"></Setter>
</Trigger>
<Trigger Property="Button.IsPressed" Value="True">
<Setter TargetName="InnerCircle" Property="Fill" Value="Orange"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Button Template="{StaticResource buttoncheckBox}" Margin="10" Padding="10"/>
Here When I hover mouse or press it is not triggering events everywhere but only when I click on the border it is triggering.
When I use textbook example it is working anywhere what is difference I don't understand.
The problem is that the Grid you are using has no Background.
This is to fix your issue:
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Grid Background="Transparent" Width="20" Height="20">
.....
You will have to check to see how you can make this code work with different resolutions. Now it seems to be only for 20x20.
In general, when you don't set a Background for a control or a panel such as the Grid, the area is considered to belong to the parent window and that's why no mouse events get raised.
If you don't want any actual background you should still set the Background property of the Grid to Transparent for the mouse movements and the clicks to be registered.
You don't need to specify a fixed size for the Grid though. Just setting the Background should be enough:
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Grid Background="Transparent">
...
The only element that is currently available for hit test is the Rectangle.Stroke (the small border or line) When you interact with that thin line you will recognize that it will behave as you would expect. To make the whole Rectangle hit test visible you have to set the Rectangle.Fill property of both Rectangles:
<Rectangle Fill="Transparent" />
To allow the Button to resize properly use a Border. To enable the Button to display content like an icon or label text you need to add a ContentPresenter:
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Border x:Name="outerCircle"
Margin="{TemplateBinding Margin}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<Grid>
<Rectangle x:Name="InnerCircle" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver"
Value="True">
<Setter TargetName="outerCircle"
Property="BorderBrush"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}">
</Setter>
</Trigger>
<Trigger Property="Button.IsPressed"
Value="True">
<Setter TargetName="InnerCircle"
Property="Fill"
Value="Orange">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
and use it like this:
<Button Background="Transparent"
Width="80" Height="80"
Padding="5"
Template="{StaticResource buttoncheckBox}"
BorderBrush="Black"
BorderThickness="0.5"
Content="Label Text" />
Modify Button.Padding to resize the inner Rectangle.

WPF Remove Butto DropShadowEffect on click by ControlTemplate

In a Button ControlTemplate I need to access the IsPressed event. How do I do that?
Background: I added a drop DropShadowEffect to a Button Style but got blurry text. This fix solved the blurry text issue. However this added a new issue. I wanted to remove the DropShadowEffect when the user clicks on the button. Figured I would do it like this;
<Style x:Key="DropShadowButtons" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border Background="{TemplateBinding Background}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Border.Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Opacity="0.5" />
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Button.IsPressed" Value="False">
<Setter Property="Border.Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="320" ShadowDepth="0" BlurRadius="0" Opacity="0" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,2,5,0"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
Then figured out that Button.IsPressed would not fire being part of the Border. So how does the ControlTemplate access the event IsPressed of the Button?
You just need the trigger on the ControlTemplate instead of the Border's Style. For the Setter to target the Border, you'll need to give the Border a name, and you'll need to give the Setter a TargetName:
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border x:Name="BackgroundBorder" Background="{TemplateBinding Background}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Border.Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Opacity="0.5" />
</Setter.Value>
</Setter>
</Style>
</Border.Style>
</Border>
<Border Background="{TemplateBinding Background}">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="5,2,5,0"
/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="BackgroundBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect
Color="Black"
Direction="320"
ShadowDepth="0"
BlurRadius="0"
Opacity="0"
/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

How to rotate button image on pressed using style in WPF

I am implementeing a design for a WPF application for the moment.
I have on one of the pages a numeric keypad with the numbers 0 - 9 sitting inside a grid. In order to not inline style every button I have created a style for this button type.
The button contains two items: An Image and a TextBlock.
The Image is a small Svg image that looks like a metal phonebooth button.
The TextBlock is just the numbers 0..9 for each button.
Now I am trying to get the button to rotate its image 180 degrees when the button is pressed down. I can get the whole button to rotate on MouseOver but not the Image inside only...
Here is the Style where the whole button rotates on MouseOver:
<Style x:Key="NumericKeypadButton" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Image x:Name="MyRotation" Stretch="Fill" Source="{svgc:SvgImage Source=/Resources/Svg/keypad_key.svg}" RenderTransformOrigin=".5,.5">
<Image.RenderTransform>
<RotateTransform Angle="0" />
</Image.RenderTransform>
</Image>
<TextBlock HorizontalAlignment="Center" Margin="0,8,0,0" Style="{DynamicResource Lato}" FontSize="80" Text="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="180" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
You could do the rotation in the "Pressed" VisualState:
<Style x:Key="NumericKeypadButton" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="rotation"
Storyboard.TargetProperty="Angle"
To="180" Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Background="{TemplateBinding Background}">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<Image Stretch="Fill"
Source="{svgc:SvgImage Source=/Resources/Svg/keypad_key.svg}"
RenderTransformOrigin=".5,.5">
<Image.RenderTransform>
<RotateTransform x:Name="rotation" Angle="0" />
</Image.RenderTransform>
</Image>
<TextBlock HorizontalAlignment="Center"
Margin="0,8,0,0" FontSize="80" Text="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

progressbar bar style right radius

I'm trying to create a template for my progressebar with round corners but I have trouble implementing the right side of my progressbar.
Here is my template :
<ProgressBar Name="blabla" Value="80" Maximum="100" Margin="95,282,113,0">
<ProgressBar.Style>
<Style TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid Height="10" MinWidth="50" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate" />
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="00:00:00"
Storyboard.TargetName="PART_Indicator"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush>Transparent</SolidColorBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="PART_Track" CornerRadius="4" BorderThickness="1"
BorderBrush="{DynamicResource CouleurForegroundProgressBar}">
</Border>
<Border CornerRadius="4,0,0,4" BorderThickness="1" x:Name="PART_Indicator"
HorizontalAlignment="Left" Background="{DynamicResource CouleurForegroundProgressBar}"
BorderBrush="{DynamicResource CouleurForegroundProgressBar}"
Margin="0,0,0,0">
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource CouleurForegroundProgressBar}" />
</Style>
</ProgressBar.Style>
</ProgressBar>
And it looks like I wanted :
But When the value reaches 100% the progression bar inside (PART_Indicator) is still straight and hide my right radius :
How can I avoid that ?
Set CornerRadius="4" on your Part_Indicator also
<Border
CornerRadius="4"
BorderThickness="1"
x:Name="PART_Indicator"
HorizontalAlignment="Left"
Background="Red"
BorderBrush="Red"
Margin="0,0,0,0">
OR I will use the Triggers like below:
<Border BorderThickness="1"
x:Name="PART_Indicator"
HorizontalAlignment="Left"
Background="Red"
BorderBrush="Red"
Margin="0,0,0,0">
<Border.Style>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="4,0,0,4"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Value, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ProgressBar}}}" Value="100">
<Setter Property="CornerRadius" Value="4"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
Adding to Nitin's Answer, you'll have to change the names of the Border elements from "PART_Track" and "PART_Indicator" to "ProgressBarTrack" and "ProgressBarIndicator" respectively. If you don't, the bound value might go out of bounds if its width is bigger than the element.

Disable button mouse over effect

I have a wppf button with a background image.
When I mouse over background will be empty and a button is shown.
How can I disable mouse effect?
<Button BorderBrush="{x:Null}" Content="Reset" BorderThickness="0"Foreground="White" Focusable="False">
<Button.Background>
<ImageBrush ImageSource="button.png" />
</Button.Background>
Here's how I disable the visual mouseover effects on buttons. I left in some of my settings just to get you a feel of how to play with the triggers and stuff, feel free to experiment!
<Style TargetType="Button" x:Key="ImageButton" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="5"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Gainsboro" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.25" />
<Setter Property="BorderBrush" Value="Transparent" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
EDIT: Using the "BasedOn" + setting FocusVisualStyle to null (first 2 lines) gets rid of the mouse over effects. Everything else is just examples. I added a border there in order to play with it through a trigger (since I want a custom mouseover effect).
In the ControlTemplate of the Button the Background property will be overridden by a trigger.
You can either redo the whole ControlTemplate and leave out the Background change or just add the image as content of your Button like so to avoid all these complications:
<Button.Content>
<Image Source="button.png" />
</Button.Content>
Or if you need the text in there as well:
<Button.Content>
<Grid>
<Image Source="button.png" />
<TextBlock Text="Reset" VerticalAlignment="Center" HorizontalAlignment="Center" />
<Grid>
</Button.Content>

Resources