好的,我的理解可能有点紧张,因为我没有使用过 WinRT 或INavigationService
但我认为Frame
它是 RT 的一部分,并INavigationService
为帧提供视图模型分辨率和导航。
我的另一个假设是你的框架有点像你的指挥,当你在框架上调用'Navigate()'时,它只是用新指定的内容替换框架的内容。如果是这种情况,那么 CM 正在为视图模型执行视图优先分辨率。
既然你想走指挥路线,听起来你想放弃 CM 实现,INavigationService
只是滚动你自己来处理INavigationService
导航方法(例如跳过Frame
sNavigate()
方法)。
快速查看 CM 源代码会发现,所有NavigationService
正在做的事情就是处理Navigate
帧上的事件,然后进行 VM 解析并设置视图(指挥可能已经这样做了)。您需要做的就是确保您的INavigationService
实现只是将指定的视图加载到外壳中,而不是在框架中导航
您可能只需要窃取构造函数代码NavigationService
并更改 的实现Navigate()
,然后只需调用ActivateItem(x)
您的 shell,其中 x 是 VM 的实例。CM 将负责其余的工作(我认为 CM boostrapper 也已经设置了您的根“框架”,因此您不必担心这一点)。
例如
一个实现可能看起来更像这样(请记住,这只是我拼凑起来的东西,可能是赤裸裸的谎言!):
public class NewFrameAdapter : INavigationService
{
private readonly Frame frame;
private readonly IConductActiveItem shell;
private event NavigatingCancelEventHandler ExternalNavigatingHandler = delegate { };
public NewFrameAdapter(Frame frame)
{
this.frame = frame;
// Might want to tighten this up as it makes assumptions :)
this.shell = (frame as FrameworkElement).DataContext as IConductActiveItem;
}
public bool Navigate(Type pageType)
{
// Do guardclose and deactivate stuff here by looking at shell.ActiveItem
// e.g.
var guard = shell.ActiveItem as IGuardClose;
if (guard != null)
{
var shouldCancel = false;
guard.CanClose(result => { shouldCancel = !result; });
if (shouldCancel)
{
e.Cancel = true;
return;
}
}
// etc
// Obviously since the guard is probably async (assume it is, if not you are ok to continue!) you'd have to not call this code right
// here but I've just stuck it in here as an example
// edit: looking at the code above (the guard code) it looks like this is all sync so the below code should be fine
// You might get away with calling shell.ActivateItem(pageType) as I'm not sure
// if the viewmodel binder in RT would resolve this all for you, but if it doesnt...
// Init the view and then resolve the VM type
ViewLocator.InitializeComponent(pageType);
var viewModel = ViewModelLocator.LocateForView(pageType);
// Activate the VM in the shell)
shell.ActivateItem(viewModel);
}
以自己的方式滚动应该不会太难。这对你有帮助吗?
那么您的 XAML 将非常简单:
<Frame blah blah>
<SomeStaticContent />
<ContentControl x:Name="ActiveItem" /> <!-- The dynamic bit... -->
<SomeMoreStaticContent />
</Frame>
我认为这可能是视图优先和视图模型优先的混合体,因为您的根Frame
将使用视图优先,而您的指挥将使用ActivateItem()
哪个视图模型,然后在绑定器启动时解析视图,但如果我的假设没问题,它应该可以工作