How to change the style of a button when pressed - c#

I am trying to change the style of a button when I click on it while the app is running.
Like I have a button with a grey color, I want it to change to red when I click on it?
I tried to do it with the Click event, however the button still shows the default effect when I hover over the button.
Here is the WPF code I used.
<Style TargetType="Button" x:Key="btnExitDef">
<Setter Property="Background" Value="#FF1E1E1E"/>
<Setter Property="Foreground" Value="#FFD6D6D6"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="0"
BorderThickness="0"
Padding="0"
BorderBrush="#000">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center">
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="#fff"/>
</Trigger>
</Style.Triggers>
</Style>
<Button Height="35" Width="45" Name="btnExit" Content="✕" BorderBrush="{x:Null}" Click="btnExit_Click" Style="{StaticResource btnExitDef}"/>

You just need to edit the button's style and add another Trigger for the IsPressed property.
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>

Related

Hover rounded corner button change its background color using ResourceDictionary

I have created a ResourceDictionary style sheet that have a style named btn_default.
I plan to use it on all the buttons in my program. My problem is that when I hover the button then the background-color doesnt change. The font color changes.
button_default
button_default:hover
I tried in my code to change the "Setter Property="Background" Value="#b5b5b5"", however I guess that doesnt affect the Border-tag, but the Style-tag?
ResourceDictionary
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample">
<!-- Btn default -->
<Style x:Key="btn_default" TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="Calibri"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#d9d9d9" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" BorderThickness="1" Padding="6,4,6,4" Background="#6c6c6c" BorderBrush="#393939">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#b5b5b5"/>
<Setter Property="Foreground" Value="#000000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- //Btn default -->
</ResourceDictionary>
Main
<Button x:Name="buttonExplorer" Content="Explorer" Style="{StaticResource btn_default}" Margin="0,0,6,0" />
<Button x:Name="buttonProcess" Content="Process" Style="{StaticResource btn_default}" Margin="0,0,6,0" />
You should declare Background property of Border using TemplateBinding extension and set Background value in Style setter, otherwise it'll never be updated
<Style x:Key="btn_default" TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="Calibri"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#d9d9d9" />
<Setter Property="Background" Value="#6c6c6c"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" BorderThickness="1" Padding="6,4,6,4" BorderBrush="#393939" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#b5b5b5"/>
<Setter Property="Foreground" Value="#000000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF: Move focus to previous control (SHIFT + Tab) when using ControlTemplate with Placeholder Textbox

I created a WPF TextBox with Placeholder text by creating a customized Style that overlays one TextBox (as a placholder text) on another TextBox in the ControlTemplate.
Here's the Style definition:
<Style x:Key="TextBoxFormBaseStyle"
BasedOn="{StaticResource {x:Type TextBox}}"
TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox x:Name="_textSource"
Panel.ZIndex="2"
Background="Transparent"
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="_textTag"
Panel.ZIndex="1"
Focusable="False"
Text="{TemplateBinding Tag}">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference _textSource}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, Source={x:Reference _textSource}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
<!-- Move Focus to child control -->
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="_textSource" Property="FocusManager.FocusedElement" Value="{Binding ElementName=_textSource}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
A Trigger on Property IsFocused allows focusing the the child TextBox control (named _textSource) when navigating through multiple TextBox's by Tab key.
Navigating to the previous element by pressing SHIFT + Tab is not working. How can I get SHIFT + Tab to set the focus to the previous element?
There are better ways to add a watermark if you want the TextBox to actuallty behave and get focused like a built-in TextBox. Try this style:
<Style x:Key="TextBoxFormBaseStyle" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="1"/>
<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">
<Grid>
<TextBox x:Name="_textTag"
Focusable="False"
Text="{TemplateBinding Tag}"
BorderThickness="0">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, RelativeSource={RelativeSource AncestorType=TextBox}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Sample usage:
<TextBox OpacityMask="Red" Tag="Red Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />
<TextBox OpacityMask="Green" Tag="Green Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />

ToggleButton Trigger IsChecked Doesn't Change Background

I have a ToggleButton with a red background. I need to set a green background when the toggle button is checked.
I've tried this:
<ToggleButton Content="Test 001" Name="btn03" Height="20">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Background" Value="#ff0000" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="#00ff00" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
But instead a green color I get a light blue color (I think is the default color of my
system).
What I'm doing wrong and how to fix it?
WPF 4.0 doesen't allow this. Look here for a different approach:
<Grid>
<Grid.Resources>
<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="border" Background="Red">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ToggleButton Content="ToggleButton" Style="{StaticResource ToggleButtonStyle}"/>
</Grid>

Change button background color due to events and view model property

I have a button that can be at one of three modes:
Normal - No mouse hover and not selected
Hover - Mouse hover and not selected
Selected - A property at the view model (DataContext) called IsSelected equals true
This is my current code:
<Style x:Key="FlatButtonStyle" TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Orange"/>
</Trigger>
<DataTrigger Binding="{Binding IsSelected}">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="Background" Value="Gray" />
<Setter Property="Foreground" Value="White"/>
<Setter Property="Width" Value="125"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border BorderThickness="0"
Background="{TemplateBinding Background}"
CornerRadius="12">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, only the Hover and normal states work.
I tried data triggers, visual state manager but I'm new to WPF and couldn't make it work.
Your IsSelected Trigger Value is missing. If you want to stick with a button use
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
I will recommend to use ToggleButton and Trigger on IsChecked Property
<ToggleButton IsChecked="{Binding IsSelected}" Style="{StaticResource FlatButtonStyle}"/>
<Style x:Key="FlatButtonStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Orange"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
<Setter Property="Background" Value="Gray" />
<Setter Property="Foreground" Value="White"/>
<Setter Property="Width" Value="125"/>
<Setter Property="Height" Value="35"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border BorderThickness="0"
Background="{TemplateBinding Background}"
CornerRadius="12">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try useing Toggle Button instead of Button control. it has by default IsChecked state. Here is an exaple of how to use toggle button
http://miteshsureja.blogspot.ae/2011/12/wpf-toggle-button.html

Programmatically Setting ControlTemplate Item

I'm having trouble figuring out how to programmatically setting the "Stroke" of my arrow. I'm using these buttons in a menu bar and I want the one currently selected to have it's arrow change to green and all the others gray.
<Style x:Key="FooterGrayButtonStyle" TargetType="{x:Type Button}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="MinHeight" Value="35" />
<Setter Property="FontSize" Value="16"/>
<Setter Property="Margin" Value="0,5,10,5" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border x:Name="Bd" Background="#FF535A65" BorderBrush="Black" BorderThickness="1" CornerRadius="10">
<Path x:Name="arrow" Stretch="Fill" Stroke="#FFB1BB1C" StrokeThickness="5" HorizontalAlignment="Right" Margin="5"
StrokeEndLineCap="Round" StrokeStartLineCap="Round" StrokeLineJoin="Miter" Width="13" Height="23" Data="M0,0 L1,1 0,2" />
</Border>
<ContentPresenter HorizontalAlignment="Left" Margin="15,-2,30,0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#FFB1BB1C" />
<Setter Property="Stroke" TargetName="arrow" Value="White"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Stroke" TargetName="arrow" Value="#FFB7B7B7"/>
<Setter Property="Foreground" Value="#FFB7B7B7"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You generally want to express something that is a state being expressed visually as a property on the control. Button doesn't have a built in property to express a selected state, but ToggleButton does: IsChecked. If you can't use a ToggleButton you could create an Attached Property that can be set from your code that's determining the currently selected Button. That could then be used in a Trigger in the same way you would use IsChecked:
<Trigger Property="local:MyProperties.IsSelected" Value="True">
<Setter TargetName="arrow" Property="Stroke" Value="Green"/>
</Trigger>
Can't you add a trigger:
<Trigger Property="IsFocused" Value="True">
<Setter Property="StrokeEndLineCap" Value="Arrow" TargetName="arrow"/>
</Trigger>
Or is it the Path not updating with your triggers that is the problem?

Categories

Resources