I've developed a WPF application in Expression Blend, a simple button attach with a storyboard with bounce effect.
So far so good, now I want my button to bounce when my mouse enters on it, it does. But it keeps doing that. I move mouse once and after bouncing again falls into the mouse region (I am not moving the mouse, mouse cursor is still) and starts bouncing again.
This is the whole code that I am using
<Window.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<BounceEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-29">
<EasingDoubleKeyFrame.EasingFunction>
<BounceEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Height="51" Margin="76,100,0,0" VerticalAlignment="Top" Width="130" RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<ei:ControlStoryboardAction Storyboard="{StaticResource Storyboard1}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
Just copy paste it in your xaml window and you'll good to go.
Keep the mouse on the top corner of mouse. You'll see the problem.
Thanks
The thing that pops out is that you're moving the button by 29px down when it's 51px tall. Chances are the button moves away from the mouse and starts moving back to reverse the animation.
You can work around this by reworking the button and animation:
- place the button in a container (grid, stackpanel - anything that works for you)
- make the container's background "Transparent" (which is NOT the same as "null")
- make the button align to the bottom of that container
- make the animation trigger on the container and change the container's height
The result is that when the button moves away the mouse is still over its container so the animation doesn't stop and reverse.
- control animation behavior with AutoReverse and RepeatBehavior
--
This is obviously not the whole code you're using (where's the "i" namespace declaration?) so I can't see your problem on my end.
Let's take this button animation as example:
<Grid>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="Test ">
<Button.RenderTransform>
<ScaleTransform ScaleX="1.0" ScaleY="1.0" />
</Button.RenderTransform>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.ScaleX" To="2.0" />
<DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.ScaleY" To="2.0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.ScaleX" To="1.0" />
<DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.ScaleY" To="1.0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
So when your mouse enters the button area, it grows, and when the mouse leaves, it shrinks back.
By default, a StoryBoard's:
AutoReverse = False, if true the animation reverts as soon as it's over.
FillBehavior = HoldEnd, which makes the button's appearence stay as how it looks once the animation is over (i.e: the button will remain 2x bigger as long as you keep your mouse above the button). If set to Stop, it will revert back to its original state as soon as the animation finishes (without animation, which is what is different from AutoReverse).
RepeatBehavior = 1x, you can set this to a TimeSpan, nx where n is the number of times you want the animation repeated, or Forever and it will loop forever.
You should check that these settings haven't been tampered with.
And last but not least, make sure the logic tied to your animation makes sense and doesn't induce a loop (which would, in turn, make the animation loop). For example if you animate based on the mouse being over an element, and the animation moves the element, then your mouse isn't over the element anymore, and thus the animation reverts, bringing back the button under the mouse, etc, forever.
You could try to put the mouse inside a canvas with a transparent (not null) background and animate the button when the mouse gets over the canvas. The button would leave its position but the canvas wouldn't. You could use that solution inside a template control, for example.
Related
In my WPF appliction, I have a partially visible grid at the bottom of the visible space. When you mouseover it, it slides up and everything in the grid is visible. When the mouse leaves the grid, it slides back down. There are Combo and TextBoxes in the grid that will contain info and be able to be updated by the user.
How do I make it so that if I click anywhere in the grid, the MouseLeave animation no longer goes off (the grid stays up even you if your mouse leaves)?
I have implemented my animation 2 different ways in an attempt to get it to behave the way I want, but no luck so far.
Implementation 1:
`<Grid x:Name="PopupAnimation" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="30">
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard Name="MouseOn">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height" From="30" To="90" Duration="0:0:.15"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard Name="MouseOff">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height" From="90" To="30" Duration="0:0:0.15"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeftButtonDown">
<StopStoryboard BeginStoryboardName="MouseOff" />
</EventTrigger>
</Grid.Triggers>
`
Implementation 2:
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Name="MouseOn">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height" From="30" To="90" Duration="0:0:.15"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Name="MouseOff">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height" From="90" To="30" Duration="0:0:0.15"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
Are either of these heading down the right road? How do I disable (and enable) an animation?
How do I make it so that if I click anywhere in the grid, the MouseLeave animation no longer goes off (the grid stays up even you if your mouse leaves)?
Don't execute the up and down movement by style, instead subscribe to the all events in question, and with the events of mouse enter and mouse leave run the storyboards in code-behind.
Then in the final event, in code behind grid click event, set a Boolean flag which will be read by the mouse leave event and allow it to not execute the storyboard.
Here is code I have to move a window in/out in codebehind to give you an idea about the storyboards:
if (moveRight)
{
(Resources["MoveToOpen"] as Storyboard)?.Begin(this, false);
(Resources["FlipArrowClose"] as Storyboard)?.Begin(this, false);
}
else
{
if (closeWindow == false)
{
(Resources["MoveToClose"] as Storyboard)?.Begin(this, false);
(Resources["FlipArrowOpen"] as Storyboard)?.Begin(this, false);
}
}
I want to animate my window coming in from the right edge of the screen.
This is my xaml
<Window x:Class="SidebarTest.DockWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DockWindow" Width="275"
ShowInTaskbar="False"
WindowStyle="None" ResizeMode="NoResize"
AllowsTransparency="True" Background="Transparent" >
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:1.5" Storyboard.TargetProperty="Width" From="0" To="275" AccelerationRatio=".1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid Background="#2F2F2F">
</Grid>
But it animates the width from left to right instead of right to left.
Like this:
How can I change this so it comes in from the edge?
In your codebehind,
public DockWindow()
{
InitializeComponent();
this.Left = this.Width + SystemParameters.FullPrimaryScreenWidth;
}
Change your trigger to
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Duration="0:0:1.5" Storyboard.TargetProperty="Left" To="10" AccelerationRatio=".1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
Instead of trying to scale the width I might suggest leaving the width fixed and applying a TranslateTransform to the Window itself and in effect literally sliding it in from offscreen. A quick and dirty example provided below, you'll likely want to play with the value of the X coordinate and the KeyTime to get the effect just right but hopefully this is helpful to you. Cheers
<Window.RenderTransform>
<TranslateTransform x:Name="SlideTheThingy" X="1000" />
</Window.RenderTransform>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SlideTheThingy"
Storyboard.TargetProperty="X">
<SplineDoubleKeyFrame KeyTime="0:0:1.25" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
Windows are positioned by their Top-Left corner. So, when you animate your width and the position stays constant, the window will naturally grow to the right
In order to have the effect you're looking for, you also need to animate the position of the Window using the .Left property. If you want to snap the window to the right side of the screen and slide in from there, you need to start animating with a value of Left that matches your screen's width (and a zero-pixel width), and then animate to screenWidth - finalWidthOfWindow.
I actually figured it out, I needed to set the horizontal Alignment to right of the component I wanted to animate the size of. And it worked like a charm!
I have a Stackpanel One, which has some content, an Image, and a defualt hidden SubStackpanel. When clickin the Image, the image should rotate 90 degrees, and slide down the SubStackpanel.
When clicking the Image again, the Image should rotate back to its original position, and the SubStackpanel should slide up to the default hidden position.
I almost got this working, the problem is that I dont know how to use the same Trigger event, on two different Storyboard animations. So right now only the first animation on the button and the SubStackpanel occurs, everytime the Image is clicked.
I´ve tried the AutoReverse property, but it fires immediately after the animation is done. This should of course only be happening when the user clicks the Image the second time.
I would like to achieve this, only using markup.
This is my currently code:
<Grid>
<StackPanel Grid.Row="0" Orientation="Vertical" Background="Beige" >
<StackPanel.Triggers>
<EventTrigger SourceName="ImageShowPanelTwo" RoutedEvent="Image.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="SubPanel" Storyboard.TargetProperty="(StackPanel.Height)" From="0" To="66" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger SourceName="ImageShowPanelTwo" RoutedEvent="Image.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="SubPanel" Storyboard.TargetProperty="(StackPanel.Height)" From="66" To="0" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
<TextBlock>Panel One</TextBlock>
<Image Name="ImageShowPanelTwo" Width="26" Height="26" Source="ImageRotate.png" RenderTransformOrigin=".5,.5" >
<Image.RenderTransform>
<RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Image.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform"
Storyboard.TargetProperty="Angle"
By="0"
To="90"
Duration="0:0:0.5"
AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Image.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform"
Storyboard.TargetProperty="Angle"
By="90"
To="0"
Duration="0:0:0.5"
AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
<StackPanel Name="SubPanel" Background="LightGreen" Height="66">
<TextBlock>SubPanel</TextBlock>
<TextBlock>SubPanel</TextBlock>
</StackPanel>
</StackPanel>
</Grid>
Hope you can help :)
Blend for Visual Studio can be used to do it in a better, simpler way, without dealing with a lot of code.
Here is the list of steps of doing it.
Step 1: Open the project in Blend for Visual Studio and in Visual Studio simultaneously.
Step 2: In Blend, create a new storyboard around all the elements that you wish to animate with it.
Let's call it "Storyboard1".
Step 3: Now, open the storyboard that we just created and click on the small arrow just beside the "+" and click on "Duplicate" in the drop down menu. Then, a new storyboard called "Storyboard1_Copy" will be created.
Step 4: Rename this new storyboard to something that you like, say, "Storyboard1_Rev".
Step 5: You must have guessed it by now. Select the duplicated storyboard and from the drop down menu, click on "Reverse".
Step 6: Now you have two storyboards ready: one for animating some elements as you like and the other for reversing that sequence of animation. Just like you call a storyboard from the C# code, you can call the reversing storyboard from the same, subject to some conditions which check if the elements are already animated or not. For this, I use a bool variable, whose value is changed each time some animation occurs on a set of elements(that is, false if the elements are not already animated and true if they are).
Illustration with an example:
I'll create an application with a simple layout. It has a button, an image and a rectangular area on the screen.
The idea is that, whenever you click on the button once, the image should be maximized and should be minimized back to original size when the button is clicked twice and so on. That is, the reverse animation should happen every other time the button is clicked. Here are some screenshots showing how it happens:
You can see that the current state of the image is shown in the button. It shows "Zoom In" when the image is in its initial small size and "Zoom Out" when it is maximized.
And finally, here is the C# code for handling the clicks of the button:
bool flag = false;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (!flag)
{
Button.Content = "Zoom Out";
Storyboard1.Begin();
flag = true;
}
else
{
Button.Content = "Zoom In";
Storyboard1_Rev.Begin();
flag = false;
}
}
All you have to do is have a status flag that shows the current status of the element(s) that you wish to animate and animate it(them) in forward or reverse timeline as per the value of the flag.
Instead of trying to set the Animation using that event, use a bool property to bind to instead:
<Image Name="ImageShowPanelTwo" Width="26" Height="26" Source="ImageRotate.png"
RenderTransformOrigin=".5,.5" >
<Image.RenderTransform>
<RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
</Image.RenderTransform>
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRotated}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="AnimatedRotateTransform"
Storyboard.TargetProperty="Angle"
By="0"
To="90"
Duration="0:0:0.5"
AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding IsRotated}" Value="False">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="AnimatedRotateTransform"
Storyboard.TargetProperty="Angle"
By="90"
To="0"
Duration="0:0:0.5"
AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
I trust that you can define your own bool property and invert it upon each MouseDown event occurrence to complete this functionality. As it is set to true the first Animation will start and as it is set to false the second will start.
This is how I solved my problem:
Created four storyboards for the Stackpanel and the arrow:
<Storyboard x:Key="RotateIconUp">
<DoubleAnimation Storyboard.TargetName="IconExpand" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="0" To="90" Duration="0:0:0.4" />
</Storyboard>
<Storyboard x:Key="RotateIconDown">
<DoubleAnimation Storyboard.TargetName="IconExpand" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="90" To="0" Duration="0:0:0.4" />
</Storyboard>
<Storyboard x:Key="SlideGridDown">
<DoubleAnimation Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(Grid.Height)" From="0" To="180" Duration="0:0:0.4" />
</Storyboard>
<Storyboard x:Key="SlideGridUp">
<DoubleAnimation Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(Grid.Height)" From="180" To="0" Duration="0:0:0.4" />
</Storyboard>
Then I trigger the storyboards from codebehind when the arrow is clicked:
private void ExpandDetails() {
try {
if (!pm_IsExanded) {
Storyboard Storyboard = (Storyboard)FindResource("RotateIconUp");
Storyboard.Begin(this);
Storyboard = (Storyboard)FindResource("SlideGridDown");
Storyboard.Begin(this);
pm_IsExanded = true;
BorderMain.BorderBrush = pm_BrushConverter.ConvertFromString("#000000") as Brush;
} else {
Storyboard Storyboard = (Storyboard)FindResource("RotateIconDown");
Storyboard.Begin(this);
Storyboard = (Storyboard)FindResource("SlideGridUp");
Storyboard.Begin(this);
pm_IsExanded = false;
BorderMain.BorderBrush = pm_BrushConverter.ConvertFromString("#d0d0d0") as Brush;
}
} catch (Exception ee) {
GlobalResource.WriteToLog("Error in ExpandDetails", ee);
}
}
I've got a canvas control that grows in height when you move the mouse over it and shrinks back on mouse leave.
<Canvas x:Name="infoBar" Width="720" Height="39" Background="Red">
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="infoBar"
Storyboard.TargetProperty="Height"
From="39" To="255" Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Canvas.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="infoBar"
Storyboard.TargetProperty="Height"
From="255" To="39" Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<StackPanel>
<TextBlock/>
<TextBlock/>
</StackPanel>
</Canvas>
This works fine. However if two quick consecutive events take place (mouseleave before mouse enter animation finishes) it goes nuts.
Is there anyway i can tell it to cancel out any other events that happen before an animation finishes?
Using your event triggers you can perform pause, stop, resume, etc. commands on named storyboards.
This article should answer your questions.
I have a WPF Window that contains a ContentPresenter that has Height and Width set to 0 by default.
When a user clicks a button, I run an animation to transform the ContentPresenter's Height and Width properties to 896,1024 (actually it does 3 rotations whilst its growing, too) and this is all good...
The DataContext for the User control implements IDataErrorInfo and if the user does not click the 'I have read and understand these Health & Safety instructions" checkbox, then a red border is shown around the checkbox...
My problem is that if the user clicks 'Cancel', and I run the animation that shrinks the Height & Width back down to 0,0, then the UserControl shrinks as required, but the red border does not completely disappear - it leaves a single red pixel in the middle of my Window
Anybody any ideas what I'm doing wrong? The 'red-border', I'm assuming is just an Adorner being rendered by WPF for me, so I'm not sure how to change this behaviour...
All help much appreciated!
Update - I tried Abe's excellent suggestion, but unfortunately it didn't work, but it did get me trying other stuff... So now I have (temporarily) commented out the 'shrinking' animations, and simply set the visibility to Collapsed at KeyTime="0:0:0.9"... when I press cancel, just less than a second later, the UserControl disappears but the red adorner stubbornly remains :(
As an extra bit of info (not sure if relevant?) the UserControl being shown in the ContentPresenter also contains a ContentPresenter to render a UserControl, and its the inner content that contains the validation adorner...
code sample:
<Button
Name="signInButton"
Grid.Row="0" Grid.Column="0"
Margin="30"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Style="{StaticResource LargeButtonStyle}"
Content="Sign In"
Command="{Binding SignInCommand}">
<Button.Triggers>
<EventTrigger
RoutedEvent="Button.Click">
<BeginStoryboard
Storyboard="{DynamicResource openViewAnimation}" />
</EventTrigger>
</Button.Triggers>
</Button>
<ContentPresenter
Name="mainView"
Grid.RowSpan="2" Grid.ColumnSpan="2"
HorizontalAlignment="Center" VerticalAlignment="Center"
Opacity="0.9"
Content="{Binding CurrentContent}">
<ContentPresenter.RenderTransform>
<RotateTransform
Angle="0" />
</ContentPresenter.RenderTransform>
</ContentPresenter>
<Storyboard x:Key="closeViewAnimation">
<DoubleAnimation
Storyboard.TargetName="mainView" Storyboard.TargetProperty="Height"
From="896" To="0" Duration="0:0:0.9"
AutoReverse="False" RepeatBehavior="1x" />
<DoubleAnimation
Storyboard.TargetName="mainView" Storyboard.TargetProperty="Width"
From="1024" To="0" Duration="0:0:0.9"
AutoReverse="False" RepeatBehavior="1x" />
</Storyboard>
Thanks, Ian
If you add an ObjectAnimationUsingKeyFrames that sets the Visibility of the element to Collapsed at the time that the other animations complete, the adorner will go away also.
<Storyboard x:Key="closeViewAnimation">
<DoubleAnimation
Storyboard.TargetName="mainView" Storyboard.TargetProperty="Height"
From="896" To="0" Duration="0:0:0.9"
AutoReverse="False" RepeatBehavior="1x" />
<DoubleAnimation
Storyboard.TargetName="mainView" Storyboard.TargetProperty="Width"
From="1024" To="0" Duration="0:0:0.9"
AutoReverse="False" RepeatBehavior="1x" />
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="mainView"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}"
KeyTime="0:0:0.9" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
Obviously, you would need to do the reverse operation at KeyTime 0 for the openViewAnimation.