Setting an Initial VisualState in WPF - wpf

When using the VisualStateManager in WPF there can be a requirement to transition to a VisualState on control initialization. As far as I can tell there is no way to declare an initial state in Xaml, leaving you with the limited option of transitioning to the required state in your code behind after initialization.
Using code behind is not always desirable, and if you are using a Binding to control your VisualStates then not always possible.
So the question is: how do you set an initial VisualState in WPF without setting it in the code behind?

Too long for a comment
Binding "should" make no difference. If it works fine from code-behind it's bound to work from xaml unless there is something really weird in the Bindings.
All of blend's actions can be considered as a xaml helper tool. End result is you get some xaml that blend creates for you. If you do not want to use blend. Just add the xaml yourself in VS.
For this very thing the GoToStateAction can be coded such as
<Window ...
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...>
...
<Button x:Name="button"
Style="{DynamicResource ButtonStyle1}">
<i:Interaction.Triggers>
<i:EventTrigger>
<ei:GoToStateAction StateName="YourState"
TargetObject="{Binding ElementName=button}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
You'll need the corresponding references in your project as well.
On a side-note do try blend. It has it's advantages in specific places. You prolly would not replace typing xaml directly, but it serves as a good helper tool. Ignoring it completely unless forced to is pointless IMO.

You can directly bind any control with visual state at the time of initialisaton itself in xaml.
You need to create one dependency property to change the state.
hope below code can help you .
<Grid model:StateManager.VisualStateProperty="{Binding VisibilityState}" >
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="97" />
<RowDefinition Height="65" />
<RowDefinition Height="297" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisibleStateGroup">
<VisualState x:Name="VisibleState">
<Storyboard Duration="0:0:0">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="myGrid" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CollapsedState">
<Storyboard Duration="0:0:0">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="myGrid" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Name="myGrid" Grid.Row="0" Grid.ColumnSpan="2" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="383*" />
<ColumnDefinition Width="383*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" Margin="0,0,15,0" HorizontalAlignment="Right" VerticalAlignment="Center">
<Label Content="MyName"></Label>
</StackPanel>
</Grid>
Dependency property code for visual state change
public class StateManager : DependencyObject
{
public static string GetVisualStateProperty(DependencyObject obj)
{
return (string)obj.GetValue(VisualStatePropertyProperty);
}
public static void SetVisualStateProperty(DependencyObject obj, string value)
{
obj.SetValue(VisualStatePropertyProperty, value);
}
public static readonly DependencyProperty VisualStatePropertyProperty =
DependencyProperty.RegisterAttached(
"VisualStateProperty",
typeof(string),
typeof(StateManager),
new PropertyMetadata((s, e) =>
{
var propertyName = (string)e.NewValue;
var ctrl = s as Grid;
if (ctrl == null)
throw new InvalidOperationException("This attached property only supports types derived from FrameworkElement.");
var transitionWorked = System.Windows.VisualStateManager.GoToElementState(ctrl, (string)e.NewValue, true);
//MessageBox.Show(transitionWorked.ToString());
}));
}

Related

Slow storyboard animation inside LongListSelector

I have a LongListSelector which is populated with some items. Each item has a submenu which can be visible or collapsed using a sliding animation. The problem is that the animation is extremely slow depending on which item you tap in the list. At the start and the end it's slow, in the middle it's smooth. I suspect that each animation frame invalidates the longlistselector which means the entire visual tree must update it's layout.
I use a datatrigger to start the animation. Because of that I can see that the triggers on lots of other items also get fired which indicates to me they are being redrawn. It also shows that when you tap in the middle of list a lot less other items get triggered as well. weird...
I hosted the testproject on github:
https://github.com/jessetabak/wpanimationproblem
The LongListSelector:
<phone:LongListSelector x:Name="LongList" Margin="0" Padding="0" ItemsSource="{Binding Items}"
HorizontalAlignment="Stretch" Background="Transparent">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<wegGooiApp2:ItemView />
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
The ItemView:
<UserControl.Resources>
<wegGooiApp2:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<Storyboard x:Key="ShowMenu">
<DoubleAnimation Storyboard.TargetProperty="(Grid.Height)"
Storyboard.TargetName="Submenu"
From="0" To="70" Duration="0:0:0.25" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Submenu"
Storyboard.TargetProperty="(Grid.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="HideMenu">
<DoubleAnimation Storyboard.TargetProperty="(Grid.Height)"
Storyboard.TargetName="Submenu"
From="70" To="0" Duration="0:0:0.25" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Submenu"
Storyboard.TargetProperty="(Grid.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0:0:0.25">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- TEST ITEM -->
<Border Height="70" BorderBrush="Red" Background="Transparent" BorderThickness="1" HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="Test Item" HorizontalAlignment="Stretch" FontSize="42" />
<Button Content="v" Grid.Column="1" Tap="Button_Tap" Tag="{Binding}">
</Button>
</Grid>
</Border>
<!-- SUBMENU -->
<Border x:Name="Submenu" Grid.Row="1" BorderBrush="Green" BorderThickness="1"
Visibility="{Binding SubMenuIsVisible, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneTime}"
Background="Green" Height="0" Margin="0 0 0 0">
<i:Interaction.Triggers>
<ec:DataTrigger Binding="{Binding SubMenuIsVisible}" Value="True">
<ec:CallMethodAction MethodName="MenuEnabled"
TargetObject="{Binding ElementName=ThisUserControl, Mode=OneWay}" />
</ec:DataTrigger>
<ec:DataTrigger Binding="{Binding SubMenuIsVisible}" Value="False">
<ec:CallMethodAction MethodName="MenuDisabled"
TargetObject="{Binding ElementName=ThisUserControl, Mode=OneWay}" />
</ec:DataTrigger>
</i:Interaction.Triggers>
<TextBlock Text="SubMenu" FontSize="42" />
</Border>
</Grid>
</UserControl>
The ItemView codebehind:
public partial class ItemView : UserControl
{
private Storyboard _showStoryboard;
private Storyboard _hideStoryboard;
public ItemView()
{
InitializeComponent();
_showStoryboard = (Storyboard) this.Resources["ShowMenu"];
_hideStoryboard = (Storyboard) this.Resources["HideMenu"];
Debug.WriteLine("ItemView CONSTRUCTED");
}
private void Button_Tap(object sender, GestureEventArgs e)
{
var button = (Button)sender;
var viewModelItem = (ItemViewModel)button.Tag;
viewModelItem.SubMenuIsVisible = !viewModelItem.SubMenuIsVisible;
}
public void MenuEnabled()
{
Debug.WriteLine("MENU ENABLED!");
if (Submenu.Visibility == Visibility.Collapsed)
{
_showStoryboard.Begin();
}
}
public void MenuDisabled()
{
Debug.WriteLine("MENU DISABLED!");
if (Submenu.Visibility == Visibility.Visible)
{
_hideStoryboard.Begin();
}
}
private void ThisUserControl_LayoutUpdated(object sender, EventArgs e)
{
//Debug.WriteLine("ITEMVIEW LAYOUT UPDATED!");
}
}
And what it looks like:
/edit 1
I tried turning it into an independent animation using a ScaleTransform, but this won't animate the surrounding ui elements. To fix this you can use a LayoutTransform instead of the standard RenderTransform. After some tweaking this worked quite nice, but the layouttranform turned it back in a slow depenpendent animation...
You are correct that changing the UserControl height causes a large portion of the visual tree to be invalidated, but this is required, and by design. The issue is that you are modifying a controls height in a storyboard to begin with, which is not an independent animation and can't run on the compositor.
Have a read of http://msdn.microsoft.com/en-us/library/windows/apps/jj819807.aspx#dependent although this is for Windows store apps (and there is EnableDependentAnimations flag in SL), the ideas remain the same. You need to figure out a way to expand items using independent animations, probably by using a ScaleTransform.

Targeting nested content in Xaml displayed using ContentPresenter

Consider the following usercontrol:
This is a custom usercontrol that I have written that has two nested elements.
FilterContent displays a special type of markup that filters content on the right hand side of the screen
MainContent hosts the filtered content.
The only real purpose of the control is to provide consistent UI and animation across the application, as this filter/content pattern is used frequently.
The (simplified) Xaml of the usercontrol look as follows:
<UserControl>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="7*"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" Content="{Binding ElementName=filterControl, Path=FilterControl}" DataContext="{Binding}" />
<ContentPresenter Grid.Column="1" Content="{Binding ElementName=filterControl, Path=MainControl}" DataContext="{Binding}" />
</Grid>
The codebehind is :
public sealed partial class FilterPaneControl : UserControl
{
public static DependencyProperty FilterControlProperty = DependencyProperty.Register("FilterControl", typeof(object), typeof(FilterPaneControl), new PropertyMetadata(default(object), PropertyChangedCallback));
public static DependencyProperty MainControlProperty = DependencyProperty.Register("MainControl", typeof (object), typeof (FilterPaneControl), new PropertyMetadata(default(object)));
public FilterPaneControl()
{
this.InitializeComponent();
}
public object FilterControl
{
get { return (object)GetValue(FilterControlProperty); }
set { SetValue(FilterControlProperty, value); }
}
public object MainControl
{
get { return (object) GetValue(MainControlProperty); }
set { SetValue(MainControlProperty, value); }
}
}
The usage of the control in an implementing page is :
<Generic:FilterPaneControl>
<Generic:FilterPaneControl.FilterControl>
<Grid>
<TextBlock Text="Filter Content here"/>
</Grid>
</Generic:FilterPaneControl.FilterControl>
<Generic:FilterPaneControl.MainControl>
<Grid>
<TextBlock Text="Main Content here"/>
</Grid>
</Generic:FilterPaneControl.MainControl>
</Generic:FilterPaneControl>
That works fine!
The Problem
The problem is when I then want to reference some of the content within the control from the implementing page. A good case for this is visual states for handling snap/portrait (WinRT implementation)
<Generic:FilterPaneControl>
<Generic:FilterPaneControl.FilterControl>
<Grid>
<TextBlock x:Name="filterContent1" Text="Filter Content here"/>
</Grid>
</Generic:FilterPaneControl.FilterControl>
<Generic:FilterPaneControl.MainControl>
<Grid>
<TextBlock Text="Main Content here"/>
</Grid>
</Generic:FilterPaneControl.MainControl>
</Generic:FilterPaneControl>
<VisualStateManager.VisualStateGroups>
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="200"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateManager.VisualStateGroups>
This leads to a run-time exception, as the visualstatemanager cannot find the referenced element 'filterContent1' even though it exists in the Visual Tree.
Additionally, if I try and reference the element directly in an Page.Loaded event handler, filterContent1 is null.
It is as if the nested Xaml doesn't render until later - which is throwing the visualstatemanager too.
Any suggestions?
First, VisualStateManager should be placed in a single panel with the element for which it is done, otherwise it would be an exception. For your case it turns out like this:
<Generic:FilterPaneControl>
<Generic:FilterPaneControl.FilterControl>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="200"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="filterContent1" Text="Filter Content here"/>
</Grid>
</Generic:FilterPaneControl.FilterControl>
...
Second, usually VisualStateManager placed in either a Template / Style, or UserControl. The transition to the states is carried out either in code or through XAML (with special techniques). Sample of set state behind code:
VisualStateManager.GoToState(NameOfControl, "State1", true);
Third, in a manner:
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="200"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
Width not sets, in my case is an exception. We need to use animation something like this:
<Storyboard Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DoubleAnimation To="200" Duration="0:0:1.0"/>
</Storyboard>
As proof of his words, I give an example:
MainWindow
<Window x:Class="VSMinUserControlHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VSMinUserControlHelp"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<local:UserControl1 x:Name="Control1" Height="118" VerticalAlignment="Top" Margin="50,12,101,0" />
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Name="State1Button" Width="75" Click="State1Button_Click">State1</Button>
</StackPanel>
</Grid>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void State1Button_Click(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToState(Control1, "State1", true);
}
}
UserControl
<UserControl x:Class="VSMinUserControlHelp.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Common1">
<VisualState x:Name="State1">
<Storyboard Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DoubleAnimation To="200" Duration="0:0:1.0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="filterContent1" Background="Aqua" Width="100" HorizontalAlignment="Left" Text="Filter Content here"/>
</Grid>
</UserControl>
Note: Example run on VS 2010, Windows XP, not tested under WinRT.

Silverlight: How do you implement validation in custom controls?

How do you implement validation in custom controls? I am looking to replicate the standard validation logic you would see with a TextBox data-bound to a model or view-model that exposes IDataErrorInfo or INotifyDataErrorInfo.
To implement validation you should add the "ValidationStates" group to the VisualStateManager of the control.
I will illustrate the simple custom control TestControl with the TestProperty property.
Style in the Generic.xaml, depending on the state displays the blue text or the red border with the first error message:
<Style TargetType="local:TestControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TestControl">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid" />
<VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvalidBorder" Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvalidBorder" Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock Text="{TemplateBinding TestProperty}" Foreground="Blue" />
<Border x:Name="InvalidBorder" BorderBrush="Red" BorderThickness="2" Visibility="Collapsed">
<TextBlock Text="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource TemplatedParent}}" Foreground="Red" FontWeight="Bold" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
There are 3 states:
Valid - No validation errors.
InvalidFocused - Applied when you set the focus to the control in the invalid state. Default controls display the red popup as well as the red border in this state, but in my particular example I don't display it for simplicity. Users can invoke this state by using the Tab keyboard button or by clicking a focusable inner control like TextBox.
InvalidUnfocused - Applied when the control in the invalid state but isn't focused.
Here is the code of the control, it contains only one property:
public class TestControl : Control
{
public TestControl()
{
this.DefaultStyleKey = typeof(TestControl);
}
public string TestProperty
{
get { return (string)GetValue(TestPropertyProperty); }
set { SetValue(TestPropertyProperty, value); }
}
public static readonly DependencyProperty TestPropertyProperty =
DependencyProperty.Register("TestProperty", typeof(string), typeof(TestControl), new PropertyMetadata(null));
}
After that if you use the IDataErrorInfo, the correct xaml is:
<local:TestControl TestProperty="{Binding SomeModelProperty, ValidatesOnDataErrors=True}" />
For the INotifyDataErrorInfo, the correct xaml is even simplier:
<local:TestControl TestProperty="{Binding SomeModelProperty}" />

Silverlight DataGrid: Hiding columns using VisualStateManager

Is it possible to hide a column of a datagrid, without using codebehind?
E.g. by using the VisualStateManager?
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
x:Class="Buttons.MainPage"
Width="640" Height="480">
<StackPanel x:Name="LayoutRoot" Width="624" HorizontalAlignment="Right" Margin="0,0,8,0" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="EditStates">
<VisualState x:Name="ReadOnly" />
<VisualState x:Name="Edit">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ShownInEditMode" Storyboard.TargetProperty="(UIElement.Visibility)" BeginTime="00:00:00" Duration="00:00:00.0010000">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<data:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding BBRNumbers}">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="AlwaysShown" Width="80" Binding="{Binding Municipality}" />
<data:DataGridTextColumn Header="ShownInEditMode" Width="73" Binding="{Binding Estate}" Visibility="Collapsed" />
</data:DataGrid.Columns>
</data:DataGrid>
</StackPanel>
Calling the following should then hide the column, but this doesnt work.
VisualStateManager.GoToState(this, "Edit", false);
Any ideas?
I haven't been able to come up with a simple solution to this as yet. However its only fair that I at least tell you why this isn't working. In order to animate a property the property needs to be DependencyProperty. The Visibility property of the DataGridColumn is not a DependencyProperty, hence it does not animate.
You can try setting column width = 0
You can either subclass DataGrid or create an attached property to toggle Visibility. However, unlike Opacity, you can't really 'animate' Visibility unless you enable FluidLayout in the VisualStateManager.
For more info regarding the fluid UI, please take a look at http://www.microsoft.com/design/toolbox/tutorials/fluidui/

WPF - Animating gridlength in XAML

I was just wondering if it's possible to animate the height of a grid using purely XAML? I looked at this tutorial:
http://windowsclient.net/learn/video.aspx?v=70654
But it seems as though one need to write custom functions for this to work.
Can it be done just by XAML purely?
its not possible out of the box because there's no such class as a GridLengthAnimation (compare with DoubleAnimation). If such a class existed (from you, microsoft or third party) then there would be a pure XAML solution.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0" x:Name="Row" />
</Grid.RowDefinitions>
</Grid>
...
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Row"
Storyboard.TargetProperty="Height" Duration="0:0:0.2">
<DiscreteObjectKeyFrame Value="{x:Static GridLength.Auto}" KeyTime="0:0:0.2" />
</ObjectAnimationUsingKeyFrames>

Resources