【问题标题】:MenuItem Visibility binding to RelayCommand CanExecute with ParameterMenuItem 可见性绑定到 RelayCommand CanExecute 与参数
【发布时间】:2013-02-10 12:41:18
【问题描述】:

我在 WPF MVVM 应用程序中使用 Josh Smith RelayCommand 类在 ViewModel 中创建命令:

例如:

ICommand RemoveAllCommand = new RelayCommand<object>(OnRemoveAll, CanRemoveAll);

我从 ContextMenu 调用此命令:

<ContextMenu x:Key="MyContextMenu" DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
    <MenuItem Header="Remove All" Command="{Binding Path=DataContext.RemoveAllCommand,
                                  RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}" CommandParameter="{Binding Path=.Header}" />

一切正常,除了我的 MenuItem 仍然可见但已禁用,我想将 Visibility 设置为 Collapsed,以便当 Relay Command 中的 CanExecute 返回 false 时,我的 MenuItem 不会显示。

我尝试设置与 Visibility 属性的绑定,但我不知道如何使用参数绑定到我的 CanRemoveAll(object obj) 方法。我也想过使用 DataTrigger,但我不知道该怎么做。

这是我在 ViewModel 中的 CanRemoveAll 方法:

    public bool CanRemoveAll(object param)
    {
        GoldTreeNodeViewModel gtn = param as GoldTreeNodeViewModel;
        return (gtn != null && gtn.Children != null && gtn.Children.Count > 0);
    }

来自 RelayCommand 类:

public event EventHandler CanExecuteChanged
    {
        add
        {
            if (_canExecute != null)
                CommandManager.RequerySuggested += value;
        }
        remove
        {
            if (_canExecute != null)
                CommandManager.RequerySuggested -= value;
        }
    }

    [DebuggerStepThrough]
    public Boolean CanExecute(Object parameter)
    {
        return _canExecute == null ? true : _canExecute((T) parameter);
    }

任何帮助将不胜感激,

【问题讨论】:

  • 能否请您在 VM 中显示 CanRemoveAll 的代码以及从哪里引发 CanExecuteChanged。
  • 刚刚将该信息添加到问题中。我也没有在任何地方明确提出CanExecuteChanged,我认为RelayCommand 和WPF 内部负责处理这一点,据我所知。

标签: wpf contextmenu relaycommand


【解决方案1】:
 <ContextMenu x:Key="MyContextMenu" DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
        <MenuItem Header="Remove All" Command="{Binding Path=DataContext.RemoveAllCommand,
                              RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}" CommandParameter="{Binding Path=.Header}" 
                  Visibility="{Binding DataContext.RemoveVisibility,RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}"
                  />

private Visibility _removeVisibility;

    public Visibility RemoveVisibility
    {
        get { return _removeVisibility; }
        set { _removeVisibility = value; Notify("RemoveVisibility"); }
    }

    public bool CanRemoveAll(object param)
    {
        GoldTreeNodeViewModel gtn = param as GoldTreeNodeViewModel;
        bool result= (gtn != null && gtn.Children != null && gtn.Children.Count > 0);
        if (result)
            RemoveVisibility = Visibility.Visible;
        else
            RemoveVisibility = Visibility.Collapsed;
        return result;
    }

我认为您绑定的 DataContext 对应于您的 ViewModel 。我希望这会有所帮助。

【讨论】:

  • 哦,这很有意义,虽然我可能需要使用我的 bool 到 Visibility 转换器,但那是次要的。让我试试,谢谢你的建议
  • 是的,您可以这样做并创建 Converter to Convert bool to Visibility。
  • 虽然我不太确定在 VM 中创建 Visibility 类型的属性,这听起来更像是与 View 相关,但我可以创建一个 public bool IsRemoveAllVisible 属性...
  • 这行得通,但我想知道是否有另一种方法可以做到这一点,而不必在 VM 中为每个 MenuItem 创建额外的 Visibility 属性...
  • 我创建 Visibility 属性只是为了让您了解如何做到这一点,否则我将不得不做更多的工作,例如创建 Converter 等。关于为您处理具有单个属性 hmmm 的所有 MenuItems可以创建字符串属性(为其分配命令参数)并将此属性绑定到所有 MenuItems Visisbility 属性并创建转换器,并在此传递 Header 值,如“添加”作为转换器参数,然后在该转换器中比较值和转换器参数是否相同设置可见性可见或折叠。这也只是一个不确定的想法。
猜你喜欢
  • 2014-09-29
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 1970-01-01
  • 2020-10-28
  • 2010-11-04
  • 1970-01-01
相关资源
最近更新 更多