c# - 通过 MVVM 绑定(bind) MenuItem 的命令

标签 c# wpf xaml mvvm menuitem

我有一个系统设置,其中使用 MVVM 架构动态填充 ContextMenu 层次结构。我的所有绑定(bind)都正常运行,除了命令。我的 View 是一个指定 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 的相关部分如下,从以下两个可绑定(bind)的只读面向公众的成员开始:
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);
}

似乎当绑定(bind)到 Command 实际起作用时,所有项目都显示为灰色,好像 CanExecute 返回 false。但是,当我在 CanExecute 中设置断点时,执行永远不会在该点中断(尽管这可能是由于布局线程造成的?)。即使我明确地将 e.CanExecute 设置为 true 并注释掉 CommandBinding_CanExecute 中的其他行,这些项目仍然显示为灰色。在 XAML 中,我尝试使用和不使用 Path= 绑定(bind)到 Command 和 CommandBinding 成员,效果相同。当我将绑定(bind)模式设置为 OneWayToSource 时,调试器会适本地提示该属性是只读的并且无法操作(我希望 ViewModel 提供命令,所以这是有意的)。

我已阅读其他示例和相关问题的解决方案。对于那些遵循 MVVM 模式的人,我无法确定我的实现有何不同。

对于任何解决方案,我必须坚持我仍然可以要求以模型作为参数来构造 ViewModel,并且我希望 View 保持所有 XAML,没有 C# 代码。

最佳答案

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

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

关于c# - 通过 MVVM 绑定(bind) MenuItem 的命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14568482/

相关文章:

c# - 在 Metro 应用程序中打印

xaml - 如何使用 Xaml 将上标添加到 Xamarin Forms 中的标签

c# - 如何将空值插入到 Uniqueidentifier 列

c# - WPF UI 多任务处理

c# - 确保在 Visual Studio 中为 Windows Phone 正确设置引用

c# - 如何在 XAML 中执行 Path.Data.Transform?

c# - 在 WP8.1 中缩放图像

c# - 从日期时间获取周数

c# - 需要 .NET 串行端口帮助,主要是在多个 "packets"中接收到的数据

c# - Entity Framework SQL 查询不使用 SQL 参数