我有一个按钮,单击它会打开上下文菜单。我在同一个堆栈面板上有另一个按钮,当通过单击按钮 2 打开上下文菜单时,第一次单击按钮 1 不会触发按钮 1 的事件,但是当再单击一次时,该事件就会被触发。简而言之,当按钮 2 的上下文菜单打开时,我需要单击 2 次才能在窗口上触发按钮 1 的事件。
下面是更容易理解的代码:
主窗口.xaml
<Grid MouseLeftButtonDown="Grid_MouseLeftButtonDown">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row = "0" Orientation="Horizontal">
<Button x:Name= "btnOne" Click="btnOneClick"/>
<Button x:Name="btnTwo"
RenderOptions.BitmapScalingMode="HighQuality" Cursor="Hand" ContextMenuService.IsEnabled="False" Click="btnTwoClick">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetName="MyContextMenu"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
<StackPanel>
<StackPanel Height="{Binding ActualHeight, ElementName=btnTwo}" Orientation="Horizontal" HorizontalAlignment="Right" >
<TextBlock HorizontalAlignment="Right" Text="Click Me" ></TextBlock>
</StackPanel>
</StackPanel>
<Button.ContextMenu>
<ContextMenu x:Name="MyContextMenu" StaysOpen="False" Width="200" MaxHeight="258"
BorderBrush="Gray" BorderThickness="1,0,1,1" Closed="MyContextMenuClosed">
<MenuItem Header="MenuOne" StaysOpenOnClick="True" Cursor="Arrow"/>
<MenuItem Header="MenuTwo" StaysOpenOnClick="True" Cursor="Arrow"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
</StackPanel>
</Grid>
MainWindow.xaml.cs
//When user clicks anywhere on the Grid
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//Close the Context menu if it's open
if (btnTwo.ContextMenu.IsOpen)
btnTwo.ContextMenu.IsOpen = false;
}
//When user clicks on btnTwo
private void btnTwoClick(object sender, RoutedEventArgs e)
{
if (!btnTwo.ContextMenu.IsOpen)
{
//Open the Context menu when Button is clicked
btnTwo.ContextMenu.IsEnabled = true;
btnTwo.ContextMenu.PlacementTarget = (sender as Button);
btnTwo.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
btnTwo.ContextMenu.IsOpen = true;
}
}
//When user clicks on btnOne, This event does does not fires when context menu is open
private void btnOneClick(object sender, RoutedEventArgs e)
{
}
我无法解释,但是,如果你删除了
StaysOpen="False"
在 XAML 中的
ContextMenu
定义中,那么它将按照您的预期工作。顺便说一句 - 您不需要在 XAML 按钮的触发器和 Click EventHandler 中调用 ContextMenu 两次。
StaysOpen
默认为 false。
true 如果菜单应保持打开状态直到 IsOpen 属性更改为 错误的;否则为假。默认为 false。
如果没有其他办法,您可以挂钩 LostMouseCapture 事件并手动触发鼠标单击,如下所示:
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
public const int MOUSEEVENTF_LEFTUP = 0x04;
public const int MOUSEEVENTF_RIGHTDOWN = 0x08;
public const int MOUSEEVENTF_RIGHTUP = 0x10;
//This simulates a left mouse click
public static void LeftMouseClick(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0);
}
public static void RightMouseClick(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_RIGHTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_RIGHTUP, xpos, ypos, 0, 0);
}
private void OnLostMouseCapture(object sender, MouseEventArgs e)
{
Point screenPos = Mouse.GetPosition(Application.Current.MainWindow);
int x = (int)screenPos.X;
int y = (int)screenPos.Y;
if (e.LeftButton == MouseButtonState.Pressed)
LeftMouseClick(x, y);
else if (e.RightButton == MouseButtonState.Pressed)
RightMouseClick(x, y);
}