I would like to know how to make a textblock move up (or better to say float up) with animation in Xaml (WPF).
Let's say I have login screen and I have two textblocks: Username and Password. When I click on the textblock (User name or Password) the textblock will move up (float up) with animation effect until the textblock will cross the border line of the box and then the textblock will stop moving. In the same animation, the font size of the text in the textblock Become smaller (for example, from 12px to 6px).
And additionally, in the same animation, when the text moving up I want to add the blur effect to the text, the blur effect start when textblock floating up and return to normal when the textblock cross the line of the box.
In the end, when i click in somewhere else on the Login screen the textblock will return to starting point position if nothing was writen in the box.
I found something similar here
this is my code (that doesn't work)
Xaml:
x:Class="tester.Window1"
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"
xmlns:local="clr-namespace:tester"
mc:Ignorable="d"
Title="Window1" Height="400" Width="600" >
<Grid>
<Border Margin="246,164,184,175" BorderThickness="1,1,1,1" BorderBrush="Black" >
<Label
Name="Two"
Margin="-1,-11,61,-1"
Width="100" Height="36" FontSize="20"
VerticalAlignment="Top" VerticalContentAlignment="Top"
Foreground="Blue" >
Name
<Label.Effect>
<BlurEffect Radius="0" x:Name="BlurEffect2"/>
</Label.Effect>
<Label.Triggers>
<EventTrigger
RoutedEvent="Label.MouseLeftButtonDown">
<BeginStoryboard>
<Storyboard x:Name="FirstLabelName" Completed="FirstLabelName_Completed" >
<DoubleAnimation
Storyboard.TargetName="Two"
Storyboard.TargetProperty="(Label.Height)"
To="20.0" Duration="0:0:0.3"
AutoReverse="False" />
<DoubleAnimation
Storyboard.TargetName="Two"
Storyboard.TargetProperty="(FontSize)"
To="16" Duration="0:0:0.3"
AutoReverse="False" />
<DoubleAnimation
Storyboard.TargetName="BlurEffect2"
Storyboard.TargetProperty="Radius"
To="10" Duration="0:0:0.3"
AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Label.Triggers>
</Label>
</Border>
<Border Margin="0,0,20,50" Height="30" Width="100" BorderThickness="1,1,1,1" BorderBrush="White" >
<Label
Name="one"
Margin="9,-1"
Width="80" Height="30" FontSize="16"
VerticalAlignment="Top" VerticalContentAlignment="Top"
Foreground="Blue" Visibility="Hidden">
Name
<Label.Effect>
<BlurEffect Radius="10" x:Name="BlurEffect"/>
</Label.Effect>
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard x:Name="StoryBoardOne">
<Storyboard x:Name="Effect1" >
<DoubleAnimation
Storyboard.TargetName="one"
Storyboard.TargetProperty="(Label.Height)"
To="30.0" Duration="0:0:0.5"
AutoReverse="False" />
<DoubleAnimation
Storyboard.TargetName="one"
Storyboard.TargetProperty="(FontSize)"
To="12" Duration="0:0:0.3"
AutoReverse="False" />
<DoubleAnimation
Storyboard.TargetName="BlurEffect"
Storyboard.TargetProperty="Radius"
To="0" Duration="0:0:0.5"
AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="StoryBoardOne"></StopStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Border>
</Grid>
</Window>
Back:
private void FirstLabelName_Completed(object sender, EventArgs e)
{
Two.Visibility = Visibility.Hidden;
one.Visibility = Visibility.Visible;
}
So what you're looking for is loosely referred to as inline label inputs. They're not tough but if you want real slick ones it does take some effort into customizing control templates. You need to create your Storyboard animations and trigger them via enter/exit actions within your triggers. Unless you're using VisualStateManager in which case you would trigger the animations via VisualState instead.
Here's a quick PoC example of how you could do something like that to get you started. However I did purposely leave some finishing touches out to avoid just handing a full solution over. Except there should be enough for a quick completion and tuning to fit your needs. Hope this helps, cheers!
The result (in the form of a choppy .gif for visual aid);
...and here's the quick sample made from a default wpf TextBox template.
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel.Resources>
<SolidColorBrush x:Key="TextBox.Static.Border" Color="#FFABAdB3"/>
<SolidColorBrush x:Key="TextBox.MouseOver.Border" Color="#FF7EB4EA"/>
<SolidColorBrush x:Key="TextBox.Focus.Border" Color="#FF569DE5"/>
<Style x:Key="CW-Inline-TextBox" TargetType="{x:Type TextBox}">
<Setter Property="Height" Value="35"/>
<Setter Property="Width" Value="150"/>
<Setter Property="Margin" Value="0,25,0,0"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<ControlTemplate.Resources>
<Storyboard x:Key="CW-Inline-input-example">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="textBlock">
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="-6.667">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="textBlock">
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="-25.733">
<EasingDoubleKeyFrame.EasingFunction>
<QuinticEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="textBlock">
<EasingColorKeyFrame KeyTime="0:0:0.6" Value="#FF0285BA"/>
</ColorAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.FontWeight)" Storyboard.TargetName="textBlock">
<DiscreteObjectKeyFrame KeyTime="0:0:0.3">
<DiscreteObjectKeyFrame.Value>
<FontWeight>Bold</FontWeight>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid>
<Border x:Name="border" Grid.Row="1"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<TextBlock x:Name="textBlock" Text="{TemplateBinding Tag}"
VerticalAlignment="Center" Margin="8,0"
Foreground="Gray" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
<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="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource CW-Inline-input-example}" />
</Trigger.EnterActions>
<!--
<Trigger.ExitActions>
// In case you wanted to do something cool on exit too..
</Trigger.ExitActions>
-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
<Condition Property="IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<TextBox Tag="Your label"
Height="35" Width="150" FontSize="20"
Style="{DynamicResource CW-Inline-TextBox}"/>
<TextBox Tag="Your other label"
Style="{DynamicResource CW-Inline-TextBox}"/>
<TextBox Tag="Another Instance"
Height="75" Width="150" FontSize="15"
Style="{DynamicResource CW-Inline-TextBox}"/>
</StackPanel>
And sorry I couldn't respond sooner, been busy. Enjoy :)
Related
I am trying to animation scaleX and scaleY on ellipse.
simply I want to animation scaleX and scaleY in 2 cases:
When background is green I want to anmitaion scaleX and scaleY from 0 to 1.
When background is red I want to animtaion scaleX and scaleY from 1 to 0
For some reason scale animation from 0 to 1 succeeded and from 1 to 0 didn't worked at all.
Code example:
<Window x:Class="WpfApp1.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"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Window.Resources>
<Storyboard x:Key="CheckedEllipseON">
<DoubleAnimationUsingKeyFrames Duration="0:0:0.2" Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="CheckedEllipseScale">
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0.0" />
<LinearDoubleKeyFrame Value="1.0" KeyTime="0:0:0.1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="0:0:0.2" Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="CheckedEllipseScale">
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0.0" />
<LinearDoubleKeyFrame Value="1.0" KeyTime="0:0:0.1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="CheckedEllipseOFF">
<DoubleAnimationUsingKeyFrames Duration="0:0:0.2" Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="CheckedEllipseScale">
<LinearDoubleKeyFrame Value="1.0" KeyTime="0:0:0.0" />
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0.1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Duration="0:0:0.2" Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="CheckedEllipseScale">
<LinearDoubleKeyFrame Value="1.0" KeyTime="0:0:0.0" />
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:0.1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Style TargetType="ToggleButton" x:Key="MyToggleButtonStyle">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Width" Value="40"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid ClipToBounds="True" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Ellipse Fill="Green" x:Name="CheckedEllipse" RenderTransformOrigin="0.5, 0.5">
<Ellipse.RenderTransform>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.0" ScaleY="1.0" x:Name="CheckedEllipseScale"/>
</Ellipse.RenderTransform>
</Ellipse>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Background,RelativeSource={RelativeSource Mode=Self}}" Value="Red">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource CheckedEllipseOFF}"/>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Background,RelativeSource={RelativeSource Mode=Self}}" Value="Green">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource CheckedEllipseON}"/>
</DataTrigger.EnterActions>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ToggleButton>
<ToggleButton.Style>
<Style TargetType="ToggleButton" BasedOn="{StaticResource MyToggleButtonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Test}" Value="true">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding Test}" Value="false">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<Button Command="{Binding TestCommand}" VerticalAlignment="Bottom" Width="100" Height="50"/>
</Grid>
Test property and TestCommand is only for changing colors green and red by boolean property.
Thank you.
There are actually two different problems in the code you posted. First, your ellipse background is set explicitly to "Green" and so would never actually change to red. This is a case of the "locally set" property taking precedence over style or trigger setters.
This can be fixed by changing the ellipse declaration:
<Ellipse Fill="{TemplateBinding Background}"
x:Name="CheckedEllipse"
RenderTransformOrigin="0.5, 0.5">
That will cause the ellipse to inherit the background value from the templated parent.
That issue affects only the color that is displayed. The triggers you are using use the ToggleButton.Background, and so are unaffected by that issue. So, why does the animation only work in one direction?
That issue is because you don't stop one animation before starting the other. The default for an animation is to hold its previous value, so once the animation runs to increase the scale, it continues to hold that scale value, causing the attempt by the other animation to reduce the scale to be overridden and ignored.
You can fix that aspect by adding <StopStoryboard/> actions to the triggers:
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Background,RelativeSource={RelativeSource Mode=Self}}" Value="Red">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="StoryON"/>
<BeginStoryboard Storyboard="{StaticResource CheckedEllipseOFF}" Name="StoryOFF"/>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Background,RelativeSource={RelativeSource Mode=Self}}" Value="Green">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="StoryOFF"/>
<BeginStoryboard Storyboard="{StaticResource CheckedEllipseON}" Name="StoryON"/>
</DataTrigger.EnterActions>
</DataTrigger>
</ControlTemplate.Triggers>
Note that you also have to give the started storyboard a name, so that you can use that name to stop it later.
With those changes, I'm able to click on the button to toggle the scale of the ellipse, causing it to increase in size when green, and decrease (and vanish) when red.
Here I have a button style in appliction resources
<Style x:Key="ClickableText" TargetType="{x:Type Button}">
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="FontFamily" Value="/Tasks;component/Assets/Fonts/#Abel"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<StackPanel VerticalAlignment="Center">
<ContentPresenter x:Name="Text" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Rectangle x:Name="Rect1" Width="{Binding ActualWidth, ElementName=Text}" Height="2" Fill="{DynamicResource LightGrey}"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In the style I have added a underlining rectangle to the text in the button.
<Rectangle x:Name="Rect1" Width="{Binding ActualWidth, ElementName=Text}" Height="2" Fill="{DynamicResource LightGrey}"/>
I have binded the rectangles width to be the same width as the text so that it adds a underline effect.
I now want to add an effect so that when you hover the button the rectangle reveals by spliting out.
I have got this far by adding this under the trigger tag
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.300" From="0" To="{Binding ActualWidth, ElementName=Text}" Storyboard.TargetName="Rect1" Storyboard.TargetProperty="Width" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.300" From="{Binding ActualWidth, ElementName=Text}" To="0" Storyboard.TargetName="Rect1" Storyboard.TargetProperty="Width" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
I want to link the to and from part of the double animation to the binding I used in the rectangle but it keeps producing errors. How can I do this effect?
I also want to use this as a reusable style I can distribute and keep in Application resources. I have seen other people do this through workarounds in code but am not sure if you can do this in application resources
Any help or guidance is greatly appriciated!!
LayoutTransform animation is Better for this effect.
I would do this animation in this way:
<Style x:Key="ClickableText" TargetType="{x:Type Button}">
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="FontFamily" Value="/Tasks;component/Assets/Fonts/#Abel"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="MainBorder" Background="{TemplateBinding Background}">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="2"/>
</Grid.RowDefinitions>
<ContentPresenter x:Name="Text" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Rectangle x:Name="Rect1" Grid.Row="1" Height="2" Width="{Binding ElementName=Text, Path=ActualWidth}" Fill="LightGray">
<Rectangle.LayoutTransform>
<ScaleTransform ScaleX="0"/>
</Rectangle.LayoutTransform>
</Rectangle>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="MainBorder" Value="White"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Rect1" Storyboard.TargetProperty="(ContentPresenter.LayoutTransform).(ScaleTransform.ScaleX)" From="0" To="1" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Rect1" Storyboard.TargetProperty="(ContentPresenter.LayoutTransform).(ScaleTransform.ScaleX)" From="1" To="0" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
Here is my code:
<StackPanel>
<StackPanel.Resources>
<Style x:Key="stlNavButtonBorder" TargetType="Border">
<Setter Property="BorderBrush" Value="#570000FF" />
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Height" Value="100" />
<Setter Property="Width" Value="200" />
<Setter Property="Margin" Value="10" />
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="BorderBrush.Color"
To="blue"
Duration="0:0:0.25"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="BorderBrush.Color"
To="#570000FF"
Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseDown">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="BorderBrush.Color"
To="Black"
Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
<Style x:Key="stlNavButtonRectangle" TargetType="Rectangle">
<Setter Property="Fill" Value="#570000FF"/>
</Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Style="{StaticResource stlNavButtonBorder}">
<Grid>
<Rectangle Style="{StaticResource stlNavButtonRectangle}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<Button Content="Button 1" />
<Button Content="Button 2"/>
<Button Content="Button 3" />
</StackPanel>
It generates those buttons:
When the mouse enters the button, it works as expected, and the border changes color:
The problem is that when the mouse is down on the button, the border does not changes from blue to black, as I tried to do in the MouseDown event trigger, but instead, disappears, which is the MouseLeave event trigger.
How to fix it? Thanks.
I could not able to find the underlying issue. If I am not wrong, the MouseDown event is swallowed by the Button for Click event. Anyway, I hope the following code will help you to overcome the issue.
Update:
Here is the updated code that will keep the MouseLeave trigger even after the IsPressed is triggered.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="stlNavButtonBorder" TargetType="Border">
<Setter Property="BorderBrush" Value="#570000FF" />
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Height" Value="100" />
<Setter Property="Width" Value="200" />
<Setter Property="Margin" Value="10" />
</Style>
<Style x:Key="stlNavButtonRectangle" TargetType="Rectangle">
<Setter Property="Fill" Value="#570000FF"/>
</Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Style="{StaticResource stlNavButtonBorder}" x:Name="border">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(BorderBrush).(SolidColorBrush.Color)"
To="Black"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(BorderBrush).(SolidColorBrush.Color)"
To="Blue"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Rectangle Style="{StaticResource stlNavButtonRectangle}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<Button Content="Button 1" />
<Button Content="Button 2"/>
<Button Content="Button 3" />
</StackPanel>
Following code also works except the case that after clicking the button, After Mouse Enter when we leave the button, it remains black.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="stlNavButtonBorder" TargetType="Border">
<Setter Property="BorderBrush" Value="#570000FF" />
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Height" Value="100" />
<Setter Property="Width" Value="200" />
<Setter Property="Margin" Value="10" />
</Style>
<Style x:Key="stlNavButtonRectangle" TargetType="Rectangle">
<Setter Property="Fill" Value="#570000FF"/>
</Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Style="{StaticResource stlNavButtonBorder}" x:Name="border">
<Grid>
<Rectangle Style="{StaticResource stlNavButtonRectangle}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="border"
Storyboard.TargetProperty="BorderBrush.Color"
To="Blue"
Duration="0:0:0.25"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="border"
Storyboard.TargetProperty="BorderBrush.Color"
To="#570000FF"
Duration="0:0:0.25"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="border"
Storyboard.TargetProperty="BorderBrush.Color"
To="Black"
Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<Button Content="Button 1" />
<Button Content="Button 2"/>
<Button Content="Button 3" />
</StackPanel>
I checked your code,
The MouseLeave Event is happening ,just change the Color #570000FF
I have an animation on mouse hover for button to change background and text color, but I wish to set it after the click, and my code does not working.
<Button Style="{StaticResource ButtonProduct}" x:Name="Overview_Button" Click="Overview_Button_Click" FontFamily="pack://application:,,,/Images/Fonts/#HandelGothicEF" Width="198" Height="50" Margin="0,30,0,20" FontSize="26">
<TextBlock FontFamily="Univers LT Std 57 Cn" FontSize="16" Text="Overview" />
</Button>
Generic XAML:
<!-- ButtonProduct -->
<Style x:Key="ButtonProduct" TargetType="Button">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="Border" CornerRadius="0" BorderThickness="0" Focusable="False" BorderBrush="Transparent" Background="White">
<ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="White" />
</Trigger>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation From="White" To="#52b0ca" Duration="0:0:0.5" Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation From="#52b0ca" To="White" Duration="0:0:0.5" Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Code:
private void Overview_Button_Click(object sender, RoutedEventArgs e)
{
var bc = new BrushConverter();
Overview_Button.Background = (Brush)bc.ConvertFrom("#51b0ce");
Clear_Main_Panel();
overviewObj = new Overview(family, Product_CombBox.SelectedIndex);
this.Center_Panel.Children.Add(overviewObj);
isOverview = true;
}
I am trying to change the Background color of my Button when the user clicks it. I am using triggers to achieve it.
My XAML is:
<UserControl.Resources>
<Style x:Key="myBtnStyle" TargetType="{x:Type Button}">
<!--VerticalAlignment="Top" VerticalContentAlignment="Top" Background="Blue" HorizontalAlignment="Right"
Height="24" Width="25" FontSize="16" FontWeight="Bold" -->
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Background" Value="Blue" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="Height" Value="24" />
<Setter Property="Width" Value="25" />
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Bold" />
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property="Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
<!--
<ControlTemplate x:Key="btnTemplate" TargetType="{x:Type Button}">
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True" >
<Setter Property="Background" Value="Cyan" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate> -->
</UserControl.Resources>
<Button DockPanel.Dock="Right" Style="{StaticResource myBtnStyle}" Name="btnVert" Click="btnVert_Click"
Margin="10,10,10,0" ToolTip="Vertical" Content="V" />
I tried various settings, but couldn't get the Background color changed on the Button when mouse is clicked. Also referred various sites - MSDN, SharpCorner, CodeProject and many others too. Couldn't get where am I going wrong?
How to get the Background color changed of Button on clicked event?
Thanks.
In this situation, you need to use EventTrigger with Storyboard, because [Source]:
EventTrigger - represents a trigger that applies a set of actions (animation storyboards) in response to an event.
Example:
<Window.Resources>
<SolidColorBrush x:Key="ButtonBrush" Color="OrangeRed" />
<Storyboard x:Key="ChangeBackgroundStoryboard">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ChangeBackgroundButton"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{StaticResource ButtonBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid>
<Grid.Triggers>
<EventTrigger SourceName="ChangeBackgroundButton"
RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource ChangeBackgroundStoryboard}" />
</EventTrigger>
</Grid.Triggers>
<Button Name="ChangeBackgroundButton"
Content="TestButton"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
</Grid>
Here Storyboard defined in resources, which defines the color ButtonBrush, which is set at the Click event. For more information, please see:
MSDN: EventTrigger
Edit
Yes, EventTrigger can be used in the template like this:
<Window.Resources>
<SolidColorBrush x:Key="IsMouseOverBackground" Color="AliceBlue" />
<SolidColorBrush x:Key="IsPressedBrush" Color="Gainsboro" />
<SolidColorBrush x:Key="ButtonBrush" Color="OrangeRed" />
<Storyboard x:Key="ChangeBackgroundStoryboard">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource ButtonBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Style x:Key="FlatButtonBaseStyle" TargetType="{x:Type Button}">
<Setter Property="Width" Value="60" />
<Setter Property="Height" Value="20" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="Border"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter Name="Content"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextBlock.FontFamily="{TemplateBinding FontFamily}"
TextBlock.FontSize="{TemplateBinding FontSize}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource IsMouseOverBackground}" />
<Setter Property="Opacity" Value="1" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource IsPressedBrush}" />
</Trigger>
<!-- Here -->
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource ChangeBackgroundStoryboard}" />
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<WrapPanel>
<Button Content="Fisrt"
Style="{StaticResource FlatButtonBaseStyle}"
Margin="10" />
<Button Content="Second"
Style="{StaticResource FlatButtonBaseStyle}"
Margin="10" />
<Button Content="Third"
Style="{StaticResource FlatButtonBaseStyle}"
Margin="10" />
</WrapPanel>
As for the possibility of contact to the other buttons through one Storyboard, you can do so:
<Window.Resources>
<SolidColorBrush x:Key="ButtonBrush" Color="OrangeRed" />
<SolidColorBrush x:Key="DefaultButtonBrush" Color="BlueViolet" />
</Window.Resources>
<WrapPanel>
<WrapPanel.Triggers>
<EventTrigger SourceName="FisrtButton"
RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FisrtButton"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{StaticResource ButtonBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondButton"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{StaticResource DefaultButtonBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ThirdButton"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{StaticResource DefaultButtonBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</WrapPanel.Triggers>
<Button Name="FisrtButton"
Content="Fisrt"
Margin="10" />
<Button Name="SecondButton"
Content="Second"
Margin="10" />
<Button Name="ThirdButton"
Content="Third"
Margin="10" />
</WrapPanel>
In this case, you just need to specify TargetName for every Button, when you click on the first Button, the color of the remaining changes to default BlueViolet:
In WPF, you can animate objects by using Storyboard.