【问题标题】:Pass command parameter to method in ViewModel in WPF?将命令参数传递给 WPF 中 ViewModel 中的方法?
【发布时间】:2015-08-18 05:38:31
【问题描述】:

我正在尝试将CommandParameter 传递给我的ViewModel 中的方法。 如何做到这一点?

private void Open(object sender)
{
    if (sender==this.objMainWindow.btnHistory)
    {
        objMainWindow.Container.Child = objHistory;
    }

    if (sender == this.objMainWindow.btnNew_Item)
    {
        objMainWindow.Container.Child = objNewItem;
    }

    if (sender == this.objMainWindow.btnSide_Effects)
    {
        objMainWindow.Container.Child = objSideEffect;
    }
}

这是我在ViewModel 中的方法,我想通过CommandParameter。我使用CommandParameter 作为按钮。

【问题讨论】:

    标签: c# wpf mvvm icommand


    【解决方案1】:

    “ViewModel”意味着 MVVM。如果你在做 MVVM,你不应该将视图传递给你的视图模型。通常你在你的 XAML 中做这样的事情:

    <Button Content="Edit" 
            Command="{Binding EditCommand}"
            CommandParameter="{Binding ViewModelItem}" >
    

    然后在你的视图模型中:

    private ViewModelItemType _ViewModelItem;
    public ViewModelItemType ViewModelItem
    {
        get
        {
            return this._ViewModelItem;
        }
        set
        {
            this._ViewModelItem = value;
            RaisePropertyChanged(() => this.ViewModelItem);
        }
    }
    
    public ICommand EditCommand { get { return new RelayCommand<ViewModelItemType>(OnEdit); } }
    private void OnEdit(ViewModelItemType itemToEdit)
    {
        ... do something here...
    }
    

    显然,这只是为了说明这一点,如果您只有一个要编辑的名为 ViewModelItem 的属性,那么您不需要将其作为命令参数传递。

    【讨论】:

    • 如何使用RaisePropertyChanged()?
    • 这只是 MVVM Lite 使用的属性更改通知的实现,您可以通过 NuGet 添加(从 ViewModelBase 派生您的视图模型)。还有许多其他方法可以做到这一点,包括herehere
    • @marbel82 确实我做到了,感谢您的更正(不幸的是无法编辑 cmets)。
    • “如果您只有一个属性需要编辑,称为 ViewModelItem,那么您不需要将其作为命令参数传递”。无论视图模型上有多少属性,我认为传递属性值的目的是避免否则会发生的竞争条件(因为在用户单击按钮和正在读取的属性之间,属性可能会发生变化)点击后的时间)。
    • 传入参数时,没有竞态条件。如果在处理程序中您首先进行异步调用然后获取参数,则它可能与传入时的值不同。
    【解决方案2】:

    仅使用数据绑定语法。例如,

    <Button x:Name="btn" 
             Content="Click" 
             Command="{Binding ClickCmd}" 
             CommandParameter="{Binding ElementName=btn,Path=Content}" /> 
    

    我们不仅可以使用数据绑定从视图模型中获取一些数据,还可以将数据传回视图模型。在 CommandParameter 中,必须使用 ElementName 显式声明绑定源。

    【讨论】:

      【解决方案3】:

      试试这个:

       public class MyVmBase : INotifyPropertyChanged
      {
        private ICommand _clickCommand;
         public ICommand ClickCommand
          {
              get
              {
                  return _clickCommand ?? (_clickCommand = new CommandHandler( MyAction));
              }
          }
          
             public void MyAction(object message)
          {
              if(message == null)
              {
                  Notify($"Method {message} not defined");
                  return;
              }
              switch (message.ToString())
              {
                  case "btnAdd":
                      {
                          btnAdd_Click();
                          break;
                      }
      
                  case "BtnEdit_Click":
                      {
                          BtnEdit_Click();
                          break;
                      }
      
                  default:
                      throw new Exception($"Method {message} not defined");
                      break;
              }
          }
      }
      
        public class CommandHandler : ICommand
      {
          private Action<object> _action;
          private Func<object, bool> _canExecute;
      
          /// <summary>
          /// Creates instance of the command handler
          /// </summary>
          /// <param name="action">Action to be executed by the command</param>
          /// <param name="canExecute">A bolean property to containing current permissions to execute the command</param>
          public CommandHandler(Action<object> action, Func<object, bool> canExecute)
          {
              if (action == null) throw new ArgumentNullException(nameof(action));
              _action = action;
              _canExecute = canExecute ?? (x => true);
          }
          public CommandHandler(Action<object> action) : this(action, null)
          {
          }
      
          /// <summary>
          /// Wires CanExecuteChanged event 
          /// </summary>
          public event EventHandler CanExecuteChanged
          {
              add { CommandManager.RequerySuggested += value; }
              remove { CommandManager.RequerySuggested -= value; }
          }
      
          /// <summary>
          /// Forcess checking if execute is allowed
          /// </summary>
          /// <param name="parameter"></param>
          /// <returns></returns>
          public bool CanExecute(object parameter)
          {
              return _canExecute(parameter);
          }
      
          public void Execute(object parameter)
          {
              _action(parameter);
          }
          public void Refresh()
          {
              CommandManager.InvalidateRequerySuggested();
          }
      }
      

      在 xaml 中:

           <Button
          Command="{Binding ClickCommand}"
          CommandParameter="BtnEdit_Click"/>
      

      【讨论】:

        【解决方案4】:

        如果您特别喜欢将元素传递给视图模型,您可以使用

         CommandParameter="{Binding ElementName=ManualParcelScanScreen}"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-12-11
          • 1970-01-01
          • 1970-01-01
          • 2021-11-25
          • 1970-01-01
          • 1970-01-01
          • 2019-08-01
          相关资源
          最近更新 更多