我有一个带有元素的DataGrid,以及这个视图后面的ViewModel。ViewModel 有一个 RelayCommand,它实现了 CanExecuteChanged。DataGridRow 有一个样式,它有一个上下文菜单,它的 MenuItems 绑定到 RelayCommand 并将该项作为参数传递。下面是 XAML:
<ContextMenu x:Key="CommentMenu" DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}">
<MenuItem Header="Bind to Project" Command="{Binding BindToProjectCommand}"
CommandParameter="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}}"/>
</ContextMenu>
<Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="ContextMenu" Value="{StaticResource CommentMenu}" />
</Style>
...
<DataGrid ItemsSource="{Binding Comments}"
RowStyle="{StaticResource DefaultRowStyle}"
IsReadOnly="True"
CanUserAddRows="False">
下面是视图模型:
public MyViewModel()
{
BindToProjectCommand = new RelayCommand<Comment>(BindToProject, CanBindToProject);
}
public bool CanBindToProject(Comment comment)
{
var answer = comment != null && comment.ProjectId == null;
return answer;
}
在运行时调用 CanExecuteChanged,将正确的注释作为参数传递,返回 true,但仍禁用菜单项。输出窗口没有绑定错误,因此绑定肯定是正确的,我可以看到正确的实例即将到来。所以问题是:1. 为什么可以执行的结果被忽略了?2. 如何使其工作?
感谢您的投入。
所以我发现 CommandParameter 的绑定总是绑定到列表中的最后一个注释。最简单的解决方法是将 SelectedItem 绑定到 ViewModel 中的属性,并更改命令和 CanBindToProject 方法,如下所示:
<DataGrid ItemsSource="{Binding Comments}"
IsReadOnly="True"
CanUserAddRows="False"
RowStyle="{StaticResource DefaultRowStyle}"
SelectedItem="{Binding SelectedComment}"
SelectionMode="Single"/>
public Comment SelectedComment
public RelayCommand BindToProjectCommand(BindToProject, CanBindToProject)
public bool CanBindToProject()
{
return SelectedComment != null && SelectedComment.ProjectId == null;
}