我有一个系统设置,其中使用MVVM架构动态填充ContextMenu层次结构。除了Command之外,我的所有绑定都能正常运行。我的视图是一个ContextMenu,它指定了ItemContainerStyle。
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(编译器抱怨它没有无参数构造函数。投诉提到a也可以使用类型转换器,但我不确定实际意味着什么(可以解决问题)。
我的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#代码。
答案 0 :(得分:1)
似乎CommandBinding是个问题。我最终创建了自己的ICommand实现,它允许我在构造上指定Execute和CanExecute委托...这完美地工作。
这解决了问题并且实现很简单,但我仍然不清楚为什么我使用CommandBindings无法正常工作。