棱镜区域切换与容器实例同步

时间:2017-03-23 22:39:07

标签: c# wpf unity-container prism regions

我在WPF中使用具有(Prism)区域“MainViewRegion”的MainWindow。这会根据用户所需的视图进行切换,当它发生时,MainWindow会调整大小以捕捉嵌入视图的新维度。

我有一些代码可以在Region切换后让桌面在桌面上完全可见。这是代码:

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”代码总是关闭。

我错过了什么?

2 个答案:

答案 0 :(得分:1)

通常,如果您有一段代码在某个事件上执行,并且您需要确保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未切割芥末的情况。)

答案 1 :(得分:0)

感谢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()的callback参数中调用Dispatcher,但没有它就无法工作。