当 root/main/shell 视图模型实现一种DialogService接口时,需要显示对话框的所有其他视图模型最终都会依赖于根视图模型。有时这可能是不可取的,例如,如果它可能导致依赖循环:
DialogService (aka RootViewModel ) -> SomeViewModel -> RootViewModel。
打破这种依赖链(并实际上反转它)的更复杂的方法如下:
- 实现检测
Window.OnSourceInitialized
事件并将其附加到主视图Window
组件的行为。这是当窗口句柄可用时触发的事件。一旦发生事件,行为将通知通过附加属性传入的一些处理程序:
<my:WindowSourceBehavior InitListener="{Binding WindowListener}" />
public class WindowSourceBehavior : Behavior<Window>
{
// ...
// boilerplate code for IWindowListener InitListener dependency property
// ...
attachedWindow.SourceInitialized += (sender, evt) =>
{
// ...
InitListener.SourceInitialized(sender as Window);
}
}
- DialogService根据行为请求公开一个处理程序或接口:
public class DialogService : IWindowListener
{
// ...
public void SourceInitialized(Window rootWindow) { /* ... */ }
}
- 在根视图模型中,(间接)将DialogService作为依赖项注入。在构造期间,将视图模型绑定属性 ,
WindowListener
设置为DialogService处理程序/接口:
public MainViewModel(IWindowListener dialogServiceInDisguise)
{
WindowListener = dialogServiceInDisguise;
}
public IWindowListener WindowListener { get; private set; }
这样做,DialogService 能够获得根窗口,并且无论哪个视图模型需要显示一个对话框,都不会创建对主视图模型的(n 间接)依赖。