WPF MVVM:从ViewModel隔离命令逻辑

时间:2016-06-14 00:10:04

标签: c# wpf mvvm prism

我使用Prism给出了WPF和MVVM的第一步。到目前为止,这么好,但是我似乎无法实现某种设计方法。

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

为了隔离Browse逻辑,我为它创建了一个命令。出现第一个代码气味,我需要一个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类中,我可以像这样调用它:

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);
    }

    // ...
}

以下是一些其他代码气味:

  • 我需要在另一个命令中包含我的命令,该命令将在执行
  • 后从中读取值
  • 我没有正确地联系CanExecuteChanged事件(我不需要,但是如果我要嵌套命令,我似乎应该这样做)
  • 使用null参数调用CanExecute()(据我所见,这是"常见",但仍然是代码味道给我),因为ICommand需要它
  • 在没有参数的情况下调用CanExecute(),因为Prism的DelegateCommand允许它。
  • 我仍然离开了#34;胶合" ViewModel中的逻辑,这是我想要首先避免的。

我有一个好方法可以将逻辑完全隔离到Command / class吗?

请注意以下设计限制:

  • 这些的行为属于UI逻辑:BrowseCommand严格依赖于正在使用的UI技术
  • 某些命令可以在操作之间共享。注意OpenFile是浏览文件后的第二步,但是Drop的第一步(此处未显示)。

1 个答案:

答案 0 :(得分:0)

ICommand主要用于仅绑定到UI。它并不意味着用于分离行为并从正常代码中调用。这就是为什么你的代码闻到了。

相反,使用常规语言功能(方法,继承,组合等......)来分离关注点,并使用ICommand命令向UI公开特定操作以进行绑定。