繁体   English   中英

如何在动态生成的ContextMenu中向项目添加命令

[英]How do I add a command to items in dynamically generated ContextMenu

我有一个从ObservableCollection填充的上下文菜单。 我希望用户能够单击这些项中的任何项,然后调用一种方法来传递被单击项的文本作为参数。

我首先关注这个问题的答案。 但是,我的控制台输出中出现错误,并且未调用我的方法。

System.Windows.Data错误:40:BindingExpression路径错误:在'object''MenuItem'(Name ='myMenu')'上找不到'FunctionToCall'属性。 BindingExpression:Path = FunctionToCall; DataItem ='MenuItem'(Name ='myMenu'); 目标元素是'MenuItem'(Name =''); 目标属性为“命令”(类型为“ ICommand”)

这是我的xaml

            <MenuItem Name="myMenu" Header="display text" ItemsSource="{Binding}" >
                <MenuItem.ItemContainerStyle>
                    <Style TargetType="MenuItem">
                        <Setter Property="Command" Value="{Binding FunctionToCall, RelativeSource={RelativeSource AncestorType=MenuItem}}"/>
                        <Setter Property="CommandParameter" Value="{Binding}"/>
                    </Style>
                </MenuItem.ItemContainerStyle>
            </MenuItem>

而我的视图模型代码

    RelayCommand _command;
    public ICommand FunctionToCall
    {
        get
        {
            if (_command == null)
            {

                _command = new RelayCommand(p => this.InnerMethod(p));
            }
            return _command ;
        }
    }
    public void InnerMethod(object parameter)
    {
        ....

另一个答案建议在绑定中添加一个或两个DataContext,我尝试了这个尝试,但仍然收到相同的错误,尽管它说找不到DataContext属性而不是FunctionToCall。

我在这里找到了RelayCommand的定义。

真正的问题在于绑定。 使用MenuItemDataContext属性实际获取ViewModel实例

<MenuItem Name="myMenu" Header="display text" ItemsSource="{Binding}" >
   <MenuItem.ItemContainerStyle>
        <Style TargetType="MenuItem">
           <Setter Property="Command" Value="{Binding DataContext.FunctionToCall, RelativeSource={RelativeSource AncestorType=MenuItem}}"/>
            <Setter Property="CommandParameter" Value="{Binding}"/>
         </Style>
   </MenuItem.ItemContainerStyle>
 </MenuItem>

MenuItem将获得ViewModel作为DataContext。 所以实际上我们想要..

MenuItem.DataContext.FunctionToCall

希望您不需要将不同的菜单项绑定到不同的命令,否则您需要进行一些更改。

根据您的评论:

您需要一个List<MenuItem> MenuItems来与ContextMenu ItemSource属性绑定为

public class MenuItem
{
    public string Header { get; set; }

    public ICommand Command { get; set; }
}

XAML:

<ContextMenu ItemsSource="{Binding MenuItems}" >
        <ContextMenu.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}" >
                <Setter Property="Header" Value="{Binding Header}"/>
                <Setter Property="Command" Value="{Binding Command}" />
            </Style>
        </ContextMenu.ItemContainerStyle>
    </ContextMenu>

并根据需要在ViewModel中添加所需的上下文菜单项。

这是怎么做的。

public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }

a

<MenuItem Header="{Binding Item1}" Command="{Binding FunctionToCall}" CommandParameter="{Binding Header, RelativeSource={RelativeSource Self}}"/>

视图模型

public class ViewModel
    {
        ICommand _cmd = new CustomCommand();
        public ICommand FunctionToCall
        {
            get { return _cmd; }
            set { _cmd = value; }
        }

        public string Item1 { get; set; }

        public ViewModel() { Item1 = "1Header"; }
    }

命令

public class CustomCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        MessageBox.Show(parameter.ToString());
    }
}

因此,假设您想将MenuItem Header作为参数传递给命令,请进行以下更改:

<Setter Property="Command" Value="{Binding FunctionToCall}"/>
<Setter Property="CommandParameter" Value="{Binding Header, RelativeSource={RelativeSource Self}}"/>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM