RelayCommand 最佳实践
RelayCommand best practice
我正在使用 RelayCommands
(它们在单独的 class 中)大约一个月了,我感觉它们在声明时有点笨拙。下面我有 3 种方法可以想到如何声明 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
,维护每种方法的概览有多难。
- 我希望将来在 Windows 7、8 和 10 上发布我的应用程序。
RelayCommands
如果我只使用 .NET4.5,是否有任何限制我必须考虑?
- 除了
RelayCommands
我还找到了这个项目:Caliburn-Micro。它允许您执行类似以下代码的操作。有谁知道与 RelayCommands
相比,这在性能方面有多好?这只是一个额外的问题,不需要回答就可以将 post 标记为答案。
Xaml(查看)
<Button x:Name="Login" Content="Log in" />
视图模型
public bool CanLogin(string username, string password)
{
return !String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password);
}
public string Login(string username, string password)
{
...
}
我同意 Krowi 的观点,第一种方法更容易阅读。但我会把你的中继命令放到它自己的 class 中,这样你就可以重新使用它:
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
}
参考以下答案。
- 声明和构造 ICommand 的最佳方法是什么?
这是我的方法之一还是有更简单的方法? 答:可以
采取结合的方式。如果您的执行方法非常少,您
可以使用 RelayCommnd 否则你可以实现你自己的 ICommand
一个单独的 class。这将提高您的视图模型的可读性
以及代码的模块化。
- 考虑到单个 ViewModel 中有 50 多个 ICommand,维护每种方法的概览有多难。
Ans:覆盖在 Ans 1
- 我希望将来在 Windows 7、8 和 10 上发布我的应用程序。如果我只使用 .NET4.5,我必须考虑 RelayCommands 有什么限制吗?
回答:我在 Windows 7 或 8 中没有看到任何限制,但不确定 Windows 10。
- 除了RelayCommands,我还找到了这个项目:Caliburn-Micro。它允许您执行类似以下代码的操作。有谁知道与 RelayCommands 相比,这在性能方面有多好?这只是一个额外的问题,不需要回答就可以将 post 标记为答案。
Ans:我不确定Caliburn-Micro 中RelayCommands 的源代码。但是如果它使用 CommandManager 来实现 CanExecute 功能。然后命令管理器将在所有用户输入更改时被触发,因此如果 CanExecute 方法中有一些繁重的逻辑将导致性能问题。 参考 Are there any performance implications with 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
实例。
我正在使用 RelayCommands
(它们在单独的 class 中)大约一个月了,我感觉它们在声明时有点笨拙。下面我有 3 种方法可以想到如何声明 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
,维护每种方法的概览有多难。 - 我希望将来在 Windows 7、8 和 10 上发布我的应用程序。
RelayCommands
如果我只使用 .NET4.5,是否有任何限制我必须考虑? - 除了
RelayCommands
我还找到了这个项目:Caliburn-Micro。它允许您执行类似以下代码的操作。有谁知道与RelayCommands
相比,这在性能方面有多好?这只是一个额外的问题,不需要回答就可以将 post 标记为答案。
Xaml(查看)
<Button x:Name="Login" Content="Log in" />
视图模型
public bool CanLogin(string username, string password)
{
return !String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password);
}
public string Login(string username, string password)
{
...
}
我同意 Krowi 的观点,第一种方法更容易阅读。但我会把你的中继命令放到它自己的 class 中,这样你就可以重新使用它:
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
}
参考以下答案。
- 声明和构造 ICommand 的最佳方法是什么? 这是我的方法之一还是有更简单的方法? 答:可以 采取结合的方式。如果您的执行方法非常少,您 可以使用 RelayCommnd 否则你可以实现你自己的 ICommand 一个单独的 class。这将提高您的视图模型的可读性 以及代码的模块化。
- 考虑到单个 ViewModel 中有 50 多个 ICommand,维护每种方法的概览有多难。 Ans:覆盖在 Ans 1
- 我希望将来在 Windows 7、8 和 10 上发布我的应用程序。如果我只使用 .NET4.5,我必须考虑 RelayCommands 有什么限制吗? 回答:我在 Windows 7 或 8 中没有看到任何限制,但不确定 Windows 10。
- 除了RelayCommands,我还找到了这个项目:Caliburn-Micro。它允许您执行类似以下代码的操作。有谁知道与 RelayCommands 相比,这在性能方面有多好?这只是一个额外的问题,不需要回答就可以将 post 标记为答案。 Ans:我不确定Caliburn-Micro 中RelayCommands 的源代码。但是如果它使用 CommandManager 来实现 CanExecute 功能。然后命令管理器将在所有用户输入更改时被触发,因此如果 CanExecute 方法中有一些繁重的逻辑将导致性能问题。 参考 Are there any performance implications with 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
实例。