I have three buttons on my Xaml
<Page.Resources>
<Style x:Key="GroupToggleStyle" TargetType="RadioButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Background" Value="BlueViolet"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource Self}}"
Value="True">
<DataTrigger.Setters>
<Setter Property="Background" Value="Red"/>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Grid>
<RadioButton GroupName="LanguageGroup" Command="{Binding LanguageChangeCommand}" IsChecked="{Binding Button0}"
CommandParameter="English" Content="English" Foreground="White" Width="80"
Style="{StaticResource GroupToggleStyle}" FontSize="15" Grid.Row="3" Grid.Column="2" BorderBrush="#0000ffff" Height="30" Margin="8,5,162,21" Grid.ColumnSpan="2" Background="BlueViolet">
<RadioButton.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</RadioButton.Resources>
</RadioButton>
<Grid/>
But when I put mouse over my button, button's background changes to default windows gray background.
What's The Problem?
Here is a photo of my buttons
The ToggleButton defines animations inside its ControlTemplate to control the e.g., checked and hover behavior/states. You will have to override the default ControlTemplate in order to implement your custom animations and triggers.
Additionally, you must also move the mouse over trigger to the RadioButton template too.
You can find examples of the default styles and templates at Control Styles and Templates or use the XAML designer (or Blend) to edit a copy of the elements template.
<Style x:Key="GroupToggleStyle"
TargetType="RadioButton"
BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Background"
Value="BlueViolet" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border x:Name="Border"
CornerRadius="5"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Background"
Value="Gray" />
</Trigger>
<Trigger Property="IsChecked"
Value="True">
<Setter TargetName="Border"
Property="Background"
Value="Red" />
</Trigger>
<Trigger Property="IsMouseOver"
Value="True">
<!-- Target the border to allow local Background values on the templated control -->
<Setter TargetName="Border"
Property="Background"
Value="Green" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In case you want to change individual buttons only, simply base the individual Style on the common base Style (but note that you have to remove the local Style assignment as the local value has a higher precedence than the implicit Style).
Related
I have a style for Buttons and now I want to apply it to RadioButtons, except that where a normal Button has a CornerRadius that is a single number (each corner is the same) I want to render the RadioButtons with different corner radii, like this:
I use a custom ControlTemplate for Button as well as a style:
<ControlTemplate TargetType="{x:Type ButtonBase}" x:Key="ButtonTemplate">
<Border Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
CornerRadius="22.5"
BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding Foreground}">
<TextBlock FontSize="14" FontWeight="Bold"
TextWrapping="Wrap" TextAlignment="Center"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="30 0"
Foreground="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"
Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
</ControlTemplate>
<Style TargetType="{x:Type ButtonBase}" x:Key="MainButton">
<Setter Property="Foreground" Value="{StaticResource IntBlue2}"/>
<Setter Property="TextBlock.Foreground" Value="{StaticResource IntBlue2}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="MinWidth" Value="132"/>
<Setter Property="Template" Value="{StaticResource ButtonTemplate}"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="LightSlateGray"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#66CDFF"/>
</Trigger>
</Style.Triggers>
</Style>
And I have a style for RadioButton that uses the Button template
<Style TargetType="RadioButton">
<Setter Property="Template" Value="{StaticResource ButtonTemplate}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource ForegroundPureWhite}"/>
<Setter Property="BorderThickness" Value="2"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledGrey}"/>
</Trigger>
</Style.Triggers>
</Style>
Everything above works, until I want the custom CornerRadius for each RadioButton.
I've tried CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}}" inside the Border in the ControlTemplate, and <Setter Property="Border.CornerRadius" Value="22.5"/> inside the MainButton style, but it doesn't work (it doesn't apply the radius).
Binding CornerRadius="{TemplateBinding CornerRadius}" to the border in the template doesn't even compile, and setting CornerRadius on a Button or RadioButton, through the control tag or through a setter in the style, also doesn't compile.
How do I use one template, but different CornerRadius in each style or instance?
A ButtonBase has no CornerRadius property that you can bind to but you could use the Tag property:
<ControlTemplate TargetType="{x:Type ButtonBase}" x:Key="ButtonTemplate">
<Border Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
CornerRadius="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}"
...
<Style TargetType="RadioButton">
<Setter Property="Tag" Value="22.5" />
...
</Style>
<RadioButton ... Tag="0" />
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
I am trying to define a Style that could be used where Button holds a TextBlock as its Content and when Button has IsEnabled=False I want to set TextBlock's Foregroung color.
<Button Style="{StaticResource TransparentButtonStyle}"
IsEnabled="{Binding IsAllowed}">
<TextBlock Text="Click Me"
Style="{StaticResource HyperLinkStyle}">
</TextBlock>
</Button>
<Style x:Key="TransparentButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="Transparent">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="HyperLinkStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Foreground" Value="LightBlue" />
<Setter Property="TextDecorations" Value="Underline" />
</Trigger>
</Style.Triggers>
</Style>
Can I modify the TextBlock's Style to grab the parent Button's IsEnabled value somehow to be able to set the Foreground color ?
you can just add <Trigger Property="IsEnabled" Value="False"> to your HyperLinkStyle, but I recommend you to create LinkButtonStyle instead, so you final markup fill be much cleaner:
<Button Content="Link text" Style="{StaticResource LinkButtonStyle}" />
this just makes your views much cleaner...
here's my LinkButton template:
<Style x:Key="LinkButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{StaticResource LinkButtonText}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock x:Name="ContentPresenter" Background="{TemplateBinding Background}"
Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="ContentPresenter" Property="Foreground" Value="{DynamicResource LinkButtonDisabled}" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsEnabled" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="ContentPresenter" Property="TextDecorations" Value="Underline"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If you want to get to Button you can use DataTrigger with RalativeSource binding
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- Setters -->
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=IsEnabled}" Value="False">
<!-- Setters -->
</DataTrigger>
</Style.Triggers>
but if you want to make your Style independent of what is the parent then normal Trigger on IsEnabled property should work just as good
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- Setters -->
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<!-- Setters -->
</Trigger>
</Style.Triggers>
normal Trigger should work because IsEnabled value is influenced by UIElement.IsEnabledCore which
Gets a value that becomes the return value of IsEnabled in derived classes
...
The default implementation of this property caches the value and also calculates whether the parent element of this element is enabled. (If the parent is not enabled, the child element cannot be effectively enabled in practical user interface (UI).)
so basically if parent Button is disabled child TextBlock will be disabled as well
Button is applied with a Foreground when it is enabled. If it is Set as Disabled, default Button's Disabled Foreground need to apply.
<Button Width="150"
Height="50"
Content="Test"
Foreground="Red"
IsEnabled="False" />
I have Triggers for this button like
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
This Foreground is not applied when it is enabled.
Any idea on this?
Need like below,
If you set the properties locally the trigger will not be able to change the value due to precedence.
Move the Foreground and IsEnabled property into the style:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Button Width="150"
Height="50"
Content="Test">
</Button>
I am not sure I understand the question properly, because those codes posted in question should work fine. Following is a working sample to produce a Button exactly as the captured image shows. I put the Style as resource in the Button's container control -StackPanel in this case- :
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Button Width="150"
Height="50"
Content="Test"
IsEnabled="True">
</Button>
</StackPanel>
If you edit Button's default template you can find the following trigger inside control template.
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
</Trigger>
This trigger set Foreground to the content presenter using TargetName. No template binding used here. It directly assigns value. So the values you set for Foreground in Style Triggers will not be applied. You can edit the control template to achieve your requirement. This limitation not only for Foreground, for Background and BorderBrush also have this.
The following code is working for me:
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid x:Name="grid" Background="{StaticResource FlatButtonNavigation}">
<Border Name="ButtonBorder" CornerRadius="5,5,5,5"
BorderBrush="Gray" BorderThickness="2">
<ContentPresenter Name="MyContentPresenter"
HorizontalAlignment="center"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextBlock.FontSize="{TemplateBinding FontSize}"
TextBlock.Foreground="{StaticResource LeftPanelFontColor}"
Margin="10"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="ButtonBorder" Property="Background" Value="LightGray"/>
<Setter TargetName="ButtonBorder" Property="BorderBrush" Value="#FFADB2B5"/>
<Setter TargetName="MyContentPresenter" Property="TextBlock.Foreground" Value="White"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Can be worked using styles as mentioned in the other answers, but there is no need to go outside the button to define the style, you can define a style explicitly related to the particular button:
<Button Width="150" Height="50" Content="Test">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
</Style.Triggers>
</Button.Style>
</Button>
</StackPanel>
I am new in WPF.
What the way to change a togglebutton behavior.
to
with black baground and no border.
Is need to use Control Template?
You have to modify the Control Template or Style to change the look and feel of the existing Control available. Have a look at this sample which is some what similar to your requirement. what i have done is i changed the Chrome (default style of windows) and created my own style with Border and content presenter. Then i have created the Triggers for the style. For visualization, in the mouseover and ischecked event i am changing background color of the Border.
<Window.Resources>
<Style x:Key="ToggleButtonStyle1" TargetType="{x:Type ToggleButton}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="border">
<ContentPresenter
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
RecognizesAccessKey="True" TextElement.Foreground="White" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true"/>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="#FF6C6C6C"/>
<Setter Property="CornerRadius" TargetName="border" Value="5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="#FF282828"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<ToggleButton HorizontalAlignment="Left" Margin="136,59,0,0" Style="{DynamicResource ToggleButtonStyle1}" VerticalAlignment="Top" Width="27" Height="24" Content="-" FontSize="21.333" FontWeight="Bold" HorizontalContentAlignment="Center" Padding="0" VerticalContentAlignment="Center" IsThreeState="True"/>
</Grid>
Yes, you want to use a ControlTemplate to change how the ToggleButton looks. Take a look at the page for the ToggleButton as well as this article:
Customizing the Appearance of an Existing Control by Creating a ControlTemplate
to get you started.