i am beginner in wpf. i got a code from a site for wpf animation. animation start when dock panel load. i want to change animation play time. i want when user click on Ellipse then animation start and when user click on dock panel then animation will stop.here is code.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DockPanel>
<Ellipse Width="200" Height="200" Name="MyEllipse">
<Ellipse.Fill>
<RadialGradientBrush >
<GradientStop Offset="0" Color="#CCCCCCCC" />
<GradientStop Offset="0.5" Color="white" />
<GradientStop Offset="1" Color="black"/>
</RadialGradientBrush >
</Ellipse.Fill>
</Ellipse>
<DockPanel.Triggers>
<EventTrigger RoutedEvent="Page.Loaded">
<BeginStoryboard Name="MyBeginStoryBoard">
<Storyboard Name="MyStoryBoard">
<DoubleAnimation Storyboard.TargetName="MyEllipse" Storyboard.TargetProperty="(Ellipse.Height)"
From="0" To="200" AutoReverse="true"
RepeatBehavior="0:0:10" BeginTime="0:0:0" />
<DoubleAnimation Storyboard.TargetName="MyEllipse" Storyboard.TargetProperty="(Ellipse.Width)"
From="0" To="200" AutoReverse="true"
RepeatBehavior="0:0:10" BeginTime="0:0:0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</DockPanel.Triggers>
</DockPanel>
</Grid>
Change the RoutedEvent to PreviewMouseDown instead of Page.Loaded.
EDIT :
You can stop the animation by adding this trigger to the DockPanel.Triggers:
<EventTrigger SourceName="MyEllipse" RoutedEvent="Ellipse.PreviewMouseDown">
<StopStoryboard BeginStoryboardName="MyBeginStoryBoard" />
</EventTrigger>
This will let you stop the animation by clicking on the Ellipse.
See MSDN for samples on pause/resume etc.
Related
I wish to animate background color change from yellow to red with a flow from left to right. How to achieve this kind of animation in wpf?
A ColorAnimation could provide the gradual change from yellow to red but because you want it to flow from left to right it might be easier to use a LinearGradient.
Set it up like this
GradientStopOffet, color
0, red
0, red
0, yellow
1, yellow
This would make the area completely yellow.
Then you animate the offset of the third gradientstop from 0 to 1
This would slowly turn the area into a gradient from red to yellow.
Once this animation has finished (or is half way) animate the second gradientstop offset from 0 to 1
This would make the entire area red.
By moving the second and third gradientstops the brush will have a 'smooth' color transition between the four gradient stops: between the first and the second, the second and the third and the third and fourth. At the beginning and at the end the transitions between the gradients stops that are at the same offset are not visible and thereby hide the color transition.
Here is an example. Play around with the starting times and durations to make the animation to your liking.
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<Storyboard x:Key="ToRed" >
<DoubleAnimation Storyboard.TargetName="YellowStop"
Storyboard.TargetProperty="Offset"
To="1"
Duration="0:0:1" />
<DoubleAnimation Storyboard.TargetName="RedStop"
Storyboard.TargetProperty="Offset"
BeginTime="0:0:0.5"
To="1"
Duration="0:0:1" />
</Storyboard>
</Window.Resources>
<Grid>
<StackPanel VerticalAlignment="Top"
Orientation="Horizontal">
<Button Click="ToRedButton_Click">To red</Button>
</StackPanel>
<Rectangle Margin="0,50,0,0">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,0">
<GradientStop Offset="0"
Color="Red" />
<GradientStop x:Name="RedStop"
Offset="0"
Color="Red" />
<GradientStop x:Name="YellowStop"
Offset="0"
Color="Yellow" />
<GradientStop Offset="1"
Color="Yellow" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Window>
C# code for the button click:
private void ToRedButton_Click(object sender, RoutedEventArgs e)
{
var toRedAnimation = this.FindResource("ToRed") as Storyboard;
if(toRedAnimation != null)
{
toRedAnimation.Begin();
}
}
If you want a hard transition, animate the offset of the redstop at the same start time as the yellow animation.
Here is another setup, it looks different and animates the color:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<Storyboard x:Key="ToRed2">
<DoubleAnimation Storyboard.TargetName="MiddleStop"
Storyboard.TargetProperty="Offset"
To="1"
Duration="0:0:1" />
<ColorAnimation Storyboard.TargetName="MiddleStop"
Storyboard.TargetProperty="Color"
BeginTime="0:0:1"
To="Red"
Duration="0:0:1" />
</Storyboard>
</Window.Resources>
<Grid>
<StackPanel VerticalAlignment="Top"
Orientation="Horizontal">
<Button Click="ToRedButton_Click">To red</Button>
</StackPanel>
<Rectangle Margin="0,50,0,0">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,0">
<GradientStop Offset="0"
Color="Red" />
<GradientStop x:Name="MiddleStop"
Offset="0"
Color="Yellow" />
<GradientStop Offset="1"
Color="Yellow" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Window>
I can suggest you to use blend. This is the most easy way to edit your xaml.
I'm trying to come up with a creative solution to give this particular effect:
My initial idea: A dynamically sized rectangle with a chroma key shader effect will slide into place over the text. However, I do not want to kill the fidelity of the text edges which tends to happen with shaders.
I also considered using the FormattedText class, though I'm not sure it supports what I'm trying to do.
Any suggestions?
EDIT
To clarify, the text will be essentially a 'TabItem'. I would like the highlighted block to float across all tab items to the selected item. They are currently laid out in a Canvas with logic handling their positioning. A simple animation would not suffice it would seem.
This should give you the effect you want. This uses a gradient brush for the color, but it uses 3 gradient stops to make sure that the color changes immediately from one to the next with no gradient in between.
<Window
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:TestingWPF"
mc:Ignorable="d"
x:Class="TestingWPF.TestWindow"
d:DesignWidth="477" d:DesignHeight="214"
Background="Black">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="74" FontWeight="Bold">
<TextBlock.Foreground>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="White" Offset="0"/>
<GradientStop x:Name="WhiteOffset" Color="White" Offset="1"/>
<GradientStop x:Name="GrayOffset" Color="Gray" Offset="1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard Storyboard.TargetProperty="Offset" Duration="0:0:1" RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="WhiteOffset" From="0" To="1" />
<DoubleAnimation Storyboard.TargetName="GrayOffset" From="0" To="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
Some Text
</TextBlock>
</Window>
I have a button that loads more data into a datagrid when clicked. To indicate progress, I change the text of the button to change from "More" to "Loading..." where the periods are animated. Next, I wanted to add a "glint" effect so that the text catches your eye. If you've used an iPhone/iPod Touch, I'm thinking of the effect on the "Slide To Unlock" text of the lock screen.
To do so, I shift a middle, lighter gradient stop from left to right. Because the animation continuously loops, I used offsets outside of the valid range to create a delay between the times when the light gradient stop is actually visible.
I got this implemented but I can tell that for some reason, the light gradient is not starting at the left edge of the text. It starts at about the 'a' in the "Loading". I accepted that and it's been in place for a while, but I'm now coming back to it just to try to understand why. It seems like maybe it's using the measure of the original text when calculating the animation, but I thought the animations were supposed to apply to each other when in the same storyboard. Here is my code:
<UserControl.Resources>
<local:EmptyBatchNumConverter x:Key="emptyBatchNumConverter" />
<BeginStoryboard x:Key="bsbLoadingMore" x:Name="bsbLoadingMore">
<Storyboard x:Name="sbLoadingMore">
<StringAnimationUsingKeyFrames Storyboard.TargetName="txtBtnMoreText" Storyboard.TargetProperty="Text" Duration="0:0:2" FillBehavior="Stop" RepeatBehavior="Forever">
<DiscreteStringKeyFrame Value="Loading" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="Loading." KeyTime="0:0:0.5" />
<DiscreteStringKeyFrame Value="Loading.." KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="Loading..." KeyTime="0:0:1.5" />
</StringAnimationUsingKeyFrames>
<!--Animate the OffSet of the light gradient stop for a "glint" effect. Using -4.5 to 4.5 to delay the visible effect between repeats (and
control the speed relative to the duration). Using an extra .4 seconds to offset the frequency from the text animation. -->
<DoubleAnimation Storyboard.TargetName="gs2" Storyboard.TargetProperty="Offset" From="-4.5" To="4.5" Duration="0:0:2.4" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</UserControl.Resources>
...
<Button Name="btnMore" Grid.Row="1" Style="{StaticResource OasisGridMoreButton}" Click="btnMore_Click" Visibility="Visible" Height="16">
<Button.Content>
<TextBlock Name="txtBtnMoreText" MinWidth="48" Text="More..." /> <!--MinWidth = width of "Loading..."-->
</Button.Content>
<Button.Foreground>
<LinearGradientBrush StartPoint="0.2,0" EndPoint="1,1">
<GradientStop x:Name="gs1" Color="Black" Offset="0"/>
<GradientStop x:Name="gs2" Color="Cyan" Offset="-4.5"/>
<GradientStop x:Name="gs3" Color="Black" Offset="1" />
</LinearGradientBrush>
</Button.Foreground>
</Button>
Here is the problem:
<LinearGradientBrush StartPoint="0.2,0" EndPoint="1,1">
Change it to:
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
Here is the full test app I made (slowed down glint to see it better):
<Window
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" mc:Ignorable="d"
x:Class="WpfApplication4.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<Storyboard x:Key="OnLoaded1"/>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard x:Name="bsbLoadingMore">
<Storyboard x:Name="sbLoadingMore">
<StringAnimationUsingKeyFrames Storyboard.TargetName="txtBtnMoreText" Storyboard.TargetProperty="Text" Duration="0:0:2" FillBehavior="Stop" RepeatBehavior="Forever">
<DiscreteStringKeyFrame Value="Loading" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="Loading." KeyTime="0:0:0.5" />
<DiscreteStringKeyFrame Value="Loading.." KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="Loading..." KeyTime="0:0:1.5" />
</StringAnimationUsingKeyFrames>
<!--Animate the OffSet of the light gradient stop for a "glint" effect. Using -4.5 to 4.5 to delay the visible effect between repeats (and
control the speed relative to the duration). Using an extra .4 seconds to offset the frequency from the text animation. -->
<DoubleAnimation Storyboard.TargetName="gs2" Storyboard.TargetProperty="Offset" From="-4.5" To="4.5" Duration="0:0:5.4" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Button x:Name="btnMore" Visibility="Visible" Margin="0,213,0,182" d:LayoutOverrides="GridBox">
<Button.Foreground>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop x:Name="gs1" Color="Black" Offset="0"/>
<GradientStop x:Name="gs2" Color="Cyan" Offset="0"/>
<GradientStop x:Name="gs3" Color="Black" Offset="1" />
</LinearGradientBrush>
</Button.Foreground>
<TextBlock x:Name="txtBtnMoreText" MinWidth="48" Text="More..." />
</Button>
</Grid>
For some reason, it is not showing the </Window> at the end...
I have the following xaml code. The XAML displays an animation on the button whenever the button is click. I want to start/stop the animation whenever a boolean property in the view model is changed. Any help is appreciated in advance.
<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" Duration="0:0:1" AutoReverse="True" RepeatBehavior="5x" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
<Button.Content>
<Grid Width="94">
<Border HorizontalAlignment="Left" Width="0" Name="myBorder">
<Border.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.115" Color="Black" />
<GradientStop Offset="0.715" Color="Red" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<TextBlock FontSize="14" HorizontalAlignment="Center">Search</TextBlock>
</Grid>
</Button.Content>
</Button>
Also how can i animate the button in such a way that once the border width has reached its max width a reverse animation should occur. I mean i want a wave like effect(using gradient) inside the button. The wave should turn back once it hits the rightmost end of the button. Same should repeat indefinitely. This animation will be controlled using a ViewModel boolean property.
I have a very strange problem with a ColorAnimation. What I want to do is pretty simple (I think): I have a Rectangle with a GradientBrush as a background. This rectangle has different VisualStates that change the colors of the gradient. I want to put an animation for the transition between the states. My problem is that when I change the state, the animation does not start with the current color, but with the default color.
Here is a code snippet that can help you reproduce this:
<Window x:Class="TestColorAnimation.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" x:Name="rect">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="OrangeState">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Color"
Storyboard.TargetName="stop1"
To="Orange" />
</Storyboard>
</VisualState>
<VisualState x:Name="RedState">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Color"
Storyboard.TargetName="stop1"
To="Red" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop x:Name="stop1" Color="LightGray" Offset="0" />
<GradientStop x:Name="stop2" Color="LightGray" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Button Grid.Row="1" Grid.Column="0" Content="Go to orange"
x:Name="orangeButton" Click="orangeButton_Click" />
<Button Grid.Row="1" Grid.Column="1" Content="Go to red"
x:Name="redButton" Click="redButton_Click" />
</Grid>
</Window>
The event handlers just call for the state change:
private void orangeButton_Click(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToElementState(this.rect, "OrangeState", true);
}
private void redButton_Click(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToElementState(this.rect, "RedState", true);
}
In this case, if I go to the orange state, the animation goes from gray to orange. But then, when I go to the red state, the animation goes from gray to red. I would like (and expected) it to go from orange to red.
I have tried to use a SolidColorBrush instead of the LinearGradientBrush and the transitions are happening as expected. I also tried to use the storyboards outside of the VisualStates (but with a LinearGradientBrush) and it also works as expected. The only situation in which I have reproduced this issue is the one in the example: LinearGradientBrush and ColorAnimation in a VisualState.
Am I doing something wrong? Is what I want possible?
Animating the LinearGradients will work if you change the target to the GradientStop Color directly:
<VisualState x:Name="OrangeState">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty = "(Rectangle.Fill).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="rect"
To="Orange" />
</Storyboard>
</VisualState>
<VisualState x:Name="RedState">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty = "(Rectangle.Fill).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="rect"
To="Red" />
</Storyboard>
</VisualState>