【发布时间】:2012-02-07 08:34:57
【问题描述】:
我们的应用程序在消息窗口关闭时使用动画淡出消息窗口。为此,我们重写 OnClosing,如果我们还没有完成动画,我们取消关闭并开始动画。动画完成后,我们关闭窗口。根据我在网上看到的情况,这似乎是一种相当普遍的模式,因为 Closing 和 Closed 不是可路由的事件。
问题是,我们偶尔会看到一个窗口“卡住”——动画似乎没有发生,所以“完成”标志永远不会被设置,窗口只是坐在那里,取消任何关闭事件。有时,动画最终会启动并关闭窗口,但有时它看起来像是永久卡住(但显然你无法确定......停止问题等等......)。
有没有人知道为什么即使调用 Begin() 后情节提要也不会启动?由于无法真正深入挖掘 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 卡在相同的状态。因此,一旦我们处于这种状态,这种行为似乎会从一个窗口“传递”到另一个窗口。
编辑: 我已经排除了另一种可能性 - 我想知道第二个窗口的“淡入”故事板是否与第一个窗口的“淡出”故事板发生某种冲突,并以某种方式影响第二个窗口的淡出。但是即使在删除淡入故事板之后也会出现问题。 此外,如果我用半秒调度计时器替换淡出故事板(即只是延迟关闭,没有动画),问题就完全消失了。只是一个健全的检查,它肯定与动画有关......
【问题讨论】: