如何触发WPF ContextMenu的结束动画?

Ash*_*vis 5 c# wpf

有没有人知道在WPF ContextMenu关闭时是否可以触发动画?

我有代码在打开ContextMenu时触发动画.动画使上下文菜单淡入视图.当ContextMenu关闭以使其淡出时,我也想要一个动画.

启动打开的淡入动画的代码如下所示:

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

        menu.BeginAnimation(ContextMenu.OpacityProperty, animation);
Run Code Online (Sandbox Code Playgroud)

淡入动画也在子菜单项上运行.

请注意,除了淡入和淡出之外,我还想运行其他动画.例如,我希望上下文菜单从零开始向上扩展,以便将其"反弹"到视图中.

Ray*_*rns 6

除了Popup.PopupAnimation之外,ContextMenu或Popup中没有钩子允许你延迟拆除ContextMenu,破坏窗口等,足以显示你的动画.这给你留下了几个选择:

  1. 您可以使用Popup.PopupAnimation延迟弹出窗口关闭,然后用您自己的动画替换它的动画,
  2. 您可以在ContextMenuClosing中在自己的Popup中显示ContextMenu,播放动画并将其删除
  3. 您可以实现自己的代码来处理右键单击,Shift-F10等,以创建Popup并在其中显示ContextMenu

使用Popup.PopupAnimation

在ContextMenuOpened事件中,找到弹出窗口并将Popup.PopupAnimation设置为任何动画,然后监视Popup.IsOpen,当IsOpen属性变为false时,使用Dispatcher回调将预定动画替换为您自己的动画.您的动画可以重用Popup类创建的TranslateTransform,也可以添加自己的变换.

这种技术简单且兼容,但缺点是您无法控制弹出窗口决定关闭的时间与所有拆除时间之间的(固定)间隔的持续时间.它似乎是大约1/6秒,所以如果你可以忍受这可能是要走的路.

使用您自己的Popup在关闭动画期间显示ContextMenu

当您获得ContextMenuClosing时,显示菜单的Popup已经消失,但您可以暂时创建一个新的.

为避免闪烁,必须在DisplatchPriority.Render或更高版本上完成.此外,新弹出窗口的位置和大小必​​须与菜单弹出窗口中创建的位置和大小完全相同.可以在ContextMenuOpened事件之后立即记录这些坐标.您必须在Dispatcher回调中执行此操作,因为 ContextMenuOpened事件期间坐标实际上不可用.

所以程序如下:

  • 在ContextMenuOpened上,执行记录弹出窗口位置和大小的Action的Dispatcher.BeginInvoke.
  • 在ContextMenuClosed上,执行一个Action的Dispatcher.BeginInvoke,它在那个Child是ContextMenu的位置和大小上构造一个Popup,将其IsOpen设置为true,启动动画
  • 当动画结束时(可以使用计时器完成),将Popup的IsOpen设置为false并清除其Child属性
  • 不要忘记确保在动画时间内正确设置ContextMenu的DataContext,这样它将显示与关闭ContextMenu之前相同的数据.

实现您自己的ContextMenu处理代码

如果在ContextMenuOpened事件中将ContextMenuEventArgs.Handled标记为true,则ContextMenu代码实际上不执行任何操作,允许您自己呈现ContextMenu.去做这个:

  1. 构造一个Popup,计算适当的位置(这绝对是非平凡的!),并将ContextMenu添加为其子级
  2. 将Popup.IsOpen设置为true并开始打开动画
  3. 当ContextMenu关闭时,启动结束动画,然后将Popup.IsOpen设置为false并清除其Child属性

其中棘手的部分是根据用户操作可靠地决定何时关闭ContextMenu(步骤3).我不知道有任何方法可以重用.NET Framework的内置机制,并且ContextMenu关闭时的规则非常复杂.


Ams*_*nna 0

您不能使用ContextMenuClosing事件吗