我已经使用RelayCommands
(它们在一个单独的类中)大约一个月了,我觉得它们在声明时有点笨拙。下面我有三种方法可以考虑如何声明RelayCommand
。
在第一种情况下,我声明我的ICommand
,然后在加载ViewModel时,我构造指向代码中某个方法的RelayCommand
。
public class MyViewModel
{
public ICommand MyCommand { get; private set; }
public MyViewModel()
{
MyCommand = new RelayCommand(MyMethod, CanMyMethod);
}
private void MyMethod()
{
// Do something here ...
}
private bool CanMyMethod()
{
return string.IsNullOrEmpty(MyString) ? false : true;
}
}
第二种方法是同时做所有事情。
public ICommand MyCommand
{
get
{
return new RelayCommand(
() =>
{
// Do something here ...
},
() =>
string.IsNullOrEmpty(MyString) ? false : true);
}
}
现在,我计划在某个ViewModel中编写一个具有相当多Commands
的应用程序。我也不能将ViewModel拆分为更小的ViewModel,因为所有的controls
都必须协同工作。
所以我的问题是:
- 声明和构造
ICommands
的最佳方法是什么?这是我的方法之一,还是有更简单的方法 - 考虑到单个ViewModel中有50多个
ICommands
,维护每种方法的概述有多难 - 我希望将来能在Windows7、8和10上发布我的应用程序。如果我只使用.NET4.5,
RelayCommands
有什么限制吗 - 除了
RelayCommands
,我还发现了这个项目:Caliburn Micro。它允许您执行类似以下代码的操作。有人知道与RelayCommands
相比,这在性能方面有多好吗?这只是一个额外的问题,不需要回答就可以将帖子标记为答案
Xaml(查看)
<Button x:Name="Login" Content="Log in" />
ViewModel
public bool CanLogin(string username, string password)
{
return !String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password);
}
public string Login(string username, string password)
{
...
}
请参阅以下答案。
- 声明和构建ICommands的最佳方法是什么?这是我的方法之一,还是有更简单的方法回答:你可以采取联合方法。如果您的execute方法非常小可以使用RelayCommand,否则您可以在中实现自己的ICommand一个单独的类。这将提高视图模型的可读性,因为以及代码的模块化
- 考虑到单个ViewModel中有50多个ICommands,维护每种方法的概述有多难。答案:答案1中的封面
- 我希望将来能在Windows 7、8和10上发布我的应用程序。如果我只使用.NET4.5,那么RelayCommands有什么限制吗?回答:我看不到Windows 7或8有任何限制,但不确定Windows 10。
- 除了RelayCommands,我还发现了这个项目:Caliburn Micro。它允许您执行类似以下代码的操作。有人知道与RelayCommands相比,这在性能方面有多好吗?这只是一个额外的问题,不需要回答就可以将帖子标记为答案。回答:我不确定Caliburn Micro中RelayCommands的源代码。但是如果它使用CommandManager来实现CanExecute功能。然后,命令管理器将在所有用户输入更改时被触发,因此,如果CanExecute方法中有一些重逻辑,这将导致性能问题请参阅CanExecuteCommand是否对性能有任何影响
这是我喜欢的模式,它基本上是方法1:的变体
public class MyViewModel
{
private readonly RelayCommand myCommand;
public MyViewModel()
{
this.myCommand = new RelayCommand(this.DoStuff, () => ...);
}
public ICommand MyCommand
{
get { return this.myCommand; }
}
private void DoStuff() { ... }
}
这样做的优点是在RelayCommand实现中保留了额外的方法(如RaiseCanExecuteChanged
),以便在视图模型中使用,但只向消费者公开一个ICommand
实例。
我同意Krowi的观点,第一种方法更容易阅读。但我会把你的中继命令放在自己的类中,这样你就可以重用它:
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
#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
}