当上下文菜单打开时,单击上下文菜单之外的控件不会被点击

问题描述 投票:0回答:2

我有一个按钮,单击它会打开上下文菜单。我在同一个堆栈面板上有另一个按钮,当通过单击按钮 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)
        {

        }
c# wpf menu popup contextmenu
2个回答
1
投票

我无法解释,但是,如果你删除了

StaysOpen="False"

在 XAML 中的

ContextMenu
定义中,那么它将按照您的预期工作。顺便说一句 - 您不需要在 XAML 按钮的触发器和 Click EventHandler 中调用 ContextMenu 两次。

MSDN 写道
StaysOpen
默认为 false。

true 如果菜单应保持打开状态直到 IsOpen 属性更改为 错误的;否则为假。默认为 false。


0
投票

如果没有其他办法,您可以挂钩 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);

    }
© www.soinside.com 2019 - 2024. All rights reserved.