在遵守 MVVM 模式的同时打开对话框似乎是常见问题之一(此处和其他地方)。我知道有像 MVVM light 这样的框架可以解决这个问题,但我目前正在开发一个非常小的个人项目,出于学习目的,我尝试自己完成大部分工作。
为了“强迫”自己注意引用,我决定从 UI 项目中提取视图模型并将它们放入单独的程序集中。 UI 项目引用 UI.ViewModels,但反之则不然。这导致我在打开(模式)对话框窗口时遇到问题。
很多人似乎都在使用DialogService
它的作用类似于:
internal class DialogService : IDialogService
{
public bool? OpenDialog(ViewModelBase vm)
{
Window window = new Window();
window.Content = vm;
return window.ShowDialog();
}
}
可以使用以下方法从视图模型类型推断相应的窗口内容DataTemplate
.
但在我的场景中,这不起作用,因为DialogService
需要在 UI 项目中,但我必须从视图模型中调用它。我当然可以滥用 DI/IoC 来注入IDialogService
实现到我的视图模型中,但这不是我想要做的。
有什么严格的方法可以让它发挥作用吗?
作为替代方案,我已将以下代码添加到我的ViewModelBase
:
public abstract class ViewModelBase : INotifyPropertyChanged
{
...
public event Action<ViewModelBase, Action<bool?>> Navigate;
protected virtual void OnNavigate(ViewModelBase vm, Action<bool?> callback)
{
Navigate?.Invoke(vm, callback);
}
}
显然,可能有更多的重载,其他参数,EventArgs
等等;我可能也应该将其放入界面中。但到目前为止,这还只是一个“想法”。
创建视图实例时(通过解析或例如在NavigationService
,见下文),我可以让NavigationService
订阅该事件并调用回调。这是一个有问题/坏主意吗?这样做有什么缺点?到目前为止(没有进行太多测试),我不喜欢的一件事是打开对话框后我无法继续下一行,但必须在回调代码中继续。这也使得通过阅读代码来跟踪程序流程变得更加困难。
任何意见都将不胜感激!这是一个非常有趣的话题,并且由于这些问题的许多答案都相当过时,我希望了解更多有关当前最佳实践的信息:)