Prism 区域切换与容器实例同步
Prism Region Switching and Synchronizing with Container Instance
我正在 WPF 中使用具有 (Prism) 区域 "MainViewRegion" 的 MainWindow。这会根据用户所需的视图进行切换,当它切换时,主窗口会调整大小以捕捉到嵌入视图的新尺寸。
我有一些代码可以在区域切换后使 window 在桌面上完全可见。这是代码:
private void WindowModeChange(string uri)
{
IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion];
if (mviewRegion == null) return;
regionManager.RequestNavigate(mviewRegion.Name, new Uri(uri, UriKind.Relative));
//Get the MainWindow instance from the container
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
//Make sure the entire window is visible onscreen
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc);
}
问题是 "uc" 变量将始终等于区域更改之前的 MainWindow 参数。 "uc" 总是比我想要的落后一步,所以 "snap-to" 代码总是关闭。
我错过了什么?
感谢 Grx70 在我的问题的评论中,他给了我解决方案。该方法的主体现在显示为:
IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion];
if (mviewRegion == null) return;
mviewRegion.RequestNavigate(new Uri(uri, UriKind.Relative), (x =>
{
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
uc.Dispatcher.Invoke(() => ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc), DispatcherPriority.Loaded);
}));
我不确定为什么我必须在 RequestNavigate() 的回调参数中调用 Dispatcher,但没有它就无法工作。
通常当你有一段代码在某个事件上执行时,你需要确保 UI 已经在某种程度上响应了那个事件,你最好的选择是使用 Dispatcher
推迟执行。根据您提供的代码判断,UI 更改是由 regionManager.RequestNavigate
调用触发的。现在我无法向您指出一段说明该内容的文档,但我从经验中知道框架将 异步处理此请求 ,即控制权将返回给您的方法(允许它继续)在此请求引起的所有工作完成之前(因此你的问题)。这是(据我所知)框架通过使用上述 Dispatcher
.
在内部完成的
根据您需要框架在多大程度上处理触发的更改,您应该使用适当的 DispatcherPriority
枚举值来确保在执行代码后完成某些事情。根据您的问题,我认为 DispatcherPriority.Loaded
是一个不错的选择(根据文档,调度程序将在呈现 UI 之后执行此类代码(这对您来说是至关重要的条件),但在任何用户输入之前处理)。我个人倾向于将优先级最大化,直到它停止工作(可能避免由例如用户输入引起的一些意外行为)。
因此,对代码的这种修改应该足以实现您的目标:
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
uc.Dispatcher.InvokeAsync(() =>
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc),
DispatcherPriority.Loaded);
现在我注意到你最终选择了 Dispatcher.Invoke
而不是 Dispatcher.InvokeAsync
- 我想你的情况没问题,因为它是你方法中的最后一条指令,但通常安全的方法是使用 Dispatcher.InvokeAsync
(我亲身经历过 Dispatcher.Invoke
没有切芥末的情况)。
我正在 WPF 中使用具有 (Prism) 区域 "MainViewRegion" 的 MainWindow。这会根据用户所需的视图进行切换,当它切换时,主窗口会调整大小以捕捉到嵌入视图的新尺寸。
我有一些代码可以在区域切换后使 window 在桌面上完全可见。这是代码:
private void WindowModeChange(string uri)
{
IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion];
if (mviewRegion == null) return;
regionManager.RequestNavigate(mviewRegion.Name, new Uri(uri, UriKind.Relative));
//Get the MainWindow instance from the container
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
//Make sure the entire window is visible onscreen
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc);
}
问题是 "uc" 变量将始终等于区域更改之前的 MainWindow 参数。 "uc" 总是比我想要的落后一步,所以 "snap-to" 代码总是关闭。
我错过了什么?
感谢 Grx70 在我的问题的评论中,他给了我解决方案。该方法的主体现在显示为:
IRegion mviewRegion = regionManager.Regions[RegionNames.MainViewRegion];
if (mviewRegion == null) return;
mviewRegion.RequestNavigate(new Uri(uri, UriKind.Relative), (x =>
{
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
uc.Dispatcher.Invoke(() => ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc), DispatcherPriority.Loaded);
}));
我不确定为什么我必须在 RequestNavigate() 的回调参数中调用 Dispatcher,但没有它就无法工作。
通常当你有一段代码在某个事件上执行时,你需要确保 UI 已经在某种程度上响应了那个事件,你最好的选择是使用 Dispatcher
推迟执行。根据您提供的代码判断,UI 更改是由 regionManager.RequestNavigate
调用触发的。现在我无法向您指出一段说明该内容的文档,但我从经验中知道框架将 异步处理此请求 ,即控制权将返回给您的方法(允许它继续)在此请求引起的所有工作完成之前(因此你的问题)。这是(据我所知)框架通过使用上述 Dispatcher
.
根据您需要框架在多大程度上处理触发的更改,您应该使用适当的 DispatcherPriority
枚举值来确保在执行代码后完成某些事情。根据您的问题,我认为 DispatcherPriority.Loaded
是一个不错的选择(根据文档,调度程序将在呈现 UI 之后执行此类代码(这对您来说是至关重要的条件),但在任何用户输入之前处理)。我个人倾向于将优先级最大化,直到它停止工作(可能避免由例如用户输入引起的一些意外行为)。
因此,对代码的这种修改应该足以实现您的目标:
var uc = container.Resolve<MainWindow>(InstanceNames.MainWindowView);
uc.Dispatcher.InvokeAsync(() =>
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(uc),
DispatcherPriority.Loaded);
现在我注意到你最终选择了 Dispatcher.Invoke
而不是 Dispatcher.InvokeAsync
- 我想你的情况没问题,因为它是你方法中的最后一条指令,但通常安全的方法是使用 Dispatcher.InvokeAsync
(我亲身经历过 Dispatcher.Invoke
没有切芥末的情况)。