1

我有一个系统设置,其中使用 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# 代码。

4

1 回答 1

1

似乎 CommandBinding 是问题所在。我最终创建了自己的 ICommand 实现,它允许我在构造时指定 Execute 和 CanExecute 代表......效果很好。

这解决了问题并且实现很简单,但我仍然不清楚为什么我使用 CommandBindings 不起作用。

于 2013-01-28T22:16:04.217 回答