2

I have noticed that I am repeating a lot of code when implementing Commands on ViewModels for a MVVM-WPF scenario. The standard implementation, as shown below, consists of a public readonly field of type ICommand, a private DelegateCommand field and a method for the execution logic. DelegateCommand gets initialized in the ICommands get-accessor.

How can this approach be condensed, considering the repetition for every command?

private DelegateCommand saveCommand;
private DelegateCommand commandClearInputFileList;
private DelegateCommand commandInputFilesDeleteSelected;

public ICommand SaveCommand {
    get {
        if (saveCommand == null) {
            saveCommand = new DelegateCommand(CommitDataBasePush);
        }
        return saveCommand;
    }
}

public ICommand CommandClearInputFileList {
    get {
        if (commandClearInputFileList == null) {
            commandClearInputFileList = new DelegateCommand(InputFilesClear);
        }
        return commandClearInputFileList;
    }
}

public ICommand CommandInputFilesDeleteSelected {
    get {
        if (commandInputFilesDeleteSelected == null) {
            commandInputFilesDeleteSelected = new DelegateCommand(InputFilesDeleteSelected);
        }
        return commandInputFilesDeleteSelected;
    }
}
4

3 回答 3

4

除了空合并运算符之外,您还可以使用延迟加载

private Lazy<DelegateCommand> _cmd = new Lazy<DelegateCommand>(() => new DelegateCommand(InputFilesClear) );

public ICommand CommandClearInputFileList { get { return _cmd.Value; } }

就个人而言,我已经放弃了命令,转而支持Caliburn.Micro框架提供的约定。上面的命令将简单地替换为公共方法。

于 2013-01-30T22:44:13.043 回答
4

就个人而言,我越来越喜欢这种风格:

    private DelegateCommand saveCommand;
    public ICommand SaveCommand 
    {
        get 
        {
            return saveCommand ?? 
                (saveCommand = new DelegateCommand(CommitDataBasePush));
        }
    }

或者,使用更少的代码行:

    private DelegateCommand saveCommand;
    public ICommand SaveCommand 
        => saveCommand ?? (saveCommand = new DelegateCommand(CommitDataBasePush));
于 2013-01-30T22:40:52.120 回答
2

DelegateCommand您可以将及其延迟初始化包装到一个简单的自定义命令类中,该类实现ICommand. 我称之为它LazyCommand,它的用法很简单:

// Declaration
public ICommand SomeCommand { get; private set; }

// Definition
SomeCommand = new LazyCommand(ExecuteSomeCommandMethod);

该类LazyCommand如下所示:

public class LazyCommand : ICommand
{
    private readonly Lazy<DelegateCommand> _innerCommand;

    public LazyCommand(Action executeAction, Func<bool> canExecuteAction = null)
    {
        _innerCommand = canExecuteAction == null ? 
            new Lazy<DelegateCommand>(() => new DelegateCommand(executeAction)): 
            new Lazy<DelegateCommand>(() => new DelegateCommand(executeAction, canExecuteAction));
    }

    public bool CanExecute(object parameter)
    {
        return _innerCommand.Value.CanExecute();
    }

    public void Execute(object parameter)
    {
        _innerCommand.Value.Execute();
    }

    public event EventHandler CanExecuteChanged
    {
        add { _innerCommand.Value.CanExecuteChanged += value; }
        remove { _innerCommand.Value.CanExecuteChanged -= value; }
    }

    public void RaiseCanExecuteChanged()
    {
        _innerCommand.Value.RaiseCanExecuteChanged();
    }
}

请让我知道这对你有没有用。干杯...

于 2013-01-31T09:38:16.290 回答