显示一个通知窗口然后将其淡出,但在鼠标悬停时暂停动画

时间:2014-03-17 16:07:12

标签: c# wpf animation

我通常是一名ASP.NET程序员,因此我对WPF没有多少经验。我试图创建一个在屏幕上打开的通知窗口,以响应某些服务器端事件。我希望它的行为与Microsoft Outlook提供的通知类似。窗口应该显示5秒钟,然后开始淡出,应该持续5秒钟,此时窗口应该关闭。如果用户将鼠标悬停在窗口上,则windowTimer或淡出动画应暂停,具体取决于已经过了多长时间。这在执行的前5秒内工作正常。但是,一旦淡出动画开始,它就不能通过鼠标悬停来暂停。我的问题是:当鼠标进入时,为什么我的代码暂停动画?

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);
    }
}

2 个答案:

答案 0 :(得分:3)

所以最简单的方法是使用故事板。由于混合是一种非常容易使用的工具,并且可以快速完成这项工作,我将以此为例。您当然也可以手动创建故事板。

第1步:创建控件

enter image description here

步骤2:点击左侧的小加号,创建故事板。说出有意义的东西。您将注意到,您在左侧列表中选择的UI元素将是故事板应用于的元素。

enter image description here

步骤3:在左侧设置关键帧。这是动画执行所需的时间以及它将执行您告诉它的位置。确保首先设置关键帧,然后设置属性。

enter image description here

第4步:最后进入visual studio并执行故事板。 在此示例中,故事板位于静态资源中。所以我将它从静态资源中拉出来并告诉它要么开始还是停止(它将它返回到开始,在这种情况下是不透明度1)

enter image description here

如果您仍想手动执行此操作,请将其添加到您的通知窗口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>

我知道快速复制和粘贴似乎更快,但学习使用Blend将在未来为您节省大量的UI心痛。

答案 1 :(得分:3)

要使代码正常工作,您只需将this.BeginAnimation(UIElement.OpacityProperty, fadeoutanim);替换为this.ApplyAnimationClock(OpacityProperty, clock);,否则您获得的时钟不会控制动画。

此外,如果鼠标在启动时鼠标悬停在窗口上,您的代码将抛出异常,您应该确保windowTimer在启动/停止之前不为null。

但使用故事板显然是一个更清洁的解决方案。

您应该查看this库,而不是重新创建自己的通知,该库可以从NuGet获得,并且有一个很好的howto