我有一个从ObservableCollection填充的上下文菜单。我希望用户能够点击任何这些项目,然后调用一个方法将所点击的项目的文本作为参数传递。
我开始关注this question的回答。但是,我的控制台输出中出现错误,我的方法没有被调用。
System.Windows.Data错误:40:BindingExpression路径错误:在'object'''MenuItem'(Name ='myMenu')'上找不到'FunctionToCall'属性。 BindingExpression:路径= FunctionToCall; DataItem ='MenuItem'(Name ='myMenu'); target元素是'MenuItem'(Name =''); target属性是'Command'(类型'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)
{
....
另一个答案建议在Binding中添加一个或两个DataContexts,我试过这个但我仍然得到相同的错误,尽管它说找不到DataContext属性而不是FunctionToCall。
我找到了RelayCommand here的定义。
答案 0 :(得分:1)
真正的问题在于绑定。使用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<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中添加所需的上下文菜单项。
答案 1 :(得分:-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());
}
}
因此,假设您希望将Header
MenuItem
作为参数传递给您的命令,请执行以下更改:
<Setter Property="Command" Value="{Binding FunctionToCall}"/>
<Setter Property="CommandParameter" Value="{Binding Header, RelativeSource={RelativeSource Self}}"/>