我发现如果您有多个调用相同命令的控件,则需要 MSDN 的原始方式,否则每个控件都会新建自己的 RelayCommand。我没有意识到这一点,因为我的应用程序每个命令只有一个控件。
因此,为了简化 ViewModels 中的代码,我将创建一个命令包装类来存储(并延迟实例化)所有 RelayCommands 并将其放入我的 ViewModelBase 类中。这样用户就不必直接实例化 RelayCommand 或 DelegateCommand 对象,也不需要了解它们的任何信息:
/// <summary>
/// Wrapper for command objects, created for convenience to simplify ViewModel code
/// </summary>
/// <author>Ben Schoepke</author>
public class CommandWrapper
{
private readonly List<DelegateCommand<object>> _commands; // cache all commands as needed
/// <summary>
/// </summary>
public CommandWrapper()
{
_commands = new List<DelegateCommand<object>>();
}
/// <summary>
/// Returns the ICommand object that contains the given delegates
/// </summary>
/// <param name="executeMethod">Defines the method to be called when the command is invoked</param>
/// <param name="canExecuteMethod">Defines the method that determines whether the command can execute in its current state.
/// Pass null if the command should always be executed.</param>
/// <returns>The ICommand object that contains the given delegates</returns>
/// <author>Ben Schoepke</author>
public ICommand GetCommand(Action<object> executeMethod, Predicate<object> canExecuteMethod)
{
// Search for command in list of commands
var command = (_commands.Where(
cachedCommand => cachedCommand.ExecuteMethod.Equals(executeMethod) &&
cachedCommand.CanExecuteMethod.Equals(canExecuteMethod)))
.FirstOrDefault();
// If command is found, return it
if (command != null)
{
return command;
}
// If command is not found, add it to the list
command = new DelegateCommand<object>(executeMethod, canExecuteMethod);
_commands.Add(command);
return command;
}
}
这个类也被 ViewModelBase 类延迟实例化,因此没有任何命令的 ViewModel 将避免额外的分配。