Reputation: 32704
I'm normally an ASP.NET programmer, so I don't have much experience with WPF. I'm trying to create a notification window that opens on the screen in response to some server side event. I want it to behave similarly to the notifications given by Microsoft Outlook. The window should show for 5 seconds, then begin fading out which should last for 5 seconds, at which point the window should close. If the user mouses over the window, the windowTimer or the fade out animation should pause depending on how much time has elapsed. This works fine in the first 5 seconds of execution. However, once the fade out animation starts, it doesn't pause by mousing over. My question is: Why isn't my code pausing the animation when the mouse enters?
public partial class MainWindow : Window
{
Timer windowTimer; //System.Timers.Timer
AnimationClock clock;
bool fadingOut = false;
public MainWindow()
{
InitializeComponent();
}
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
windowTimer = new Timer(5000);//5 seconds
windowTimer.Start();
windowTimer.Elapsed += new ElapsedEventHandler(windowTimer_Elapsed);
}
protected override void OnMouseEnter(MouseEventArgs e)
{
base.OnMouseEnter(e);
if (!fadingOut)
{
windowTimer.Stop();
}
if (clock != null)
{
clock.Controller.Pause();
}
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
if (!fadingOut)
{
windowTimer.Start();
}
if (clock != null)
{
clock.Controller.Resume();
}
}
private void windowTimer_Elapsed(object sender, ElapsedEventArgs e)
{
windowTimer.Elapsed -= windowTimer_Elapsed;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => BeginFadeout()));
}
private void BeginFadeout()
{
windowTimer.Stop();
fadingOut = true;
DoubleAnimation fadeoutanim = new DoubleAnimation(0,
(Duration)TimeSpan.FromSeconds(5));
fadeoutanim.Completed += (s, _) => this.Close();
clock = fadeoutanim.CreateClock();
this.BeginAnimation(UIElement.OpacityProperty, fadeoutanim);
}
}
Upvotes: 0
Views: 1092
Reputation: 764
To get your code working you could just replace this.BeginAnimation(UIElement.OpacityProperty, fadeoutanim);
with this.ApplyAnimationClock(OpacityProperty, clock);
, otherwise the clock you get is not the one that controls the animation.
Also, your code will throw exception if the mouse is over the window when it starts, you should ensure that windowTimer is not null before starting / stopping it.
But using a storyboard is clearly a cleaner solution.
Instead of recreating your own notification, you should have a look at this library, which is available from NuGet and has a good howto.
Upvotes: 3
Reputation: 9857
So the easiest way to do this is with storyboards. Since blend is a very easy tool to use and makes quick work of this I will use this as the example. You can also of course create the storyboard by hand.
Step 1: Create your control
Step2: Create your storyboard by clicking the little plus symbol on the left. Name it something meaningful. You will note that the UI element you have selected in the list on the left will be the one that the storyboard is applied to.
Step 3: On the left set the keyframe. This is how long the animation will take to execute and where it will execute what you tell it to. Make sure to set the keyframe FIRST then set the properties.
Step 4: Finally go into visual studio and execute your storyboard. In this example the storyboard resides in the static resources. So I pull it out of the static resources and tell it to either begin or stop (which returns it to the start which in this case is opacity 1)
If you still want to do it by hand then add this to your notification window XAML
<Window.Resources>
<Storyboard x:Key="FadeOutAnimation">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="window">
<EasingDoubleKeyFrame KeyTime="0:0:1.1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
I know a quick copy and paste seems faster but learning to use Blend will save you a ton of UI heart ache in the future.
Upvotes: 4