ContextMenu
上有一个Button
,我想在MouseEnter
事件中打开,而不是默认的右键单击事件。这是我的XAML:
<Button Content="Button" MouseEnter="Button_MouseEnter" MouseLeave="Button_MouseLeave">
<Button.ContextMenu>
<ContextMenu>
.... context menu items ....
</ContextMenu>
</Button.ContextMenu>
</Button>
以及相关的事件处理程序:
private void Button_MouseEnter(object sender, MouseEventArgs e)
{
backButtonContextMenu.Placement = PlacementMode.Bottom;
backButtonContextMenu.IsOpen = true;
Console.WriteLine("MouseEnter called");
}
private void Button_MouseLeave(object sender, MouseEventArgs e)
{
backButtonContextMenu.IsOpen = false;
Console.WriteLine("MouseLeave called");
}
非常直接。不幸的是,当鼠标悬停在按钮上时,这两种方法被无限调用,来回交替。以下是我的控制台中输出的示例:
MouseEnter called
MouseLeave called
MouseEnter called
MouseLeave called
MouseEnter called
MouseLeave called
MouseEnter called
MouseLeave called
... etc. ...
我认为这与ContextMenu在打开时窃取焦点有关,或者可能会放置某种不可见的“辅助”背景来检测何时需要关闭它。有没有人对这种行为有解释,有没有办法避免它?从UI的角度来看,这是一个非常简单的效果。
答案 0 :(得分:2)
当ContextMenu
被调用Button
松开鼠标然后关闭ContextMenu
然后鼠标重新返回Button
时,它进入循环cos你得到了你的循环。
private void Button_MouseLeave(object sender, MouseEventArgs e) {
if (backButtonContextMenu.IsMouseOver)
return;
backButtonContextMenu.IsOpen = false;
Debug.WriteLine("MouseLeave called");
}
然而,现在你遇到了不得不在另一个时刻关闭菜单的问题。
在这种情况下,当我需要一个像ContextMenu
这样的菜单而不是它的默认行为时,我倾向于选择Popup
。
对Popup
:
<StackPanel>
<Button x:Name="button"
Content="Button" />
<Button x:Name="button2"
Content="Button 2" />
<Popup Placement="Right"
PlacementTarget="{Binding ElementName=button}">
<Menu>
<MenuItem Header="AAA" />
</Menu>
<Popup.Style>
<Style TargetType="{x:Type Popup}">
<Setter Property="IsOpen"
Value="True" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self},
Path=PlacementTarget.IsMouseOver}"
Value="False" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self},
Path=IsMouseOver}"
Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="IsOpen"
Value="False" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Popup.Style>
</Popup>
</StackPanel>
您可以根据需要调整条件。
答案 1 :(得分:0)
最近我遇到了这个问题,当鼠标悬停在按钮上时,我需要一个菜单来打开和关闭。 Viv的出色答案(https://stackoverflow.com/a/17453601/3403999)解决了一个小问题:当鼠标从按钮切换到弹出窗口时,我注意到了闪烁的效果(反之亦然)。基本上,弹出窗口在不到一秒钟的时间内关闭并重新打开。最初,我尝试使用HorizontalOffset属性使弹出窗口重叠,但闪烁仍然存在。
我的最终解决方案是在一个非常基本的情节提要中添加Enter / Exit动作,我想与他人分享,以防其他人看到Viv的答案并试图弄清楚如何防止闪烁:
<StackPanel>
<Button x:Name="button"
Content="Button" />
<Button x:Name="button2"
Content="Button 2" />
<Popup Placement="Right"
PlacementTarget="{Binding ElementName=button}">
<Menu>
<MenuItem Header="AAA" />
</Menu>
<Popup.Style>
<Style TargetType="{x:Type Popup}">
<Setter Property="IsOpen"
Value="True" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self},
Path=PlacementTarget.IsMouseOver}"
Value="False" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self},
Path=IsMouseOver}"
Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard x:Name="HidePopupStoryboard">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen"
Duration="0:0:0.1">
<DiscreteBooleanKeyFrame KeyTime="100%"
Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="HidePopupStoryboard" />
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Popup.Style>
</Popup>
</StackPanel>
您可以增加持续时间以使其短暂打开,但即使是1/10秒的延迟也足以防止闪烁。您甚至可以抛出双重动画,使其淡入/淡出,而不是完全打开/关闭。