如何触发 WPF ContextMenu 的关闭动画?

5

有人知道当WPF上下文菜单关闭时是否可以触发动画吗?

我有一些代码,当上下文菜单打开时触发动画。这个动画使上下文菜单淡入视图。我还想要一个动画,当上下文菜单关闭时,让它淡出。

启动打开的淡入动画的代码大致如下:

        var animation = new DoubleAnimation();
        animation.From = 0;
        animation.To = 1;
        animation.Duration = TimeSpan.FromSeconds(0.2);
        animation.Freeze();

        menu.BeginAnimation(ContextMenu.OpacityProperty, animation);

淡入动画也可以运用在子菜单项上。

请注意,我还想运行除淡入淡出之外的其他动画。例如,我希望上下文菜单从无到有缩放,以便它可以“弹跳”进入视图。


你能发布当上下文菜单打开时的动画代码吗? - Amsakanna
2个回答

6
除了Popup.PopupAnimation之外,在ContextMenu或Popup中没有钩子可以延迟ContextMenu的拆卸、窗口的销毁等,以便展示你的动画。这让你有几个选择:
1. 你可以使用Popup.PopupAnimation来延迟弹出关闭,然后用自己的动画替换它。 2. 你可以在ContextMenuClosing中使用自己的Popup来呈现ContextMenu,播放动画,然后将其移除。 3. 你可以实现自己的代码来处理右键单击,Shift-F10等,以创建Popup并在其中显示ContextMenu。
使用Popup.PopupAnimation
在ContextMenuOpened事件中,找到Popup并将Popup.PopupAnimation设置为任何动画,然后监视Popup.IsOpen。当IsOpen属性变为false时,使用Dispatcher回调来替换预定的动画。你的动画可以重用Popup类创建的TranslateTransform,也可以添加自己的变换。
这种技术简单且兼容,但缺点是你无法控制弹出窗口决定关闭和一切拆卸之间的(固定)时间间隔的持续时间。它似乎是大约1/6秒,所以如果你可以接受这个,这可能是一个好方法。
使用自己的Popup来在关闭动画期间显示ContextMenu
当你得到ContextMenuClosing时,显示菜单的Popup已经不存在了,但你可以暂时创建一个新的Popup。
为了避免闪烁,这必须在DisplatchPriority.Render或更高的优先级下完成。此外,新的Popup必须与菜单弹出时创建的Popup完全相同的位置和大小。这些坐标可以在ContextMenuOpened事件之后立即记录。你将不得不在Dispatcher回调中执行此操作,因为在ContextMenuOpened事件期间实际上并没有这些坐标可用。
因此,步骤如下:
1. 在ContextMenuOpened上,使用Dispatcher.BeginInvoke调用一个Action来记录弹出窗口的位置和大小。 2. 在ContextMenuClosed上,使用Dispatcher.BeginInvoke调用一个Action,在该位置和大小处构造一个Popup,其Child为ContextMenu,设置其IsOpen为true,开始动画。 3. 当动画结束时(可以使用计时器完成),将Popup的IsOpen设置为false,并清除其Child属性。 4. 不要忘记确保ContextMenu的DataContext在动画时间内设置正确,以便在关闭ContextMenu之前显示与之前相同的数据。
实现自己的ContextMenu处理代码
如果在ContextMenuOpened事件中将ContextMenuEventArgs.Handled标记为true,则ContextMenu代码实际上不会执行任何操作,允许你自己呈现ContextMenu。要做到这一点:
  1. 构建一个弹出窗口,计算合适的位置(这绝对不是易事!),并将ContextMenu添加为其子项。
  2. 设置Popup.IsOpen属性为true,并开始您的打开动画。
  3. 当ContextMenu需要关闭时,启动您的关闭动画,然后将Popup.IsOpen属性设置为false并清空其Child属性。

难点在于根据用户操作可靠地决定何时关闭ContextMenu(步骤3)。我不知道任何重用NET Framework内置机制的方法,而且ContextMenu应关闭的规则非常复杂。


非常感谢你提供如此详细的答案,我会尽快尝试将它应用到我的代码中。 - Ashley Davis

0

很不幸,那个事件太晚了!我可以开始淡出动画,但是它没有任何效果,因为上下文菜单立刻消失了。 - Ashley Davis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接