【问题标题】:MVVM - Commands on special eventsMVVM - 特殊事件的命令
【发布时间】:2013-11-09 23:57:35
【问题描述】:

我尝试将命令与 MVVM - 模式一起使用,但我不知道如何将命令“绑定”到特殊事件,例如MouseUp 或 MouseEnter。如何做到这一点?

【问题讨论】:

  • 使用来自 MVVM 灯的 EventToCommand 行为:galasoft.ch/mvvm
  • 如果你不想使用 MVVM Light,Blend 也有类似的行为。
  • @Tico - 你能解释一下这种行为以及如何使用它吗?
  • @ImmortalBlue 在 Blend 上打开你的项目。转到Behaviors 有一个叫InvokeCommandAction。它所做的是将事件“转换”为命令。作为示例,我将展示我所做的(我将使用 pastebin:pastebin.com/3mbxzagp)
  • 请检查答案或向我们添加更多帮助

标签: c# .net wpf mvvm icommand


【解决方案1】:

首先,您应该在 ViewModel 中定义 ICommnad 属性。

public ICommand MouseUpCommand
{
    get 
    {
        if (this.mouseUpCommand == null)
        {
            this.mouseUpCommand = new RelayCommand(this.OnMouseUp);
        }

        return this.mouseUpCommand;
    }
}

private void OnMouseUp()
{
    // Handle MouseUp event.
}


你可以找到很多ICommand 的实现。其中之一:

public class RelayCommand : ICommand
{
    public RelayCommand(Action<object> execute)
    {
         this._execute = execute;
         ...
    }

    ...

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
} 


然后添加事件触发器,在其中调用您的Command:

<i:EventTrigger EventName="MouseUp">
      <i:InvokeCommandAction Command="{Binding MouseUpCommand}"/>
</i:EventTrigger>

【讨论】:

  • 如果我不使用 ICOMMAND、relaycommand 并且只是在各自视图的代码隐藏文件中声明 mousedown,这可以被视为 MVVM 实现吗?
  • @Sangram 不。任何时候你使用后面的代码 - 它都不是正确的 MVVM。显然,没有ViewModel,就不可能有 MVVM。
  • @AnatoliiG,这绝对是废话 - MVVM 旨在减少后面的代码,但说后面的代码 = 不是 MVVM 是不正确的。见channel9.msdn.com/blogs/kreekman/… 01:01:00
  • 另外,你的视图模型应该是 UI 不可知的,(虽然我明白这只是一个例子,很明显!)但你应该在命令级别将事物标记为功能级别。例如,该命令应称为 RefreshMenu 或任何它在功能上绑定的名称,因此如果您想从其他地方调用该命令,您最终不会得到指向“MouseUp”命令的菜单项。
  • @ImmortalBlue 再次阅读我的评论。我刚刚告诉过它不是“正确的”MVVM。如果您对 xaml 和 MVVM 有一定的经验,那么您应该同意,每次看到代码隐藏时,它都是以快速而肮脏的方式完成的。通常不可测试、难以重构、维护等。
【解决方案2】:

请阅读以下page的EventToCommand

【讨论】:

    【解决方案3】:

    看WPF Binding UI events to commands in ViewModel。

    为此,您需要 System.Windows.Interactivity.dll,您可以从 Nuget 获得它

    【讨论】:

      【解决方案4】:

      在此处完成@AnatoliiG 帖子是RelayCommand 类的实现和示例用法。

      代码:

      public class RelayCommand : ICommand
      {
      #region Fields
       
      readonly Action<object> _execute;
      readonly Predicate<object> _canExecute;
       
      #endregion // Fields
       
      #region Constructors
       
      public RelayCommand(Action<object> execute)
      : this(execute, null)
      {
      }
       
      public RelayCommand(Action<object> execute, Predicate<object> canExecute)
      {
      if (execute == null)
      throw new ArgumentNullException("execute");
       
      _execute = execute;
      _canExecute = canExecute;
      }
      #endregion // Constructors
       
      #region ICommand Members
       
      [DebuggerStepThrough]
      public bool CanExecute(object parameter)
      {
      return _canExecute == null ? true : _canExecute(parameter);
      }
       
      public event EventHandler CanExecuteChanged
      {
      add { CommandManager.RequerySuggested += value; }
      remove { CommandManager.RequerySuggested -= value; }
      }
       
      public void Execute(object parameter)
      {
      _execute(parameter);
      }
       
      #endregion // ICommand Members
      }
      

      用法:

      // To use this class within your viewmodel class:
      RelayCommand _myCommand;
      public ICommand MyCommand
      {
      get
      {
      if (_myCommand == null)
      {
      _myCommand = new RelayCommand(p => this.DoMyCommand(p),
      p => this.CanDoMyCommand(p) );
      }
      return _myCommand;
      }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-21
        • 2011-09-02
        • 2012-06-17
        • 1970-01-01
        • 2023-03-28
        • 2011-06-28
        • 2014-11-06
        • 1970-01-01
        相关资源
        最近更新 更多