在 WPF 应用程序中打开或关闭 ContextMenu 时调整按钮的视觉状态
Adjusting the visual state of a button when ContextMenu is open or closed in WPF app
在我正在开发的 WPF 应用程序中,有一个 Button
Style
定义了它自己的 Template
(ControlTemplate
).
我通过 ControlTemplate.Triggers
处理视觉更新,例如 IsMouseOver
的以下内容:
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="IsMouseOverBorder"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="IsMouseOverBorder"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:0.16" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
我已经为一些使用这种风格的 Button
添加了上下文菜单。这样做之后,当右键单击 Button
时,会显示上下文菜单,但 IsMouseOver
触发器会立即执行退出操作。我更希望在上下文菜单打开时保持 IsMouseOver
视觉状态——这样看起来会好得多。
我该怎么做?
这里有几个额外的触发器,我认为它们可以实现我想要的,但事实并非如此。第一个触发器 (ContextMenuOpening
) 起作用,但第二个触发器不起作用 - 按钮处于永久 IsMouseOver
外观状态。
<EventTrigger RoutedEvent="ContextMenuService.ContextMenuOpening">
<BeginStoryboard Name="ContextMenuOpeningStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="IsMouseOverBorder"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ContextMenuService.ContextMenuClosing">
<RemoveStoryboard BeginStoryboardName="ContextMenuOpeningStoryboard" />
</EventTrigger>
知道为什么这行不通,或者有其他可行的方法吗?
我使用我的问题中定义的样式让它工作,但我不得不手动引发 ContextMenuService.ContextMenuClosingEvent
事件(使用一些反射来这样做):
<ContextMenu Closed="ContextMenu_Closed">...</ContextMenu>
后面的代码:
private void ContextMenu_Closed(object sender, RoutedEventArgs args)
{
var type = typeof(ContextMenuEventArgs);
var contextMenuEventArgs = (ContextMenuEventArgs) type.Assembly.CreateInstance
(
type.FullName, false, BindingFlags.Instance | BindingFlags.NonPublic, null,
new object[] { this, false }, null, null
);
if (contextMenuEventArgs != null)
{
contextMenuEventArgs.RoutedEvent = ContextMenuService.ContextMenuClosingEvent;
_myToggleButton.RaiseEvent(contextMenuEventArgs);
}
}
在我正在开发的 WPF 应用程序中,有一个 Button
Style
定义了它自己的 Template
(ControlTemplate
).
我通过 ControlTemplate.Triggers
处理视觉更新,例如 IsMouseOver
的以下内容:
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="IsMouseOverBorder"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="IsMouseOverBorder"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:0.16" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
我已经为一些使用这种风格的 Button
添加了上下文菜单。这样做之后,当右键单击 Button
时,会显示上下文菜单,但 IsMouseOver
触发器会立即执行退出操作。我更希望在上下文菜单打开时保持 IsMouseOver
视觉状态——这样看起来会好得多。
我该怎么做?
这里有几个额外的触发器,我认为它们可以实现我想要的,但事实并非如此。第一个触发器 (ContextMenuOpening
) 起作用,但第二个触发器不起作用 - 按钮处于永久 IsMouseOver
外观状态。
<EventTrigger RoutedEvent="ContextMenuService.ContextMenuOpening">
<BeginStoryboard Name="ContextMenuOpeningStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="IsMouseOverBorder"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ContextMenuService.ContextMenuClosing">
<RemoveStoryboard BeginStoryboardName="ContextMenuOpeningStoryboard" />
</EventTrigger>
知道为什么这行不通,或者有其他可行的方法吗?
我使用我的问题中定义的样式让它工作,但我不得不手动引发 ContextMenuService.ContextMenuClosingEvent
事件(使用一些反射来这样做):
<ContextMenu Closed="ContextMenu_Closed">...</ContextMenu>
后面的代码:
private void ContextMenu_Closed(object sender, RoutedEventArgs args)
{
var type = typeof(ContextMenuEventArgs);
var contextMenuEventArgs = (ContextMenuEventArgs) type.Assembly.CreateInstance
(
type.FullName, false, BindingFlags.Instance | BindingFlags.NonPublic, null,
new object[] { this, false }, null, null
);
if (contextMenuEventArgs != null)
{
contextMenuEventArgs.RoutedEvent = ContextMenuService.ContextMenuClosingEvent;
_myToggleButton.RaiseEvent(contextMenuEventArgs);
}
}