none
WPF SplitButton展开上下文菜单事件(ContextMenuOpening)无效? RRS feed

  • 问题

  • WPF没有内置的SplitButton控件。从第三方下载了一两个自制的,基本都是由一个Button和一个ContextMenu合成。该控件有两个鼠标点击事件确实有效:一个是Click,当点击按钮本身时激发;另一个是ItemClick,当点击打开的上下文菜单的某项时激发。我需要一个上下文菜单开启前的事件,做了如下测试:在xaml中通过ContextMenuOpening="testLeft_ContextMenuOpening"声明、注册对应的事件处理方法(上述两个点击事件也是在xaml声明、注册的);在隐藏代码中通过语句testLeft.ContextMenuOpening += testLeft_ContextMenuOpening;声明、注册对应的事件处理方法。两种方式,程序均可编译通过。但执行时,却没有效果。请教各位老师,我的使用有什么问题?有什么好的解决方法?谢谢费心。


    ly_he

    2017年5月25日 16:04

答案

  • 谢谢Bob老师,

    这个控件我也关注过,也测试了下载的程序。谢谢您的提示,我再认真看看。

    为了网站工作规范,我就把此帖标记为答复了。希望以后得到您的更多帮助!


    ly_he

    • 已标记为答案 ly_he 2017年5月29日 13:53
    2017年5月29日 13:53

全部回复

  • Hi,

    请参考下面的文档:

    ContextMenu Opening event doesn't fire properly

    https://connect.microsoft.com/VisualStudio/feedback/details/353112/contextmenu-opening-event-doesnt-fire-properly

    根据以上文档的描述,ContextMenuOpening设计的比较特殊,ContextMenuOpening事件必须在ContextMenu的父控件处理,而不是ContextMenu本身。 如果您尝试在ContextMenu处理它,只有当ContextMenu已经打开时,您才能单击该事件才会触发该事件,直观的现象就是你需要连续点击两次才会触发。

    所以你可以在父控件如button上来注册这个事件,并做相应的处理。

     <Button x:Name="myButton" Margin="10" Content="Right-click me!" ContextMenuOpening="MyButton_ContextMenuOpening" VerticalAlignment="Center" HorizontalAlignment="Center" >
                    <Button.ContextMenu >
                        <ContextMenu >
                           
                        </ContextMenu>
                    </Button.ContextMenu>
                </Button>
            private void MyButton_ContextMenuOpening(object sender, ContextMenuEventArgs e)
            {
    
                FrameworkElement fe = e.Source as FrameworkElement;
                ContextMenu cm = fe.ContextMenu;
                MenuItem mia = new MenuItem();
                mia.Header = "Item1";
                MenuItem mib = new MenuItem();
                mib.Header = "Item2";
                MenuItem mic = new MenuItem();
                mic.Header = "Item3";
                MenuItem mid = new MenuItem();
                mid.Header = "Item4";
                cm.Items.Add(mia);
                cm.Items.Add(mib);
                cm.Items.Add(mic);
                cm.Items.Add(mid);
            }

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    2017年5月26日 7:11
    版主
  • 谢谢Bob老师,

    是我犯糊涂了!ContextMenu是要右键点击才会打开,并激发Opening和Opened两个事件,真是抱歉。

    看了您的回复,注意到您的Content="Right-click me!" 这个设置,一下点醒了我。十分感谢。

    不过,我的想法是。有没有可能在我的程序运行中,仅在这个特定场景下(用户点击SplitButton时),临时把右键点击(系统的内置功能)改变为左键点击?因为,强行要求用户右键点击SplitButton的右边的展开按钮,似乎有点太难为人了。其他场景下,还是应该按照右键点击ContextMenu父控件,打开相应的上下文菜单。

    是不是要通过SplitButton的KeyDown等事件做文章?我真的不会,还请老师费心帮助。

    净给您添麻烦,十分抱歉。


    ly_he

    2017年5月26日 8:35
  • Hi,

    >>临时把右键点击(系统的内置功能)改变为左键点击?

    你可以尝试在某个特定场景使用ContextMenuService.IsEnabled="false" 来禁止使用右击打开。然后在左击事件中进行打开。

     <Button x:Name="myButton" Margin="10" Content="Right-click me!" ContextMenuService.IsEnabled="false" Click="myButton_Click"  VerticalAlignment="Center" HorizontalAlignment="Center" >
                    <Button.ContextMenu >
                        <ContextMenu x:Name="mycm">
                            <MenuItem Header="Item1"/>
                            <MenuItem Header="Item2"/>
                            <MenuItem Header="Item3"/>
                            <MenuItem Header="Item4"/>
                        </ContextMenu>
                    </Button.ContextMenu>
                </Button>
     private void myButton_Click(object sender, RoutedEventArgs e)
            {
                mycm.Visibility = Visibility.Visible;
                mycm.IsOpen = true;
            }

    希望有帮助。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年5月26日 9:46
    版主
  • 谢谢Bob老师,您的思路很好,我理解了。不过我的难点在于使用的是WPF的SplitButton。无法区别鼠标点击的是该分割控件的哪个部分:如果点击的是按钮的主体(一般在左边,显示content的部分),还需要保持控件的Click;如果点击的是打开上下文的部分(一般在右边,有个尖角朝下的三角图标),才需要打开上下文菜单,执行 mycm.Visibility = Visibility.Visible;和 mycm.IsOpen = true;这两句。我想,在您的思路基础上,如果能区别点击的是控件的那个部分,我的问题应该就可以解决了。我想,既然WPF的SplitButton都是用两个控件合成的,是否可以通过解析点击的是控件的那个组成元素,来区别执行?关于如何解析这种组合控件组成部分的方法,还烦请老师给予指点。实在不好意思。

    ly_he

    2017年5月26日 15:04
  • Bob老师,

    昨天想了想,其实,您的回复应该已经解决了我的问题。主要是我纠结于认准使用SplitButton,限制了思路。

    我的问题,按照您的实现代码。完全可以通过以下两个方向解决:

    1、利用xaml,做一个复合Button。即一个Button作为父控件,里面嵌套一个子Button。父Button执行正常的Click事件,子Button按您提供代码,打开上下文菜单。

    2、两个Button并排放置,利用xaml视觉做成一个控件的感觉即可。实现方法同1。

    以上思路,请指正。再次感谢。


    ly_he

    2017年5月27日 3:58
  • 你好,

    >>不过我的难点在于使用的是WPF的SplitButton。无法区别鼠标点击的是该分割控件的哪个部分:如果点击的是按钮的主体(一般在左边,显示content的部分),还需要保持控件的Click;如果点击的是打开上下文的部分(一般在右边,有个尖角朝下的三角图标),才需要打开上下文菜单,

    基于你的描述,我推荐你参考下面的控件:

    A WPF SplitButton

    https://www.codeproject.com/Articles/20612/A-WPF-SplitButton

    这个控件应该能够满足你的需求,这个控件有三种Mode可以选择。你可以参考控件制作自己的Split Button.

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年5月29日 1:03
    版主
  • 谢谢Bob老师,

    这个控件我也关注过,也测试了下载的程序。谢谢您的提示,我再认真看看。

    为了网站工作规范,我就把此帖标记为答复了。希望以后得到您的更多帮助!


    ly_he

    • 已标记为答案 ly_he 2017年5月29日 13:53
    2017年5月29日 13:53