WPF Button change color when disabled - c#

The code below is a snippet from a programme. The button that is pressed is now set to red.
private void Disk_click(object sender, RoutedEventArgs e)
{
((Button)sender).Background = Brushes.Red;
((Button)sender).Foreground = Brushes.Red;
// here is the button colored red
((Button)sender).IsEnabled = false;
// here is the button again grey
}
The intention is that when a button is pressed, the colour will change and then the button will be disabeld. The colour must be preserved on the button. The colours that can occur are: red, blue, green and yellow.
But if I disable the button, the colour is not retained. The colour must be adjustable from this c# code.
Does anyone know how I can solve this? Or what I am doing wrong?
All help is highly appreciated!

It would be more accurate to edit the button design on the xaml side instead of the code behind.
You can use the Style property for this.
In case IsHitTestVisible is false, you can set the controls you want according to your taste when it is true.
<Button Name="Button1" Width="100"
Height="20"
Content="Click"
Click="Disk_click">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsHitTestVisible" Value="False">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="IsHitTestVisible" Value="True">
<Setter Property="Background" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

The button colour is being overridden by the Disabled style which is set in the Xaml.
In the Xaml code of the button, you can set the disabled Background & Foreground colour which will allow it to persist.

Have you considered using a Controltemplate with Triggers?
Usually requierments like yours are achieved using Templates and Styles.
A Controltemplate might look something like this:
<ControlTemplate x:Key="ButtonControlTemplate" TargetType="{x:Type Button}">
<Border x:Name="border" Height="Auto" Width="65" BorderThickness="0" Background="Transparent">
<StackPanel x:Name="Control" Margin="5,0,5,0" Orientation="Horizontal" MinHeight="25" VerticalAlignment="Center">
<TextBlock VerticalAlignment="Center" x:Name="Icon" FontSize="16" Foreground="Red"></TextBlock>
<ContentPresenter x:Name="contentPresenter" Margin="5,0,0,0" VerticalAlignment="Center"></ContentPresenter>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#FFF4F4F4" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="Foreground" Value="#FF838383"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsEnabled" Value="True"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter TargetName="border" Property="Background" Value="#FFF4F4F4" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
If it must be done with C# code you could try something like this:
if(myButton.IsEnabled == true)
{
//do logic here
// Button Red
} else
{
//do logic here
//Button Gray
}
Hope i could help.

Following button style would be helpful;
<Window
x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Background" Value="LightGray" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter
x:Name="MyContentPresenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button
Width="75"
Height="35"
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="Button_Click"
Content="Button"
Style="{StaticResource MyButtonStyle}" />
</Grid>
On Click;
private void Button_Click(object sender, RoutedEventArgs e)
{
((Button)sender).IsEnabled = false;
}
Result;

Related

Button's trigger IsMouseOver stops working after button's background is set in code-behind

I want the background of a button to change when the cursor hovers over the button.
I have managed to do this in a style which use the "IsMouseOver" trigger which sets the button's background to red.
I also want the button to alter it's background between two colors when the click event occurs.I have managed to do this in the code-behind of the Window which switches between blue and green.
The problem
The trigger works as expected as long as I don't click the button.
When I click the button, the background is changed to either blue or green as expected.
If I then afterwards hover the button, the background is not set to red while hovering with the cursor.
XAML-code
<Window x:Class="Main.MainWindow">
<Window.Resources>
<Style x:Key="FooStyle" TargetType="Button">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="Transparent">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Orientation="Vertical">
<Button x:Name="btnFoo"
Content="Foo"
Width="100"
Click="Foo_Click"
Style="{StaticResource FooStyle}" />
</StackPanel>
</Window>
Window code-behind
private void Foo_Click(object sender, RoutedEventArgs e)
{
btnFoo.Background = btnFoo.Background == Brushes.Blue ? Brushes.Lime : Brushes.Blue;
}
I suspect the trigger actually works but it something else here which is the problem.
What could be the problem?
How to solve this?
What could be the problem?
The fact that local values take precedence over style setters and triggers as explained in the docs.
How to solve this?
For example by moving the trigger to the ControlTemplate:
<Style x:Key="FooStyle" TargetType="Button">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="Transparent">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="Red" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Window.Resources>
<Style x:Key="FooStyle" TargetType="Button">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="Transparent">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel Orientation="Vertical">
<Button x:Name="btnFoo"
Content="Foo"
Width="100"
Click="BtnFoo_Click"
MouseEnter="BtnFoo_MouseEnter"
MouseLeave="BtnFoo_MouseLeave"
Style="{StaticResource FooStyle}" />
</StackPanel>
</Grid>
Code Behind
Brush color { get; set; }
private void BtnFoo_Click(object sender, RoutedEventArgs e)
{
color= color == Brushes.Lime ? Brushes.Blue : Brushes.Lime;
btnFoo.Background = color;
}
private void BtnFoo_MouseEnter(object sender, MouseEventArgs e)
{
btnFoo.ClearValue(Button.BackgroundProperty);
}
private void BtnFoo_MouseLeave(object sender, MouseEventArgs e)
{
btnFoo.Background = color==null?btnFoo.Background:color;
}

How to make a button in a Textbox's ControlTemplate update the text of the TextBox?

I currently have a custom control set up as shown below. (I am trying to make a custom numericupdown)
Basically, what this style does is it overlays two buttons on top of a styled text box. The two buttons should increase/decrease the value in the TextBox by one every time. The styling is fine, and the control displays correctly, but I do not know how to make it function.
WHAT I NEED
I need it so the buttons will decrease/increase the textbox's integer by one every time.
WHAT I HAVE TRIED
Just for your information, my current XAML ResourceDictionary is called Generic.xaml.
Try 1
I have tried creating a new C# class called Generic.xaml.cs and adding x:class="MyProject.Themes.Generic" and creating click events for the button. I would then add the appropriate event handlers into the Generic.xaml.cs file. I did manage to get the click events working, but I couldn't find a way to decrease the value of the TextBox.
For example:
<Button Click="increaseValue"></Button>
public partial class Generic
{
private void increaseValue(object sender, RoutedEventArgs e)
{
// code to change the textbox's value would be here, but I didn't know how to do it
}
}
Try 2
I have tried the exact same method as above, but with some differences. I nested all of my styles (in the code at the very bottom) into this:
<Style>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBox>
<!-- Styles go here -->
</TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
None of the above worked. Does anyone have any ideas?
Below is my full XAML code (it works fine). I mainly need assistance with the code-behind.
<Style TargetType="{x:Type local1:roundNumericUpDown}">
<Setter Property="FontFamily" Value="{StaticResource SourceSansRegular}" />
<Setter Property="Padding" Value="10, 0, 5, 1" />
<Setter Property="FontSize" Value="15" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="{StaticResource initialColor}" />
<Setter Property="Height" Value="28px" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Text" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="{TemplateBinding Background}" x:Name="Bd" BorderThickness="0" CornerRadius="15" BorderBrush="#FF383838">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="32px" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="PART_ContentHost" />
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="13" />
<RowDefinition Height="2" />
<RowDefinition Height="13" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Height="13" VerticalAlignment="Top" x:Name="IncreaseButton">
<Polygon Points="0,5 16,5 8,0" Stroke="{StaticResource decalColor}" Fill="{StaticResource decalColor}" />
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource hoverColor}" />
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="0, 13, 0 0" x:Name="Bd" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource clickColor}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource clickColor1}" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Grid.Row="2" Height="13" VerticalAlignment="Bottom" x:Name="DecreaseButton">
<Polygon Points="0,0, 16,0 8,5" Stroke="{StaticResource decalColor}" Fill="{StaticResource decalColor}" />
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource hoverColor}" />
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="0, 0, 13 0" x:Name="Bd" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource clickColor1}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource clickColor}" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try 1 is the right track
Of course I recommend to add try catch for the Convert method in-case user change the text to non-numeric value or switch TextBox to TextBlock making the value change only when the buttons are clicked and in that case you can guarantee it to be always number and you will not need the try and catch.
public partial class Generic
{
private void increaseValue(object sender, RoutedEventArgs e)
{
TextBox textBox = (((((sender as Button).Parent as Grid).Parent as Grid)).Parent as Border).TemplatedParent as TextBox;
textBox.Text = Convert.ToString(Convert.ToInt32(textBox.Text) + 1);
}
}
Not recommended
I honestly do not recommend the way you are creating your control. It would have been much easier and simpler to create an actual UserControl for your textBox and buttons and and add style to each element (textBox, UpButton, DownButton). Then you will have the freedom to access all 3 element freely. usually Style is for styling :)
Hopefully this answers your question

Why isnt my button using the style I created?

So I decided to try to give a button a custom style.
Yet when I assign it the Style it wont use it, why is this?
I tried creatinga button with a textbox, image and a ellipse with a label on that too.
I want the button to change color when I hover over it but its making my button disappear.
Window resources
<Window.Resources>
<Style x:Key="MenuButton" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="Background" Value="#272727">
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Gray"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And then the button
<Button Background="Transparent"
Style="{StaticResource MenuButton}"
Height="25"
BorderThickness="0">
<StackPanel Orientation="Horizontal">
<Image Source="Resources/earth-globe.png"
Height="20"
Width="20"
HorizontalAlignment="Left"
Margin="0,0,5,0"
UseLayoutRounding="True"
RenderOptions.BitmapScalingMode="Fant"/>
<Label Content="Websites"
Foreground="White"
VerticalAlignment="Center"
Width="100"
Height="24"/>
<Grid HorizontalAlignment="Right" Height="20" Width="20">
<Ellipse Width="20"
Height="20"
Fill="#555555"
Margin="0,0,0,0">
</Ellipse>
<TextBlock Text="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="12"
TextAlignment="Center"
Foreground="White"/>
</Grid>
</StackPanel>
</Button>
You do not want to put that style in the template portion of the style because a template is used for customizing the full control look (i.e. making a button a circle) and a way of giving the developer more flexibility over styling. What you could do is make a style that is applied to the button. Instead try this:
<Window.Resources>
<Style x:Key="MenuButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="#272727" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Gray" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
If you did want to modify the template property though, also a valid approach you need to add a <ContentPresenter />. See the below example:
<Window.Resources>
<Style x:Key="MenuButton" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter />
<ControlTemplate.Triggers>
<Trigger Property="Background" Value="#272727">
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Gray"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
However, with the minimal styling you have it seems like a poor use case to modify the template and I would recommend the first approach.
Add missing ContentPresenter to your DataTemplate.
<Style x:Key="MenuButton" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter /> <!--This thing was missing-->
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="RED" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How to make value of a custom control editable upon receiving focus

I created a custom WPF control which displays the value of the Weight property which is an int. When the user clicks on the custom control or when the control gets the focus, the user should be able to edit the value of the Weight property.
To accomplish this, I tried the following:
If the control is "inactive", the Weight property will be displayed
in a TextBlock.
If the control gets the focus, the Weight property
will be displayed in a TextBox.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary1">
<Style TargetType="{x:Type local:CustomControl1}">
<Style.Resources>
<ControlTemplate x:Key="Control_Focused" >
<Border Background="Green"
BorderBrush="Black"
CornerRadius="50" Width="40" Height="40">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Width="35"
Text="{Binding Mode=TwoWay,Path=Model.Weight,UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:CustomControl1}}
,Converter={x:Static local:CustomControl1.IntToStringConverter}}" />
</StackPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="Control">
<Border Background="Green"
BorderBrush="Black"
CornerRadius="50" Width="40" Height="40">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="PART_TextBlockWeighted" Text="{Binding Mode=TwoWay,Path=Model.Weight,UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:CustomControl1}}}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Template" Value="{StaticResource Control_Focused}" ></Setter>
</Trigger>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Template" Value="{StaticResource Control}" ></Setter>
</Trigger>
</Style.Triggers>
</Style>
The problem with this custom control style is that when the user clicks into the TextBox, the trigger will change the control template to the TextBlock. How can I fix this?
Try using the IsKeyboardFocusWithin property instead. I believe this will do what you need.
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="Template" Value="{StaticResource Control_Focused}" ></Setter>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="False">
<Setter Property="Template" Value="{StaticResource Control}" ></Setter>
</Trigger>
</Style.Triggers>

Change the Label's foreground colour on MouseOver WPF

I have the following problem: I have a Button, which has a StackPanel inside it, with a ContentControl and a Label within the StackPanel, and I've set the button's properties IsMouseOver and IsPressed to change the button's colour when the action happen. But, I would like to invert the label's colour when the mouse is over the button.
This is my button's code: (because I think my description is not clear enough):
<Button Template="{StaticResource OnMouseOver}" ToolTip="Release" >
<StackPanel Orientation="Horizontal">
<ContentControl Template="{StaticResource Release}"/>
<Label Content="Release" Foreground="#457345" />
</StackPanel>
</Button>
This is how I changed the button's properties when the button is pressed and when the mouse is over the button:
<ControlTemplate TargetType="Button" x:Key="OnMouseOver">
<Border x:Name="border" Background="Transparent">
<ContentPresenter ContentSource="Content" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#A1CCA1"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Background" Value="#AFD8AF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
For the record, I've tried to do something like ControlTemplate for my label, but it didn't work, and my label just vanished when I did.
Could you help me?
try this :
<ControlTemplate TargetType="Button" x:Key="OnMouseOver">
<Border x:Name="border" Background="Transparent">
<StackPanel Orientation="Horizontal">
<ContentControl />
<Label x:Name="label" Content="Release" Foreground="#457345" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#A1CCA1"/>
<Setter TargetName="label" Property="Foreground" Value="#AFD8AF"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Background" Value="#AFD8AF"/>
<Setter TargetName="label" Property="Foreground" Value="#A1CCA1"/>
</Trigger>
</ControlTemplate.Triggers>
<Button x:Name="button" Template="{StaticResource OnMouseOver}" ToolTip="Release" Height="42" VerticalAlignment="Bottom" Margin="235,0,127,143" >
</Button>

Categories