I want to fade a window in/out in my application.
Fading in occurs on Window.Loaded
and I wanted to fade out on close (Window.Closed
or Window.Closing
). Fading in works perfectly, but Window.Closing
is not allowed value for RoutedEvent
property.
What RoutedEvent
should I be using for Close?
<Window.Triggers> <EventTrigger RoutedEvent="Window.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:2" FillBehavior="HoldEnd" /> </Storyboard> </BeginStoryboard> </EventTrigger> <EventTrigger RoutedEvent="Window.Closing"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2" FillBehavior="HoldEnd" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Window.Triggers>
I get a error on , Value 'Window.Closing' cannot be assigned to property 'RoutedEvent'. Invalid event name.
Closing is not a routed event, so you can't use it in an EventTrigger. Perhaps you could start the storyboard in the handler of the ClosingEvent in the code-behind and cancel the event... something like that :
private bool closeStoryBoardCompleted = false; private void Window_Closing(object sender, CancelEventArgs e) { if (!closeStoryBoardCompleted) { closeStoryBoard.Begin(); e.Cancel = true; } } private void closeStoryBoard_Completed(object sender, EventArgs e) { closeStoryBoardCompleted = true; this.Close(); }
I thought I'd add another solution of doing this, using behaviors from the Expression SDK and combining it with the solution from @Thomas. Using that, we can define a "CloseBehavior" that handles the code behind of starting a storyboard and closing the window when it's done.
using System.ComponentModel; using System.Windows; using System.Windows.Interactivity; using System.Windows.Media.Animation; namespace Presentation.Behaviours { public class CloseBehavior : Behavior<Window> { public static readonly DependencyProperty StoryboardProperty = DependencyProperty.Register("Storyboard", typeof(Storyboard), typeof(CloseBehavior), new PropertyMetadata(default(Storyboard))); public Storyboard Storyboard { get { return (Storyboard)GetValue(StoryboardProperty); } set { SetValue(StoryboardProperty, value); } } protected override void OnAttached() { base.OnAttached(); AssociatedObject.Closing += onWindowClosing; } private void onWindowClosing(object sender, CancelEventArgs e) { if (Storyboard == null) { return; } e.Cancel = true; AssociatedObject.Closing -= onWindowClosing; Storyboard.Completed += (o, a) => AssociatedObject.Close(); Storyboard.Begin(AssociatedObject); } } }
The behavior defines a storyboard as a dependency property, so we can set it in xaml and when the AssociatedObject
(the window where we define the behavior) is closing, this storyboard is started using Storyboard.Begin()
. Now, in xaml we simply add the behavior to the window using the following xaml
<Window x:Class="Presentation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:behave="clr-namespace:Presentation.Behaviours" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" x:Name="window"> <Window.Resources> <Storyboard x:Key="ExitAnimation"> <DoubleAnimation Storyboard.Target="{Binding ElementName='window'}" Storyboard.TargetProperty="(Window.Opacity)" Duration="0:0:1" From="1" To="0"/> </Storyboard> </Window.Resources> <i:Interaction.Behaviors> <behave:CloseBehavior Storyboard="{StaticResource ExitAnimation}"/> </i:Interaction.Behaviors> <Grid> </Grid> </Window>
Note the xml namespace i
from the System.Windows.Interactivity dll, and also that the window is referenced, so it has to have a x:Name
assigned. Now we simply add the behavior to every window on which we wish to execute a storyboard before closing the application, instead of copying the logic to every code-behind in each window.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With