【问题标题】:Add an item click listener directly to dynamically populated context menu in code behind在后面的代码中将项目单击侦听器直接添加到动态填充的上下文菜单中
【发布时间】:2018-11-10 01:29:21
【问题描述】:

我在 WPF 中有一个上下文菜单,它将由 List<String> 驱动以显示一组动态生成的菜单项。

列表赋值给上下文菜单的ItemsSource属性,并正确显示菜单的内容。

如果我在后面的代码中创建了一个MenuItem,我可以为该项目分配一个点击侦听器,然后将该项目添加到正确填充列表的菜单的Items 列表中,并允许每个项目调用点击监听器。

我已经实现了这种方法,如下所示。

 private ContextMenu _elementContextMenu;

    public ContextMenu ElementContextMenu {
        get {
            if (_elementContextMenu == null) {
                _elementContextMenu = new ContextMenu();

                //root menu item
                _elementMenuRootItem = new MenuItem();
                _elementMenuRootItem.Click += _elementMenuRootItem_Click;
                _elementMenuRootItem.ItemsSource = ElementMenuContent;

                _elementContextMenu.Items.Add(_elementMenuRootItem);
            }
            return _elementContextMenu;
        }
        set { _elementContextMenu = value; }
    }

使用这种方法,点击监听器将点击的菜单项作为事件源传递,我可以将其转换为MenuItem,如下所示:

  void _elementMenuRootItem_Click(object sender, RoutedEventArgs e) {
        MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;
    }

我想要实现的是显示为列表根的项目列表。

如果我将菜单项列表(在此实现中名为 ElementMenuContent)绑定到上下文菜单的 ItemsSource 属性,则菜单会按照我的意愿填充,但是没有 Click ContextMenu 中的事件。

所需的实现如下所示:

    public ContextMenu ElementContextMenu {
        get {
            if (_elementContextMenu == null) {
                _elementContextMenu = new ContextMenu();
                _elementContextMenu.ItemsSource = ElementMenuContent;

                //Add a click listener directly to the ContextMenu object which allows
                //the source menu item which was clicked to be referenced in the same way 
                //as with a MenuItem click listener
            }
            return _elementContextMenu;
        }
        set { _elementContextMenu = value; }
    }

正在实现的组件扩展了 WPF Canvas,并且只是一个 .cs 文件,因此必须完全在代码中实现。在这种情况下我不能使用 XAML。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# wpf code-behind


    【解决方案1】:

    我不确定我是否理解您问题的这一部分:

    我想要实现的是显示为列表根的项目列表。

    如您所说,ContextMenu 本身没有可用的 Click 事件。最简单的解决方案是订阅 PreviewMouseUp,它将捕获所有鼠标点击活动,然后您可以使用 MouseButtonEventArgs 访问您需要的内容。

    PreviewMouseUphttps://docs.microsoft.com/en-us/dotnet/api/system.windows.uielement.previewmouseup?view=netframework-4.7.2

    如果这没有帮助,您可以随时考虑创建自定义路由事件:https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-create-a-custom-routed-event

    【讨论】:

    • 这是我第一次尝试完成这项工作的方式,它确实在鼠标单击时正确动作,但是它不允许我轻松获取菜单项的内容。我最终采用的解决方案是在后面的代码中附加一个处理程序。这在 XAML 中很简单,但仅使用 c# 代码就不那么直观了。
    【解决方案2】:

    对于遇到同样问题的任何人,解决方案是设置菜单本身的ItemsSource 属性(在这种情况下,ElementMenuContent 对象是List<String>,并将事件处理程序添加到@987654324 @ 对任何MenuItem 组件的ClickEvent 进行操作如下:

        _elementContextMenu.ItemsSource = ElementMenuContent;
    
        _elementContextMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(ElementContextMenuItemClick));
    

    处理程序方法被定义为正常。

        public void ElementContextMenuItemClick(object sender, RoutedEventArgs e) {
            MenuItem selectedMenuItem = (MenuItem)e.OriginalSource;
            String command = selectedMenuItem.Header.ToString();
            SwimLaneController.Instance.ProcessContextMenuCommand(this, command);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      • 1970-01-01
      相关资源
      最近更新 更多