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的第一步(此处未显示)。
这是否仍适用于完全依赖于用户界面,像我的“BrowseFile”的行为? – Alpha
@Alpha号如果你想分离一些不同的概念,然后创建自己的抽象。 – Euphoric
如果我理解正确,那么你会直接在ViewModel中保留“BrowseFile”之类的东西,但只要这变得稍微复杂一些,就可以将这种复杂性分离出来,放到你自己的类中。这将成为你从VM调用的东西。同样,对于所有事情来说,管理结果和管理调用仍然会留在虚拟机内部,对吧? – Alpha