CheckBox changed background on mouse over and in checked state - c#

I'm writing template for CheckBox control.
Here is CheckBox template code:
<Style x:Key="{x:Type CheckBox}"
TargetType="{x:Type CheckBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Border x:Name="Border"
Width="15"
Height="15"
CornerRadius="1"
BorderThickness="1"
BorderBrush="DarkGray"
Background="White">
</Border>
</BulletDecorator.Bullet>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource DefaultButtonBlueBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource DefaultButtonBlueBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="4,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
RecognizesAccessKey="True" />
</BulletDecorator>
</Setter.Value>
</Setter>
</Style>
I want to change border background color when checkbox in checked state and mouse over. I tried to specify MultiTrigger like that:
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="Border" Property="Background" Value="Red" />
</MultiTrigger.Setters>
</MultiTrigger>
But this don't work.
Is this even possible in wpf?
Thank you.

WPF (opposed to UWP) has stricter limitations regarding the possibilities when using the VisualStateManager. You can only target a property once per state. Which makes quite sense. When in the Checked state, the property BorderBackground is animated to the corresponding value. When your MultiTrigger is activated it tries to modify the Border.Background property, which is currently blocked by the active animation.
You can either replace the relevant visual states with triggers or let animation and trigger target different elements.
Simply overlay the content of the BulletDecorator with an additional Border and toggle its Background instead:
<Style x:Key="{x:Type CheckBox}" TargetType="{x:Type CheckBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Grid>
<Border x:Name="MouseOverBorder"
Panel.ZIndex="1"
Background="Transparent"
CornerRadius="1"
BorderThickness="1" />
<Border x:Name="Border"
Width="15"
Height="15"
CornerRadius="1"
BorderThickness="1"
BorderBrush="DarkGray"
Background="White" />
</Grid>
</BulletDecorator.Bullet>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource DefaultButtonBlueBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource DefaultButtonBlueBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="4,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
RecognizesAccessKey="True" />
</BulletDecorator>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="MouseOverBorder"
Property="Background"
Value="Red" />
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

Decrease used horizontal space of TreeView

How do I control the horizontal space being used by the expanded TreeViewItems so a treeview can take less space? Can it be done by styling alone or do it have to be a fully remade treeview to control these kind of styling properties?
The items you see are layout by the ItemsPresenter of the parent TreeViewItem. This means to change the indentation of the child items you must change the position of the ItemsPresenter in the layout.
To do so you must override the default ControlTemplate of the TreeViewItem. Find the ItemsPresenter and give it a negative left Margin to decrease the indentation or a positive left marging to increase the indentation of the child items.
The following Style is taken from Microsoft Docs: TreeView ControlTemplate Example. There you find all the resources that the following Style depends on.
The key is to set a negative left Margin on the ItemsPresenter which is named "ItemsHost":
<ItemsPresenter x:Name="ItemsHost"
...
Margin="-12,0,0,0" />
The full TreeViewItemStyle (without resources):
<Style x:Key="{x:Type TreeViewItem}"
TargetType="{x:Type TreeViewItem}">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="HorizontalContentAlignment"
Value="{Binding Path=HorizontalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="VerticalContentAlignment"
Value="{Binding Path=VerticalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Padding"
Value="1,0,0,0" />
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="FocusVisualStyle"
Value="{StaticResource TreeViewItemFocusVisual}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19"
Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd"
Storyboard.TargetProperty="(Panel.Background).
(SolidColorBrush.Color)"
>
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource SelectedBackgroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unselected" />
<VisualState x:Name="SelectedInactive">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd"
Storyboard.TargetProperty="(Panel.Background).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource SelectedUnfocusedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ExpansionStates">
<VisualState x:Name="Expanded">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="ItemsHost">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ToggleButton x:Name="Expander"
Style="{StaticResource ExpandCollapseToggleStyle}"
ClickMode="Press"
IsChecked="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"/>
<Border x:Name="Bd"
Grid.Column="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<!-- Host of the child items -->
<ItemsPresenter x:Name="ItemsHost"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
Visibility="Collapsed"
Margin="-12,0,0,0" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems"
Value="false">
<Setter TargetName="Expander"
Property="Visibility"
Value="Hidden" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader"
Value="false" />
<Condition Property="Width"
Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header"
Property="MinWidth"
Value="75" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader"
Value="false" />
<Condition Property="Height"
Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header"
Property="MinHeight"
Value="19" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

how to tweak a style at runtime

I have a style defined in my app.xaml file that applies to all buttons. By default, all buttons get a DarkGray border. However, when a certain action on that button occurs, I would like to change the border to Red.
I have done this by creating an entirely new style, defining the x:key value for it and then assigning the new style like so:
Style style = this.FindResource("RedBorderButtonStyle") as Style;
button.Style = style;
However, I have to copy and paste the entire code below just to change the border color. There must be a better way.
Thanks in advance!
<Style TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="MinHeight" Value="20px" />
<Setter Property="Foreground" Value="#FFFFFFFF" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border TextBlock.Foreground="{TemplateBinding Foreground}" x:Name="Border" BorderThickness="1" BorderBrush="DarkGray">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlNormalColor}" />
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.9" />
<VisualTransition GeneratedDuration="0" To="Pressed" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Instead of defining and applying a new Style, you could bind the BorderBrush property of the Border in your ControlTemplate to the BorderBrush property of the Button itself:
<Style TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="MinHeight" Value="20px" />
<Setter Property="Foreground" Value="#FFFFFFFF" />
<!-- default BorderBrush:-->
<Setter Property="BorderBrush" Value="DarkGray" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border TextBlock.Foreground="{TemplateBinding Foreground}" x:Name="Border" BorderThickness="1"
BorderBrush="{TemplateBinding BorderBrush}">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlNormalColor}" />
</Border.Background>
...
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...and simply set the BorderBrush property of the Button:
button.BorderBrush = System.Windows.Media.Brushes.Red;

Styling TextBox in WPF generates Storyboard errors

I have found a nice style for WPF applications and I´m trying to make it work with ValidationErrors.
Here the full textbox style:
<Style x:Key="TextBoxStyle" TargetType="TextBox">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{StaticResource ForegroundBrush}" />
<Setter Property="FontSize" Value="13.333" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="Background" Value="{StaticResource TextBoxBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorderBrush}" />
<Setter Property="MinHeight" Value="30" />
<Setter Property="Padding" Value="6,4" />
<Setter Property="SelectionBrush" Value="{StaticResource TextBoxFocusedBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxHoverBorderBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxHoverBackgroundBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualElement" />
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ReadOnlyVisualElement" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualElement" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisualElement" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid" />
<VisualState x:Name="InvalidUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>True</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Opacity="1">
<Grid>
<Border x:Name="ReadOnlyVisualElement" Background="{StaticResource TextBoxReadOnlyBackgroundBrush}" Opacity="0" />
<ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}" />
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" BorderBrush="{StaticResource DisabledVisualElement}" BorderThickness="{TemplateBinding BorderThickness}" Background="{StaticResource DisabledVisualElement}" IsHitTestVisible="False" Opacity="0" />
<Border x:Name="FocusVisualElement" BorderBrush="{StaticResource TextBoxFocusedBrush}" BorderThickness="{TemplateBinding BorderThickness}" IsHitTestVisible="False" Opacity="0" />
<Border x:Name="ValidationErrorElement" BorderBrush="{StaticResource ValidationErrorElement}" BorderThickness="{TemplateBinding BorderThickness}" Visibility="Collapsed">
<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}">
<ToolTip.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>true</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToolTip.Triggers>
</ToolTip>
</ToolTipService.ToolTip>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
The problem is when it will show the validation error, it says that the element "validationTooltip" cannot be found.
I've tried change the storyboard from
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
to
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.Target="{Binding ElementName=validationTooltip}">
and the error has stopped, but instead another error shows, saying "cannot resolve all property references in the property path" pointing to "IsOpen".
Do you guys have any clues?
After some time, I got the expected result using triggers and creating my own style.
Here is the code.
<Style TargetType="TextBox" x:Key="FieldTextBoxStyle" BasedOn="{StaticResource FieldTextBoxStyle2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Opacity="1">
<Grid>
<Border x:Name="ReadOnlyVisualElement" Background="{StaticResource TextBoxReadOnlyBackgroundBrush}" Opacity="0" />
<ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}" />
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" BorderBrush="{StaticResource DisabledVisualElement}" BorderThickness="{TemplateBinding BorderThickness}" Background="{StaticResource DisabledVisualElement}" IsHitTestVisible="False" Opacity="0" />
<Border x:Name="FocusVisualElement" BorderBrush="{StaticResource TextBoxFocusedBrush}" BorderThickness="{TemplateBinding BorderThickness}" IsHitTestVisible="False" Opacity="0" />
<Border x:Name="ValidationErrorElement" BorderBrush="{StaticResource ValidationErrorElement}" BorderThickness="{TemplateBinding BorderThickness}" Visibility="Collapsed">
<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" IsHitTestVisible="true" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}"/>
</ToolTipService.ToolTip>
</Border>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsEnabled" Value="true" />
<Condition Property="IsMouseOver" Value="true" />
</MultiTrigger.Conditions>
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource TextBoxHoverBorderBrush}" />
<Setter TargetName="Border" Property="Background" Value="{StaticResource TextBoxHoverBackgroundBrush}" />
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="DisabledVisualElement" Property="Opacity" Value="1" />
</Trigger>
<Trigger Property="IsReadOnly" Value="true">
<Setter TargetName="ReadOnlyVisualElement" Property="Opacity" Value="1" />
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter TargetName="FocusVisualElement" Property="Opacity" Value="1" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="true" />
<Condition Property="Validation.HasError" Value="true" />
</MultiTrigger.Conditions>
<Setter TargetName="ValidationErrorElement" Property="Visibility" Value="Visible" />
<Setter TargetName="validationTooltip" Property="IsOpen" Value="true" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="false" />
<Condition Property="Validation.HasError" Value="true" />
</MultiTrigger.Conditions>
<Setter TargetName="ValidationErrorElement" Property="Visibility" Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>

Wpf button mouse moveover change color

I am trying to create a button template. Everything works find except that when I move the mouse over the button, the color of the text should change to white. The XAML code:
<!--Control colors.-->
<Color x:Key="ControlNormalColor">#FFFFFF</Color>
<Color x:Key="ControlMouseOverColor">#999999</Color>
<Color x:Key="DisabledControlColor">#FFFFFF</Color>
<Color x:Key="DisabledForegroundColor">#999999</Color>
<Color x:Key="ControlPressedColor">#999999</Color>
<!-- FocusVisual -->
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="2" StrokeThickness="1" Stroke="#60000000" StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Button -->
<Style TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="MinHeight" Value="29px" />
<Setter Property="MinWidth" Value="103px" />
<Setter Property="FontFamily" Value="Century Gothic" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="#999999" />
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border TextBlock.Foreground="{TemplateBinding Foreground}" x:Name="Border">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlNormalColor}" />
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5" />
<VisualTransition GeneratedDuration="0" To="Pressed" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My question, what must I do to get the text in the button to change to white on a mouseover? This code was copied from internet. I am pretty new in WPF world. Though I understand approximately was is going on in this code, my knowledge of WPF is somewhat limited.
you have to add one more ColorAnimationUsingKeyFrames in MouseOver VisualState to Change the Foreground color while mouseover occured, you can use below menioned code
<Color x:Key="ControlNormalColor">#FFFFFF</Color>
<Color x:Key="ControlMouseOverColor">#999999</Color>
<Color x:Key="DisabledControlColor">#FFFFFF</Color>
<Color x:Key="DisabledForegroundColor">#999999</Color>
<Color x:Key="ControlPressedColor">#999999</Color>
<!-- FocusVisual -->
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="2" StrokeThickness="1" Stroke="#60000000" StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Button -->
<Style TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="MinHeight" Value="29px" />
<Setter Property="MinWidth" Value="103px" />
<Setter Property="FontFamily" Value="Century Gothic" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="#999999" />
<Setter Property="FontWeight" Value="Bold"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border TextBlock.Foreground="{TemplateBinding Foreground}" x:Name="Border">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlNormalColor}" />
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5" />
<VisualTransition GeneratedDuration="0" To="Pressed" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlNormalColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledControlColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
By using Triggers in style we can get it .On Mouse Over we can set the background color in setter
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="50" Height="50" HorizontalContentAlignment="Left" BorderBrush="{x:Null}" Foreground="{x:Null}" Margin="50,0,0,0">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

How to update the color of the ToggleButton content?

For my WP7 app, when a ToggleButton is in a checked state, I expect the content color to reverse (button turns from black to white and text from white to black). This work great when the content is text since the ToggleButton takes care of changing the color. However, this isn’t the case for other type of content such as a Patch object. I replaced the content of my ToggleButton with a Path object and it’s color isn’t changing (when in a checked state, the ToggleButton background turns from black to white and the Path object stays white instead of turning black).
The first thing I did is to bind the Fill property of the Path object to it's parent foreground color. But that didn't work either. I could be trying to use DataTrigger, but Silverlight/WP doesn't support them.
I updated the text to use a Path (drawing of pause symbol) and the color of the path doesn't follow the same behavior of the text. Any idea why? How could I fix that?
<ToggleButton Grid.Column="0" x:Name="PauseButton">
<ToggleButton.Content>
<Path Name="PauseIcon" Fill="White"
Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0" />
</ToggleButton.Content>
</ToggleButton>
Use Checked and Unchecked events:
<ToggleButton Grid.Column="0" x:Name="PauseButton"
Background="Black"
Checked="PauseButton_Checked"
Unchecked="PauseButton_Unchecked"
Style="{DynamicResource ToggleButtonStyle}">
<Path x:Name="PauseIcon" Fill="White"
Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0" />
</ToggleButton>
And apply the ToogleButton background and the Path fill:
private void PauseButton_Checked(object sender, RoutedEventArgs e)
{
(sender as ToggleButton).Background = Brushes.White;
PauseIcon.Fill = Brushes.Black;
}
private void PauseButton_Unchecked(object sender, RoutedEventArgs e)
{
(sender as ToggleButton).Background = Brushes.Black;
PauseIcon.Fill = Brushes.White;
}
The ToggleButtonStyle is used (if you want) to disable the Microsoft_Windows_Themes:ButtonChrome behavior when the cursor is over the button, or it's pressed:
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Stroke="Black" StrokeDashArray="1 2"
StrokeThickness="1" Margin="2"
SnapsToDevicePixels="true"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
<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}">
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
RenderDefaulted="{TemplateBinding Button.IsDefaulted}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
RecognizesAccessKey="True"/>
</Microsoft_Windows_Themes:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would have to guess that there is a style somewhere defining the behavior for the text (TextBlock).
You can achieve the same by using the following style for the path:
<ToggleButton Grid.Column="0" x:Name="PauseButton">
<ToggleButton.Content>
<Path Name="PauseIcon" Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0">
<Path.Style>
<Style TargetType="{x:Type Path}">
<Setter Property="Fill" Value="White"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PauseButton, Path=IsChecked}" Value="True">
<Setter Property="Fill" Value="Black"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</ToggleButton.Content>
</ToggleButton>
Try using VisualStates in your style, You can do it very easily with Expression Blend.
At the end of my post is an example of my style where I put the foreground of my content presenter on another color when it is disabled.
The single difference between a Button and ToggleButton is that is has a Toggled-state where you'll have to add a state and change your foreground.
The state will look somewhat like this :
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
<EasingColorKeyFrame KeyTime="0" Value="#FF7052A8"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimation Duration="0" To="#FFbab0c7" Storyboard.TargetName="contentPresenter"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)" />
</Storyboard>
</VisualState>
So this a an example of my Button-style. Just create your own and assign it to your ToggleButton.
<Style TargetType="{x:Type Button}">
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ColorAnimation Duration="0" To="White" Storyboard.TargetName="contentPresenter"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)" />
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
<EasingColorKeyFrame KeyTime="0" Value="#FF532B8C"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.HorizontalAlignment)" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static HorizontalAlignment.Center}"/>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
<EasingColorKeyFrame KeyTime="0" Value="#FF6137ae"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
<EasingColorKeyFrame KeyTime="0" Value="#FF7052A8"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimation Duration="0" To="#FFbab0c7" Storyboard.TargetName="contentPresenter"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="rectangle" Fill="#FF371C69" RadiusX="10" RadiusY="10"/>
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true"/>
<Trigger Property="ToggleButton.IsChecked" Value="true"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try do next:
<ToggleButton Grid.Column="0" x:Name="PauseButton">
<ToggleButton.Content>
<Path Name="PauseIcon" Fill="{Binding ElementName=PauseButton, Path=Foreground}"
Data="M0,0 0,27 8,27 8,0z M14,0 14,27 22,27 22,0" />
</ToggleButton.Content>
</ToggleButton>
It should work.

Categories

Resources