WPF MVVM:从 ViewModel 中隔离命令逻辑

WPF MVVM: Isolating command logic from ViewModel

我正在使用 Prism 迈出 WPF 和 MVVM 的第一步。到目前为止,还不错,但有一些我似乎无法实现的设计方法。

在我的 UI 中,我有两种打开文件的方法。有一个可以单击的浏览按钮,将出现一个“打开文件”对话框,提示输入文件并将其打开。您也可以将文件拖放到 UI 顶部,它会打开它。

为了隔离浏览逻辑,我为它创建了一个命令。出现第一个代码味道,我需要 ICommand 接口未公开的结果。

public class BrowseFileCommand: ICommand
{
    public string ExecutionResult { get; private set; }

    public bool CanExecute(object parameter) => true;

    public void Execute(object parameter)
    {
        var openFileDialog = new OpenFileDialog()
        {
            Multiselect = false,
            Filter = "Event log files (*.evtx)|*.evtx"
        };

        ExecutionResult = openFileDialog.ShowDialog() == true ? openFileDialog.FileName : null;
    }

    public event EventHandler CanExecuteChanged;
}

然后,在我的 ViewModel class 中,我可以这样调用它:

public class MainWindowViewModel: BindableBase
{
    public DelegateCommand BrowseFileCommand { get; set; }

    public MainWindowViewModel()
    {
        BrowseFileCommand = new DelegateCommand(BrowseAndOpenFile, () => _browseFileCommand.CanExecute(null));
        // ...
    }

    private BrowseFileCommand _browseFileCommand = new BrowseFileCommand();

    private void BrowseAndOpenFile()
    {
        _browseFileCommand.Execute(null);
        var fileName = _browseFileCommand.ExecutionResult;
        if (!string.IsNullOrWhiteSpace(fileName))
            OpenFile(fileName);
    }

    // ...
}

这里有一些其他的代码味道:

有什么好的方法可以让我将逻辑完全隔离到命令/class?

注意以下设计限制:

ICommand 主要仅用于绑定到 UI。它并不意味着用于分离行为并从普通代码中调用。这就是为什么您的代码有异味。

相反,使用正常的语言特性(方法、继承、组合等)来分离关注点,并仅使用 ICommand 命令将特定操作公开给 UI 以进行绑定。