Storyboard.Begin()偶尔被阻止或延迟

时间:2012-02-01 00:05:18

标签: c# .net windows-7

我们的应用程序使用动画在消息窗口关闭时淡出。为此,我们重写OnClosing,如果我们还没有完成动画,我们取消关闭并启动动画。动画完成后,我们关闭窗口。这似乎是基于我在网上看到的相当普遍的模式,因为Closing and Closed不是可路由的事件。

问题是,我们偶尔会看到一个窗口“卡住” - 动画似乎没有发生,所以“完成”标志永远不会被设置,窗口就在那里,取消任何关闭事件。有时候,动画最终开始关闭,窗口关闭,但有时它似乎永远卡住了(虽然显然你无法确定......停止问题以及所有......)。

有没有人想过为什么即使在调用Begin()之后Storyboard也不会被踢掉?如果没有真正深入挖掘Storyboard代码/数据结构,感觉就像是在等待事情真正开始之前发生,从未发生过。

以下是我目前排除的一些可能性:

  • 错误的线程(在GUI线程上创建/处理/访问所有窗口,动画,故事板等)
  • GUI线程被阻止(单击X仍会触发Closing事件,GUI线程响应其他窗口,系统托盘等中的事件)
  • GUI线程忙(我们只在GUI线程上进行UI工作,我们通常只打开一个窗口,一次最多只能运行一个“关闭”动画)

那就是说,这里有一些可能有所贡献的事情:

  • Windows可以互相关闭(在某些情况下,如果一个已经打开,新的将关闭现有的)
  • 我们还有一个通过XAML绑定到Loaded事件的“淡入”动画,但这似乎完全正确。
  • 我们最近删除了“主”UI窗口,因此应用程序的主窗口现在是一个虚拟隐藏窗口。

我怀疑最后一个最强烈,因为它是最近添加的,并且在此更改之前从未报告/注意到此行为(尽管我无法明确地说明从未在此更改之前发生) 。但是其他与GUI /窗口相关的事件仍然可以正常工作,淡出动画逻辑当时大多数

最后,这是我们执行结束动画的代码:

public class MyWindow : Window {
    private bool _storyBoardCompleted;
    private Storyboard _closingStoryBoard;

    protected Storyboard GetClosingStoryBoard()
    {
        Grid mainGrid = (Grid)FindName("MainGrid");
        DoubleAnimation closingAnimation = new DoubleAnimation();
        closingAnimation.From = 1;
        closingAnimation.To = 0;
        closingAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(500));

        Storyboard.SetTarget(closingAnimation, mainGrid);
        Storyboard.SetTargetProperty(closingAnimation, new PropertyPath(OpacityProperty));

        Storyboard storyboard = new Storyboard();
        storyboard.Children.Add(closingAnimation);
        storyboard.Completed += StoryboardCompleted;

        return storyboard;
    }

    private void StoryboardCompleted(object sender, EventArgs e)
    {
        _storyBoardCompleted = true;
        Close();
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        if (_closingStoryBoard == null)
        {
            _closingStoryBoard = GetClosingStoryBoard();
            _closingStoryBoard.Begin();
        }

        if (!_storyBoardCompleted)
        {
            e.Cancel = true;
        }
    }
}

编辑: 每当我们及时打开其中两个窗口非常靠近时,问题就会突然出现,并在显示第二个之前关闭第一个窗口。基本上:

window1.Show()
window1.Close()
window2.Show()

此时,如果我们尝试关闭window2,它将取消关闭,如上面的代码,但动画将不会开始(因此问题)。如果我们稍后再调用window2.Close()紧跟window3.Show()(即显示第三个窗口),那么window2的动画结束并且窗口关闭 - 但是window3陷入了相同的状态。因此,一旦我们处于这种状态,行为几乎似乎从一个窗口“传递”。

编辑: 我已经排除了另一种可能性 - 我想知道第二个窗口的“淡入”故事板是否与第一个窗口的“淡出”故事板有些冲突,并以某种方式影响第二个窗口的淡出。但即使在删除淡入故事板后,问题仍然存在。 此外,如果我用一个半秒的调度计时器(即只是延迟关闭,没有动画)替换淡出故事板,问题就完全消失了。只是一个完整性检查它肯定与动画有关...

2 个答案:

答案 0 :(得分:0)

您是否曾尝试将参数添加到Begin方法:

_closingStoryBoard.Begin(this);

答案 1 :(得分:0)

我从来没有明确说明为什么会发生这种情况,但这似乎与我第二个窗口显示第二个窗口仍然是动画的事实有关。我仍然不明白为什么这会引起问题,但我能够通过等待第一个完全关闭然后显示第二个(基本上挂在第一个窗口的Closed事件上)来解决它。

如果“等待第一个窗口关闭”的解决方法永远不够用,我们仍然想知道为什么这样做会这样做......