【问题标题】:How do I add a command to items in dynamically generated ContextMenu如何向动态生成的 ContextMenu 中的项目添加命令
【发布时间】:2016-05-06 03:02:06
【问题描述】:

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

我首先关注this question 的答案。但是,我的控制台输出出现错误,并且我的方法没有被调用。

System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“MenuItem”(名称=“myMenu”)上找不到“FunctionToCall”属性。绑定表达式:路径=函数调用; DataItem='MenuItem' (Name='myMenu');目标元素是'MenuItem'(名称='');目标属性是“命令”(输入“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 here 的定义。

【问题讨论】:

  • 我认为您的相对来源指向动态创建的MenuItem,而不是包含您的命令的MenuItem。你能查一下{Binding DataContext.FunctionToCall, ElementName=myMenu}吗?
  • 收到类似的消息。 “System.Windows.Data 错误:4:找不到与引用'ElementName = myMenu'的绑定源。BindingExpression:Path = DataContext.FunctionToCall;DataItem = null;目标元素是'MenuItem'(名称='');目标属性是“命令”(输入“ICommand”)”

标签: c# wpf xaml data-binding


【解决方案1】:

这是怎么做的。

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

xaml

<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());
    }
}

因此,在您的情况下,假设您想将HeaderMenuItem 作为参数传递给您的命令,请进行以下更改:

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

【讨论】:

  • 我不确定我是否理解。我目前正在将我的 MenuItem 绑定到视图构造函数中的 ObservableCollection(模型属性)。您的解决方案似乎只是将命令连接到单个 MenuItem。
  • 如果你能理解这种方法,你就不会问这个问题。请参阅语法和方法。不过,我会尝试更新我的答案。
  • 我能够通过更改我的 ObservableCollection 来存储具有 FunctionToCall 方法的对象来使其工作。以前我的模型有这种方法,而我只有一个字符串集合。谢谢
【解决方案2】:

真正的问题在于您的绑定。使用 MenuItem 的 DataContext 属性 实际访问 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&lt;MenuItem&gt; 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 中添加任意数量的上下文菜单项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 1970-01-01
    相关资源
    最近更新 更多