WPF Animate and change Opacity of Image in sequence - c#

I have three images, two of these images animate as follow and third image should blink:
<Window.Resources>
<Storyboard x:Key="AnimateTarget" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames BeginTime="0:0:0" Duration="0:00:03" Storyboard.TargetName="img1" Storyboard.TargetProperty="Y">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="200" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0:0:2" Duration="0:00:03" Storyboard.TargetName="img2" Storyboard.TargetProperty="x">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="200" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="0:0:4" Duration="0:0:0.5" Storyboard.TargetProperty="(Image.Opacity)" Storyboard.TargetName="img3" From="1.0" To="0.0" RepeatBehavior="Forever" AutoReverse="True" />
</Storyboard>
</Window.Resources>
The first two images are animating fine but the third image doesn’t blink, it will do nothing and just stay there as you can see I have used the following code for blinking the third image:
<DoubleAnimation BeginTime="0:0:4" Duration="0:0:0.5" Storyboard.TargetProperty="(Image.Opacity)" Storyboard.TargetName="img3" From="1.0" To="0.0" RepeatBehavior="Forever" AutoReverse="True" />
Also this is a code for the third image:
<Image Height="65" Name="image1" Stretch="Fill" Width="67" Source="/PicTakeWPF;component/Images/422505_110594629067212_100003500265268_37406_1212153553_n.jpg">
<Image.RenderTransform>
<TranslateTransform x:Name="img3"></TranslateTransform>
</Image.RenderTransform>
</Image>
I would appreciate if someone helps me on this
Thanks,

Try using the Name (image1) of your image object as Storyboard.TargetName for the opacity animation
<DoubleAnimation BeginTime="0:0:4" Duration="0:0:0.5" Storyboard.TargetProperty="(Image.Opacity)" Storyboard.TargetName="image1" From="1.0" To="0.0" RepeatBehavior="Forever" AutoReverse="True" />
because the opacity is a property of the image itself, the other 2 animations affect the translation of the image object and that's why you use the TranslateTransform name for those animations.
You don't even need to add
<Image.RenderTransform>
<TranslateTransform x:Name="img3"></TranslateTransform>
</Image.RenderTransform>
for the third image (if you're not planning on animating the translation).

Related

UWP Hide TabView Footer

I have TabView that basically looks like this:
<controls:TabView
x:Name="PlaylistTabView">
<controls:TabView.ItemHeaderTemplate>
<DataTemplate x:DataType="data:Playlist">
// Something
</DataTemplate>
</controls:TabView.ItemHeaderTemplate>
<controls:TabView.ItemTemplate>
<DataTemplate x:DataType="data:Playlist">
<local:HeaderedPlaylistControl IsPlaylist="True" Loaded="HeaderedPlaylistControl_Loaded" />
</DataTemplate>
</controls:TabView.ItemTemplate>
<controls:TabView.TabStartHeader>
// Something
</controls:TabView.TabStartHeader>
<controls:TabView.TabEndHeader>
// Something
</controls:TabView.TabEndHeader>
<controls:TabView.Footer>
<RelativePanel
x:Name="PlaylistFooter"
Height="{StaticResource PlaylistTabFooterHeight}"
RenderTransformOrigin="0,0">
<RelativePanel.RenderTransform>
<TranslateTransform />
</RelativePanel.RenderTransform>
<local:IconTextButton
x:Name="ShowAllPlaylistButton"
Padding="10,5"
IconTextMargin="0,0,10,0"
LabelPosition="Left"
RelativePanel.AlignRightWithPanel="True"
Style="{StaticResource PlaylistIconTextButtonStyle}"
ToolTipService.ToolTip="Show All Playlists">
<local:IconTextButton.Icon>
<FontIcon
x:Name="UpArrowIcon"
FontFamily="Segoe MDL2 Assets"
FontWeight="{x:Bind ShowAllPlaylistButton.FontWeight}"
Glyph=""
RenderTransformOrigin=".5,.5">
<FontIcon.RenderTransform>
<RotateTransform />
</FontIcon.RenderTransform>
</FontIcon>
</local:IconTextButton.Icon>
<local:IconTextButton.Flyout>
<MenuFlyout Closed="ClosePlaylistsFlyout" Opening="OpenPlaylistsFlyout" />
</local:IconTextButton.Flyout>
</local:IconTextButton>
<local:IconTextButton
x:Name="SortByButton"
Padding="10,5"
HorizontalAlignment="Right"
Icon="Sort"
IconTextMargin="10,0,0,0"
Label="Sort By Title"
LabelPosition="Right"
RelativePanel.AlignLeftWithPanel="True"
Style="{StaticResource PlaylistIconTextButtonStyle}"
Tapped="SortByButton_Tapped"
ToolTipService.ToolTip="Sort Playlists" />
</RelativePanel>
</controls:TabView.Footer>
</controls:TabView>
I have a local:HeaderedPlaylistControl in the ItemTemplate which is basically a ListView. I want to implement the effect that as you scroll down the footer will translate down and when you scroll up the footer will quickly show up.
I am able to implement such effect. However, I am only moving the PlaylistFooter not the TabView.Footer, meaning that the Footer lingers and leaves a blank space at the bottom as is shown in the picture below. How can I move the footer as well?
I checked your code, I found you have implemented TranslateTransform for PlaylistFooter, if you just move the PlaylistFooter down not set Visibility as Collapsed, the footer will still display, So the better way is set Visibility as Collapsed.
<VisualStateGroup x:Name="FooterVisibilityStates">
<VisualState x:Name="FooterFadeIn">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PlaylistFooter" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaylistFooter" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.3" Value="Visibility" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FooterFadeOut">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PlaylistFooter" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaylistFooter" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.4" Value="Collapsed" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaylistFooter" Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteObjectKeyFrame KeyTime="0" Value="False" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
Update
After discuss with Seaky Luo, we found a solution that set PlaylistFooter height as 0 when the list view scroll down. For more please refer the following code.
<Storyboard x:Name="HideFooterAnimation">
<DoubleAnimation
Storyboard.TargetName="PlaylistFooter"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)"
To="0"
Duration="0:0:0.1" />
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="PlaylistFooter"
Storyboard.TargetProperty="Height"
Duration="0:0:0.1">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PlaylistTabFooterHeight}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Name="ShowFooterAnimation">
<DoubleAnimation
Storyboard.TargetName="PlaylistFooter"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)"
To="{StaticResource PlaylistTabFooterHeight}"
Duration="0" />
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="PlaylistFooter"
Storyboard.TargetProperty="Height"
Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="0" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>

How to reset control after ScaleTransform animation

I am working on a Windows 10 universal application targeting PC. I want to run an animation repeatedly (not in a "RepeatBehaviour" loop, but run it again after something else happens), but I am struggling with resetting the animated control AFTER animation completes.
One of the animations in a storyboard is TranslateTransform. After it completes, I can re-position the control using Canvas.SetLeft and Canvas.SetTop in code. However, after I "disappear" a control using ScaleTransform animation the control remains invisible and I cannot make it visible again. Changing control Height and Width does nothing.
Using AutoReverse in XAML does resolve the issue, but I do not want this to be visible to the user. The control is supposed to "disappear". I want to reset the control in code before the next run, behind the scenes.
My Storyboard and the Border control which I am animating are shown below. This works fine the first time. The image flies across the screen with some rotation and then disappears. Second time the image is invisible until the scale transform runs again.
I tried adding another ScaleTransform animation before the first key frame, to scale from 0 to 1 quickly (I tried duration of "0" or "0.1") but that breaks the whole thing for some reason.
I wonder if RenderTransformOrigin has something to do with this, but am unsure how to use it with TransformGroup. So it is set to (0.5,0.5) to center the rotation.
Any help would be appreciated.
<Storyboard x:Name="myStoryboard">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(Canvas.Top)"
EnableDependentAnimation="False">
<SplineDoubleKeyFrame x:Name="MyTopSpline" KeyTime="0:0:1.9"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(Canvas.Left)"
EnableDependentAnimation="False"">
<SplineDoubleKeyFrame x:Name="MyLeftSpline" KeyTime="0:0:1.9"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"
From="0" To="360" BeginTime="0:0:1.0" Duration="0:0:1.9" />
<DoubleAnimation Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleX)"
From="1" To="0" BeginTime="0:0:1.9" Duration="0:0:0.9" />
<DoubleAnimation Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(ScaleTransform.ScaleY)"
From="1" To="0" BeginTime="0:0:1.9" Duration="0:0:0.9" />
</Storyboard>
<Border Name="myImage" Height="244" Width="244" Canvas.Left="200" Canvas.Top="100" Visibility="Collapsed"
RenderTransformOrigin=".5,.5">
<Border.RenderTransform>
<TransformGroup>
<RotateTransform Angle="0" />
<ScaleTransform ScaleX="1" ScaleY="1" />
</TransformGroup>
</Border.RenderTransform>
</Border>
First, let's clean up your code a bit. Instead of using a TransformGroup, you should use a composite transform object called CompositeTransform as it's a lot easier to work with. Don't forget to name it too.
<Border.RenderTransform>
<CompositeTransform x:Name="myImageTransform" />
</Border.RenderTransform>
So now your Storyboard should look like the following. Note that I have added a myStoryboard_Completed handler to it.
<Storyboard x:Name="myStoryboard"
Completed="myStoryboard_Completed">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(Canvas.Top)">
<SplineDoubleKeyFrame x:Name="MyTopSpline" KeyTime="0:0:1.9" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(Canvas.Left)">
<SplineDoubleKeyFrame x:Name="MyLeftSpline" KeyTime="0:0:1.9" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)"
From="0"
To="360"
BeginTime="0:0:1.0"
Duration="0:0:1.9" />
<DoubleAnimation Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
From="1"
To="0"
BeginTime="0:0:1.9"
Duration="0:0:0.9" />
<DoubleAnimation Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
From="1"
To="0"
BeginTime="0:0:1.9"
Duration="0:0:0.9" />
</Storyboard>
Inside this handler, all you need to do is to reset all the transform attributes and canvas offsets.
private void myStoryboard_Completed(object sender, object e)
{
myImage.Visibility = Visibility.Collapsed;
Canvas.SetTop(myImage, 100);
Canvas.SetLeft(myImage, 200);
myImageTransform.Rotation = 0;
myImageTransform.ScaleX = myImageTransform.ScaleY = 1;
}
But here is a better way.
Instead of doing some of the stuff in code behind, why not wrap all the logic inside the same Storyboard? All you need is to use DoubleAnimationUsingKeyFrames to define both start and end values for each of your animations.
<Storyboard x:Name="myStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(Canvas.Top)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="100" />
<SplineDoubleKeyFrame x:Name="MyTopSpline" KeyTime="0:0:1.9" Value="100" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="myImage"
Storyboard.TargetProperty="(Canvas.Left)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="200" />
<SplineDoubleKeyFrame x:Name="MyLeftSpline" KeyTime="0:0:1.9" Value="200" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)"
Storyboard.TargetName="myImage">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.9" Value="360" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
Storyboard.TargetName="myImage">
<EasingDoubleKeyFrame KeyTime="0" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:1.9" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:2.8" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
Storyboard.TargetName="myImage">
<EasingDoubleKeyFrame KeyTime="0" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:1.9" Value="1" />
<EasingDoubleKeyFrame KeyTime="0:0:2.8" Value="0" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="myImage">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame KeyTime="0:0:3">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
Hope this helps!
Adding this line of code to StoryBoard completed event resolved the issue:
MyStoryboard.Stop();

WPF animate button Image

I have a button on which I am adding 2 images. Later on I have to put animation on these images of button.
In below Xaml code I am using button template but after applying the templates button original behavior is lost like there is no border, no change on mouse cursor when hover etc. It is just apear as plan image.
How can I put back the button default behaviour?
<Button Height="89" Margin="0,62,158,0" Name="buttonStart" VerticalAlignment="Top" Click="buttonStart_Click" HorizontalAlignment="Right" Width="133" >
<Button.Template>
<ControlTemplate TargetType="Button" >
<Grid>
<Image x:Name="Normal" Source="/TFSCheckinReportGenerator;component/Resource/generate.png" Height="80" Width="80" Opacity="1"></Image>
<Image x:Name="Waiting" Source="/TFSCheckinReportGenerator;component/Resource/waiting.png" Height="80" Width="80" Opacity="0"></Image>
</Grid>
<ControlTemplate.Resources>
<Storyboard x:Key="ChangeImageToWaiting">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Normal" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Waiting" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Progress" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Waiting" Storyboard.TargetProperty="Width" Duration="00:00:01" AutoReverse="True">
<SplineDoubleKeyFrame Value="40"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Waiting" Storyboard.TargetProperty="Height" Duration="00:00:01" AutoReverse="True">
<SplineDoubleKeyFrame Value="40"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
</ControlTemplate>
</Button.Template>
</Button>
Instead of Template and ControlTemplate use ContentTemplate and DataTemplate and it will helps to show button original behavior like border and change button appearance on mouse hover etc.
Template defines the appearance of the control. ContentTemplate specifies how the content contained in/displayed by a ContentControl is to be displayed.
<Button Height="89" Margin="0,62,158,0" Name="buttonStart" VerticalAlignment="Top" HorizontalAlignment="Right" Width="133" >
<Button.ContentTemplate>
<DataTemplate>
<Grid>
<Image x:Name="Normal" Source="catalogscreen.png" Height="80" Width="80" Opacity="1"></Image>
<Image x:Name="Waiting" Source="catalogscreen.png" Height="80" Width="80" Opacity="0"></Image>
</Grid>
<DataTemplate.Resources>
<Storyboard x:Key="ChangeImageToWaiting">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Normal" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Waiting" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Progress" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Waiting" Storyboard.TargetProperty="Width" Duration="00:00:01" AutoReverse="True">
<SplineDoubleKeyFrame Value="40"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Waiting" Storyboard.TargetProperty="Height" Duration="00:00:01" AutoReverse="True">
<SplineDoubleKeyFrame Value="40"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</DataTemplate.Resources>
</DataTemplate>
</Button.ContentTemplate>
</Button>

my storyboard skips some keyframes

I would like to swing an ellipse to one place and then shrink it. After the first storyboard stops, I intend to stretch the ellipse with the ellipse. However the shrinking process doesn't work at all. Hard to firgure out why~ Any help or tips will be appreciated. Thanks~
<Window.Resources>
<Storyboard x:Key="Swing" Duration="0:0:7">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="Leg" AutoReverse="True" RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0" Value="27.081"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-25.783"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="Leg">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:6" Value="489.676"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="Leg">
<EasingDoubleKeyFrame KeyTime="0:0:6" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:7" Value="0.2"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Swing2" BeginTime="0:0:7">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="Leg">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0.2"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard x:Name="Swing_BeginStoryboard" Storyboard="{StaticResource Swing}"/>
<BeginStoryboard x:Name="Swing_BeginStoryboard1" Storyboard="{StaticResource Swing2}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Ellipse x:Name="Leg" Fill="#FFF4F4F5" HorizontalAlignment="Left" Margin="156,204,0,147" Stroke="Black" Width="33" RenderTransformOrigin="0.464,-0.014">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="27.081"/>
<TranslateTransform/>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
</Grid>
If I change the second storyboard as below, the ellipse will be shinking from the beginning.
<Storyboard x:Key="Swing2">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="Leg">
<EasingDoubleKeyFrame KeyTime="0:0:7" Value="0.2"/>
<EasingDoubleKeyFrame KeyTime="0:0:9" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>

How to create a Progress Ring like Windows 8 Style in WPF?

I want to show progress in my Desktop apps like Windows 8 ProgressRing. This type of progress is shown at times of installation or when Windows Start, but this control can be used in many applications as its very clean and modern, but I don't know how to achieve that. The progress ring image is here.
Please see the image:
May I know how do I code for it may be in XAML or in Code? I have seen that in WPF ProgressRing control is not present, so I have to go to some custom control. Idea link or suggestions please how can I proceed.
Using MahApps.Metro would be much simpler, but given below is a simple Metro-like wait indicator showing how it would be done in XAML.
<Viewbox>
<Canvas Width="50" Height="50"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
Fill="#FFFFFFFF"
RenderTransformOrigin="0.5,0.83333">
<Path.RenderTransform >
<RotateTransform x:Name="_rot1" Angle="0"/>
</Path.RenderTransform>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot1"
Storyboard.TargetProperty="Angle"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="360"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<PowerEase Power="1.3" EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
<Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
Fill="#DDFFFFFF"
RenderTransformOrigin="0.5,0.83333">
<Path.RenderTransform>
<RotateTransform x:Name="_rot2" Angle="13"/>
</Path.RenderTransform>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot2"
Storyboard.TargetProperty="Angle"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="13"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="13"/>
<EasingDoubleKeyFrame KeyTime="0:0:2.2" Value="-347">
<EasingDoubleKeyFrame.EasingFunction>
<PowerEase Power="1.3" EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="-347"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
<Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
Fill="#BBFFFFFF"
RenderTransformOrigin="0.5,0.83333">
<Path.RenderTransform>
<RotateTransform x:Name="_rot3" Angle="26"/>
</Path.RenderTransform>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot3"
Storyboard.TargetProperty="Angle"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="26"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="26"/>
<EasingDoubleKeyFrame KeyTime="0:0:2.4" Value="-334">
<EasingDoubleKeyFrame.EasingFunction>
<PowerEase Power="1.3" EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="-334"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
<Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
Fill="#99FFFFFF"
RenderTransformOrigin="0.5,0.83333">
<Path.RenderTransform>
<RotateTransform x:Name="_rot4" Angle="39"/>
</Path.RenderTransform>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot4"
Storyboard.TargetProperty="Angle"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="39"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="39"/>
<EasingDoubleKeyFrame KeyTime="0:0:2.6" Value="-321">
<EasingDoubleKeyFrame.EasingFunction>
<PowerEase Power="1.3" EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="-321"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
<Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
Fill="#77FFFFFF"
RenderTransformOrigin="0.5,0.83333">
<Path.RenderTransform>
<RotateTransform x:Name="_rot5" Angle="52"/>
</Path.RenderTransform>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot5"
Storyboard.TargetProperty="Angle"
RepeatBehavior="Forever">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="52"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="52"/>
<EasingDoubleKeyFrame KeyTime="0:0:2.8" Value="-308">
<EasingDoubleKeyFrame.EasingFunction>
<PowerEase Power="1.3" EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="-308"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
</Canvas>
</Viewbox>
It's essentially the same Path object, a filled circle, used 5 times, at 5 different rotation angles and 5 different opacity values for the fill.
Doubtless, there is a more efficient way to do this, but this method shows the animation and timings, as well as the easing to give it more natural, less abrupt feel, when the circles spin around and stop.
Use ProgressRing from MahApps.Metro:
The ProgressRing control is styled after a similar control in Windows 8 to indicate activity rather than a percentage of progress completed.
Example:
<Controls:ProgressRing IsActive="True" />
To change the size of the rings, you need to set Width and Height. Also, you can set a different color for each ring and set the size less than the established. To do this and get this Control without install full MahApps.Metro pack, look at my previous answer:
Make the ProgressRing in MahApps.Metro Smaller

Categories