WPF : How to animate a button on click of another button? - wpf

I have the following XAML code:
<Button Content="Menu 1" Height="23" Name="button1" Width="75" Margin="10">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" From="0" To="200" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.RenderTransform>
<TranslateTransform X="0" Y="0" />
</Button.RenderTransform>
</Button>
This code moves the button in the Y direction when the mouse is over the button.
However, I want the same functionality when I move my mouse over another button.
In short, let's assume I have Button1 and Button2. When I move my mouse over Button1, the Button2 should move down in the Y direction. How can I achieve this. Could anyone provide a working XAML code for the same.

You could subclass Button and add a property named ButtonToAnimate.
In the event trigger, point the Target of the DoubleAnimation to the ButtonToAnimate.

Related

Adding content/text in rectangle WPF

This is my code for rectangle :
<Rectangle x:Name="rect1" Grid.Column="1" Fill="#FF5C626C" HorizontalAlignment="Left" Height="50" Margin="36,171,0,0" StrokeThickness="2" VerticalAlignment="Top" Width="358" RadiusX="30" RadiusY="50">
<Rectangle.Triggers>
</Rectangle.Triggers>
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ParallelTimeline >
<ColorAnimation Storyboard.TargetProperty="Fill.Color" To="#FF767C84" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Rectangle.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ParallelTimeline >
<ColorAnimation Storyboard.TargetProperty="Fill.Color" To="#FF5C626C" />
</ParallelTimeline>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
My question is how do i add a text/content in the rectangle ?
One might suggest using a code block, but if u go through my code, youu'll notice that the rectangle changes it's color on mouseover.So if i put a textblock over the rectangle,the mouseover doesn't work properly(as the textblock covers the entire rectangle).
Another suggestion would be to use a border.But i am not sure about this as i need to find the code to apply mouse over effect on a border.
The next suggestion might be to use a button instead.I would've but my rectangle has corner radius and is a bit round-shaped which, if i use a button, would be hard to achieve.
So how do i add content/text inside the rectangle?
If you feel you definitely have to use a rectangle, put it in a grid and add a TextBlock element above it.
By setting the TextBlock's IsHitTestVisible property to False all hit-testing (mouse events) will be ignored on it and fall through to your rectangle.
<Grid>
<Rectangle (...your attributes here...)>
(...your rectangle code here...)
</Rectangle>
<TextBlock Text="Hello World!" IsHitTestVisible="False" />
</Grid>

Expander getting stuck after IsExpanded set to true by storyboard

So I have an expander that I want to have the normal functionality (open and close with its own button) but I also want a different button to expand it when pressed (this button is in the header of the expander). I'm using a storyboard in an event trigger for the Button.Click which works, but after it is expanded this way the normal button doesn't work, it just stays expanded. My xaml is below, I would really prefer to keep this all in the xaml, I could come up with a way to do it in the codebehind/viewmodel myself.
<Expander x:Name="IndexExpander" IsExpanded="True" Grid.Row="4" Grid.ColumnSpan="5" Margin="10" MaxHeight="150">
<Expander.Triggers>
<EventTrigger SourceName="btnAddIndex" RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="IndexExpander" Storyboard.TargetProperty="IsExpanded" BeginTime="0:0:0.25" Duration="0:0:0.20" >
<DiscreteBooleanKeyFrame KeyTime="0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Expander.Triggers>
<Expander.Header>
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
<TextBlock Text="Indexes" FontWeight="Bold"/>
<!-- Add/Delete Buttons-->
<Grid Margin="10,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" x:Name="btnAddIndex" Command="{Binding AddIndexCommand}" Template="{StaticResource AddButtonTemplate}" IsEnabled="{Binding IsEditable}" Margin="0,0,5,0" />
</Grid>
</StackPanel>
</Expander.Header>
Alright, so for anyone following in my footsteps here's what I did. I got the idea from here, and adapted it until it worked correctly.
<Expander.Triggers>
<EventTrigger SourceName="btnAddCol" RoutedEvent="Button.Click">
<BeginStoryboard x:Name="ColumnExpanderStory">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="ColumnExpander" Storyboard.TargetProperty="IsExpanded">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ToggleButton.PreviewMouseUp">
<RemoveStoryboard BeginStoryboardName="ColumnExpanderStory" />
</EventTrigger>
</Expander.Triggers>
<Expander.Header>
The problem was that the storyboard overrides any other bindings to the IsExpanded property, so it has to be removed to restore them (read more here). The suggestion was to use the ToggleButton.Checked event to remove the storyboard, but that didn't work for me, only the "Preview" events seemed to have the right timing. I started with PreviewMouseDown, but it would remove the storyboard, then on mouse up toggle the expander, meaning the first click would just flip states back and forth quickly. Using PreviewMouseUp got around that issue.

Can not find the EventTrigger.SourceName

<Canvas>
<Button Name="b1" Content="Button"/>
<Rectangle Name="Mr1" Fill="Black">
<Rectangle.Triggers>
<EventTrigger SourceName="b1" RoutedEvent="Button.Click">
<BeginStoryboard>
<code.../>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
Error: can not find the b1.
Please help me, thank you.
I was just facing this same problem.. posting the solution for anyone else interested.
<Canvas>
<Canvas.Resources>
<Storyboard x:Key="MyAwesomeAnimation" Storyboard.TargetName="Mr1" Storyboard.TargetProperty="Height">
<!-- Some Awesome animation here..-->
</Storyboard>
</Canvas.Resources>
<Button Name="b1" Content="Button">
<Button.Triggers>
<!--The key is to define the click trigger on the button. Why should the rectangle know about the button?-->
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource MyAwesomeAnimation}"></BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
<Rectangle Name="Mr1" Fill="Black" />
</Canvas>
You can set this property to the name of any element within the scope of where the trigger collection (the collection that this Trigger is part of) is applied. This is typically a named element that is within the template that contains this Trigger.

Creating button content with centered text and animated border

The following XAML code creates a button with a border as its content. The border has a TextBlock as it's child. When you CLICK on the button, the border width gradually grows.
Since the text block is inside the border it is not seen until you click the button.
Now my requirements are:
There should be a text displayed on the button even before you click it.
Even after you click the button, only the border should animate while the button text remains in its center position.
<Button Name="button5" Width="100" Margin="10" HorizontalContentAlignment="Left">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="myBorder" Storyboard.TargetProperty="Width" From="0" To="94" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
<Button.Content>
<Border Background="Gray" Width="0" Name="myBorder">
<TextBlock>Search</TextBlock>
</Border>
</Button.Content>
</Button>
I will appreciate if anyone is able to provide answers with working XAML code.
I've modified your XAML only slightly:
<Button Name="button5" Width="100" Margin="10" HorizontalContentAlignment="Left">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="myRectangle" Storyboard.TargetProperty="Width" From="0" To="94" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
<Button.Content>
<Grid>
<Rectangle x:Name="myRectangle" Fill="Gray" Width="0" HorizontalAlignment="Left" />
<TextBlock Text="Search" />
</Grid>
</Button.Content>
</Button>
For the Button's content, you could use a Grid which contains your Border and the TextBlock. Since no columns or rows are specified, the TextBlock and the Border are drawn on top of each other. It situations like this where the Border does not have content, I prefer to use a Rectangle instead since it is bit lighter. Hope this helps!

Scale transform in xaml (in a controltemplate) on a button to perform a "zoom"

I've got a button with an image in it and it's being styled by the following:
<ControlTemplate x:Key="IconButton" TargetType="Button">
<Border>
<ContentPresenter Height="80" Width="80" />
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation From="1" To="0.5" Duration="0:0:0.5" />
<DoubleAnimation From="0.5" To="1" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard TargetProperty="Width">
<DoubleAnimation From="80" To="95" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Button is as follows:
<Button Template="{StaticResource IconButton}" Name="btnExit">
<Image Source="Images/Exit.png" />
</Button>
The problem is that the width doesn't change when my mouse goes over. (Or at least - the width of the image does not...)
I believe there is a "scale" transform I can use to enlarge the button and all it's contents? how would I do that here...?
Thanks.
Your template seems to be pretty minimal but I'm assuming your only just getting started on it, however this will help you get started with using a ScaleTransform as opposed to animating the width.
The ScaleTransform can be applied to the RenderTransform property of either the Button itself or just the Border of your template. This could be a TransformGroup if you want to do more than just Scale (i.e. a composite transform consisting of other tranforms such as Translate, Rotate, Skew) but to keep it simple and for examples sake something like the following applies a single ScaleTransform value to the Button:
<Button Template="{StaticResource IconButton}" Name="btnExit">
<Button.RenderTransform>
<ScaleTransform ScaleX="1.0" ScaleY="1.0"></ScaleTransform>
</Button.RenderTransform>
<Image Source="Images/Exit.png" />
</Button>
or this to apply to the Border of the ControlTemplate:
<ControlTemplate x:Key="IconButton" TargetType="Button">
<Border Background="Blue" x:Name="render">
<Border.RenderTransform>
<ScaleTransform ScaleX="1.0" ScaleY="1.0"></ScaleTransform>
</Border.RenderTransform>
<ContentPresenter Height="80" Width="80" />
</Border>
...
...
Next you will want to change your MouseEnter trigger to target that property and for width you will want to target the ScaleX property of the ScaleTransform. The following Storyboard will scale the Button 2.5 times in the X direction (add TargetName="render" to <Storyboard... if you have chosen to apply the Transform to the Border as opposed to the Button).
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard>
<Storyboard TargetProperty="RenderTransform.ScaleX">
<DoubleAnimation To="2.5" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
If you were to use a TransformGroup with a number of transforms you would change the TargetProperty value to something like RenderTransform.(TransformGroup.Children)[0].ScaleX assuming the ScaleTransform is the first child of the group.
This should get you up and running with what you need and you can take it where you want from there...
HTH

Resources