2016-06-14 186 views
0

我给我的WPF和MVVM的第一个步骤,使用Prism隔离命令逻辑。到目前为止,这么好,但有一种我无法实现的特定设计方法。WPF MVVM:从视图模型

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

为了分离浏览逻辑,I为它创建的命令。出现第一个代码异味,我需要一个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() ,因为棱镜的DelegateCommand允许它。
  • 我仍然留在视图模型,这正是我想避免在首位的“胶合”的逻辑。

有没有一种很好的方法可以将逻辑完全隔离到Command/class?

请注意以下设计限制:

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

回答

0

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

取而代之,使用正常的语言功能(方法,继承,组合等)来分隔关注点,并使用命令向UI展示绑定的特定操作。

+0

这是否仍适用于完全依赖于用户界面,像我的“BrowseFile”的行为? – Alpha

+0

@Alpha号如果你想分离一些不同的概念,然后创建自己的抽象。 – Euphoric

+0

如果我理解正确,那么你会直接在ViewModel中保留“BrowseFile”之类的东西,但只要这变得稍微复杂一些,就可以将这种复杂性分离出来,放到你自己的类中。这将成为你从VM调用的东西。同样,对于所有事情来说,管理结果和管理调用仍然会留在虚拟机内部,对吧? – Alpha