我有一个系统设置,其中使用 MVVM 架构动态填充 ContextMenu 层次结构。我的所有绑定都正常运行,除了命令。我的视图是一个指定 ItemContainerStyle 的 ContextMenu。
ContextMenu 的 ItemContainerStyle 设置为:
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding Command, Mode=OneWay}"/>
<Setter Property="IsCheckable" Value="{Binding IsCheckable}"/>
<Setter Property="IsChecked" Value="{Binding IsChecked, Mode=TwoWay}"/>
<Setter Property="Header" Value="{Binding Label}"/>
<Setter Property="ItemsSource" Value="{Binding Children}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsVisible}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContextMenu.ItemContainerStyle>
到目前为止,还没有 ItemTemplate,因为似乎我已经能够在样式中完成所有所需的功能。
ViewModel 必须使用它包装的模型实例来构造,因此 ContextMenu 的 DataContext 似乎不能显式设置为 ViewModel(编译器抱怨它没有无参数构造函数。抱怨提到类型转换器可以也可以使用,尽管我不确定这实际上意味着什么(可以解决问题)。
我的 ViewModel 的相关部分如下,从以下两个可绑定的只读面向公众的成员开始:
public CommandBinding CommandBinding { get; private set; }
public RoutedCommand Command { get { return CommandBinding.Command as RoutedCommand; } }
CommandBinding 及其命令在构造函数中实例化:
CommandBinding = new CommandBinding(new RoutedCommand(), CommandBinding_Executed, CommandBinding_CanExecute);
该构造中提到的方法只是对模型的成员进行操作,并实现如下:
void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (ContextItem.Command != null) ContextItem.Command(ContextItem);
}
void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ContextItem.IsEnabled;
if (ContextItem.ExecuteConditions != null) e.CanExecute = ContextItem.ExecuteConditions.GetInvocationList().Cast<ExecuteCondition>().All(s => s() == true);
}
似乎当绑定到 Command 实际起作用时,所有项目都显示为灰色,好像 CanExecute 返回 false。但是,当我在 CanExecute 中设置断点时,执行永远不会在该点中断(尽管这可能是由于布局线程造成的?)。即使我明确地将 e.CanExecute 设置为 true 并注释掉 CommandBinding_CanExecute 中的其他行,这些项目仍然显示为灰色。在 XAML 中,我尝试使用和不使用 Path= 绑定到 Command 和 CommandBinding 成员,效果相同。当我将绑定模式设置为 OneWayToSource 时,调试器会适当地抱怨该属性是只读的并且无法操作(我希望 ViewModel 提供命令,所以这是有意的)。
我已阅读其他示例和相关问题的解决方案。对于那些遵循 MVVM 模式的人,我无法确定我的实现有何不同。
对于任何解决方案,我必须坚持我仍然可以要求以模型作为参数来构造 ViewModel,并且我希望视图保持所有 XAML,没有 C# 代码。