【问题标题】:WPF: How to dynamically generate ContextMenuWPF:如何动态生成 ContextMenu
【发布时间】:2013-02-09 01:27:00
【问题描述】:

我有包含多个项目的 ListBox(SelectionMode=Extended),我想添加上下文菜单功能。问题是如何根据某些条件动态创建上下文菜单。例如。如果只选择了一个项目,我想显示常规上下文菜单,但在选择多个项目时显示其他上下文菜单(例如添加了一些新项目)。另外,如果所选项目中至少有一个具有某些属性集,我想创建第三种上下文菜单。等等...可以有多个这样的条件。

基本上,我需要在用户右键单击鼠标按钮之后但在菜单实际显示之前立即动态生成上下文菜单。这可能吗?

【问题讨论】:

    标签: wpf contextmenu


    【解决方案1】:

    我找到了我的问题的答案,它是 ContextMenuOpening 事件。 基本上我需要处理这个事件并根据当前的应用程序状态进行菜单调整。更多细节在这里:https://msdn.microsoft.com/en-us/library/Bb613568(v=vs.100).aspx

    【讨论】:

    • 链接现在无效
    • 以防万一 Document 再次以任何方式被删除,标题为“如何:处理 ContextMenuOpening 事件”,以便您搜索它。
    【解决方案2】:

    我知道这是一个老问题。 似乎有一个非常简单的答案可以解决 OP 在 MVVM 场景中的原始问题,因为 ContextMenu 类支持通过 ItemsSource 属性进行绑定。

    希望它可以帮助遇到此问题的人。

    XAML

          <ContextMenu ItemsSource="{Binding Path=ItemList, UpdateSourceTrigger=PropertyChanged}">
          </ContextMenu>
    

    在ViewModel中,可以根据当前应用状态动态修改“ItemList”属性。

    【讨论】:

    • @Julien,请参阅this 答案。
    【解决方案3】:

    如果您有一组预定义的上下文菜单,想要根据特定场景使用,您始终可以将上下文菜单创建为资源。

    <Window.Resources>
        <ContextMenu x:Key="Menu1">
            <MenuItem>Item1</MenuItem>
        </ContextMenu>
        <ContextMenu x:Key="Menu2">
            <MenuItem>Item1</MenuItem>
            <MenuItem>Item2</MenuItem>
        </ContextMenu>
    </Window.Resources>
    

    然后在您的ListBox 上创建数据触发器以设置要使用的ContextMenu,而不是我在下面所做的,我建议绑定到您的视图模型上的属性或为此的代码,因为它可能会变得非常混乱在xml中。 这里的实现检查是否只选择了一个项目,在这种情况下切换到 Menu1

    <ListBox x:Name="mylist" SelectionMode="Multiple" ContextMenu="{StaticResource Menu2}" >
        <ListBox.Style>
            <Style TargetType="{x:Type ListBox}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=SelectedItems.Count, RelativeSource={RelativeSource Self}}" Value="1" >
                        <Setter Property="ContextMenu" Value="{StaticResource ResourceKey=Menu1}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Style>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Path=DisplayName}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    如果选择显示哪个上下文菜单只与视图有关,我建议在后面的代码中处理它。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            // Hook up any events that might influence which menu to show
            mylist.SelectionChanged += listSelectionChanged;
            InitializeComponent();
        }
    
        private void listSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var listBox = sender as ListBox;
            if (listBox == null)
                return; // Or throw something, hard
    
            ContextMenu menuToUse;
            // Logic for selecting which menu to use goes here
    
            listBox.ContextMenu = menuToUse;
        }
    }
    

    虽然如果 ViewModel 确实对显示哪个菜单感兴趣(听起来不像,但如果不知道完整的上下文很难分辨),您可以公开一些属性,让您在 ViewModel 中决定 ContextMenu以显示。尽管您很可能希望创建一个类来确保在任何给定时间只有一个布尔值为真,而不是单个布尔属性。

    public class MyViewModel : INotifyPropertyChanged
    {
    
        public MyViewModel()
        {
            SelectedItems = new ObservableCollection<string>();
            SelectedItems.CollectionChanged += SelectedItemsChanged;
        }
    
        private void SelectedItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // Logic to see which ShowMenuX property to set to true goes here
        }
    
        public ObservableCollection<string> SelectedItems { get; set; }
    
        private bool _showMenu1 = false;
        public bool ShowMenu1
        {
            get { return _showMenu1; }
            set
            {
                _showMenu1 = value;
                RaisePropertyChanged("ShowMenu1");
            }
        }
    
        // INotifyPropertyChanged implementation goes here
    }
    

    【讨论】:

    • 非常有帮助,谢谢,但不能完全解决我的问题。我需要在代码中即时创建上下文菜单。这是因为一些影响上下文菜单的条件只能从代码中检查/计算。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 2016-05-06
    • 2013-01-19
    • 1970-01-01
    • 2017-10-23
    • 2012-04-24
    相关资源
    最近更新 更多