如果您想使用没有额外窗口的嵌入式对话框,您可以使用 Prism 的 RegionManager 来实现概述的行为。诀窍是将弹出区域与视觉树中的主要区域平行放置:
<Grid>
<ContentControl cal:RegionManager.RegionName="MainRegion" IsEnabled={Binding IsNoPopUpActive} />
<ContentControl cal:RegionManager.RegionName="PopUpRegion"/>
</Grid>
现在使用 RegionManager 将视图“A”放入“MainRegion”。创建一个类似于 IPopUpDialogController 的控制器类。它应该负责按需将您的视图“B”(或应用程序中的任何其他 PopUpView)放入“PopUpRegion”。此外,它应该控制一个标志,指示启用或禁用底层“MainRegion”。这样,在弹出窗口关闭之前,用户将无法使用视图“A”中的控件。
这甚至可以通过在将帧推送到 Dispatcher 之前使用 ComponentDispatcher.PushModal() 以模态方式完成。但是,我建议避免使用模态对话框。
更新:根据评论中的要求,可以在后备视图模型中实现 IsNoPopUpActive。在那里,您可以将其链接到 RegionManager 的弹出区域的视图集合:
public bool IsNoPopUpActive
{
get { return _regionManager.Regions["PopUpRegion"].Views.Count() == 0; }
}
请记住在修改视图集合(添加/删除弹出窗口)后立即触发 PropertyChanged 事件。
仅供参考:现在我避免在后台禁用控件,而是插入一个透明面板。这样可以避免单击背景控件。但是,这不处理键盘输入(制表符到控件)。要修复键盘输入,您需要确保键盘焦点被困在弹出窗口中(关于 WPF 焦点概念的 MSDN)。
将以下焦点属性添加到弹出区域应该可以解决问题:
KeyboardNavigation.DirectionalNavigation="None"
KeyboardNavigation.ControlTabNavigation="None"
KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.TabIndex="-1"