等待,直到Splashscreen在不阻塞UI线程的情况下可见



以下情况:我有一个闪屏,必须在2秒内淡出(从透明到不透明)。当窗口淡入时,程序应该等待,直到它完全可见(故事板完成),然后它应该继续做它的事情。当窗口逐渐淡出时,用户应该已经看到控件的动画(所以阻塞UI线程当然不是一个选项)。这里的动画是指旋转愉快的加载圆。

在我发现如何使用WPF的故事板淡入淡出窗口的一个很好的变体之后,我试图通过使用EventWaitHandle来完成这个任务。由于我的初始化例程已经异步运行,所以我可以使用它。这阻塞了工作线程,并在Splashscreen完全可见之前停止了应用程序的初始化工作。但不知何故,这种方式在一段时间后就被打破了,这似乎不是最好的解决方案。

我现在是这样做的:

public async Task Appear(double time)
{
    Core.IDE.GetGUICore().GetUIDispatcher().Invoke(() =>
    {
        this.Opacity = 0;
        this.Show();
        _fadeInStoryboard = new Storyboard();
        _fadeInStoryboard.Completed += this.FadeInAnimation;
        DoubleAnimation fadeInAnimation = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(time)));
        Storyboard.SetTarget(fadeInAnimation, this);
        Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(OpacityProperty));
        _fadeInStoryboard.Children.Add(fadeInAnimation);
    });
    _currentHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
    Core.IDE.GetGUICore()
        .GetUIDispatcher()
        .InvokeAsync(this._fadeInStoryboard.Begin, DispatcherPriority.Render);
    _currentHandle.WaitOne();
}
/// <summary>
/// Hides the SplashScreen with a fade-out animation.
/// </summary>
/// <param name="time">The fade-out time in seconds.</param>
public void Disappear(double time)
{
    Core.IDE.GetGUICore().GetUIDispatcher().Invoke(() =>
    {
        _fadeOutStoryboard = new Storyboard();
        _fadeOutStoryboard.Completed += this.FadeOutAnimation;
        DoubleAnimation fadeOutAnimation = new DoubleAnimation(1.0, 0.0,
            new Duration(TimeSpan.FromSeconds(time)));
        Storyboard.SetTarget(fadeOutAnimation, this);
        Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(OpacityProperty));
        _fadeOutStoryboard.Children.Add(fadeOutAnimation);
    });
    Core.IDE.GetGUICore()
       .GetUIDispatcher()
       .BeginInvoke(new Action(_fadeOutStoryboard.Begin), DispatcherPriority.Render, null);
}
private void FadeInAnimation(object sender, EventArgs e)
{
    _currentHandle.Set();
}
private void FadeOutAnimation(object sender, EventArgs e)
{
    this.Hide();
}

这是正确的方法吗?有更好的解决方案吗?知道它为什么坏了吗?顺便说一下,我的意思是,应用程序继续做它的初始化的东西,而窗口正在淡入,这结束在一个动画运行,直到它可能在30%的可见度,然后淡出,因为主窗口已经显示。

Thanks in advance

如果您在XAML中声明您的Storyboard,它真的会为您简化事情。试着在你的闪屏控制中使用这个Trigger:

<Grid>
    <Grid.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard Duration="0:0:5" Completed="Storyboard_Completed">
                    <DoubleAnimation From="0.0" To="1.0" 
                        Storyboard.TargetProperty="Opacity" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Grid.Triggers>
    <!--Put your UI elements here-->
</Grid>

你可以从Storyboard_Completed处理程序加载你的应用程序的其余部分,或者如果这是在一个单独的Window,那么你可以从那里引发一些事件或delegate,你应该在MainWindow中处理。

最新更新