2012-12-05 78 views
2

我有一个WinRT的应用程序,它是和使用caliburn.micro INavigationService(FrameAdapter)运行的很好。问题是我的应用程序中的所有页面都是整页,他们重复了很多视图xaml标记。我想这样做将有更大的“MasterPages”类型的结构,其中我有限定主要布局和包含ContentControl中,并使用所述导体图案切换出ContentControl中的内容物的壳的视图。过去我使用WPF和Silverlight取得了这种架构的成功,所以我认为它可以在WinRT中使用。卡利微WinRT的导航和指挥

问题是导航基础结构(使用FrameAdapter)和使用ContentControl绑定到导体的ActiveItem(如SimpleNavigation样本)的Conductor基础结构之间似乎存在断开。

在导体的场景我用ActivateItem:

ActivateItem(new MyViewModel()); 

但与INavigationService我用NavigateToViewModel:

navigationService.NavigteToViewModel<MyViewModel>(); 

和两个似乎并不远要连接我可以告诉。

我有一个想法是创建一个实现INavigationService和基本处理的子屏幕的创建和激活一个ConductorNavigationService。虽然看起来可能似乎并不很直截了当,所以我想我会检查,看看是否存在caliburn.micro做到这一点已经支持的方式。

+0

你有没有想过这个家伙?我看了一些在WPF中的东西,但它只是太多的工作来嘲笑它的快速回答 – Charleh

+0

我从来没有想过如何让它工作,但我改变了我的设计,使我有现在决定不实施主页面方案。如果你最终增加一个解决方案,我会验证它的工作原理并接受答案。感谢您的帮助! –

回答

3

好吧,我的理解可能有点紧张,因为我没有使用WinRT或INavigationService,但我认为Frame是RT的一部分,INavigationService提供了视图模型解析和导航框架。

我的另一个假设是,你的框架是一个有点像你的指挥已经,并且当你调用“导航()”在框架上,它只是替换新指定的内容框架的内容。如果是这种情况,那么CM正在查看视图模型的第一个分辨率。

既然你想要去的导体路径,这听起来像你想沟INavigationService的CM执行,只是推出自己来处理INavigationService导航方法(例如跳过Frame小号Navigate()法)。

快速查看CM源代码,发现所有NavigationService正在处理框架上的Navigate事件,然后执行VM解析并设置视图(导线可能已经这样做)。所有你需要做的是确保你的INavigationService实现只是加载指定的视图到外壳,而不是导航框架

你可能只需要盗取构造函数代码NavigationService和改变Navigate()执行,然后就打电话ActivateItem(x)其中x是VM的实例。 CM会照顾其余的(我认为CM boostrapper已经设置了你的根'Frame',所以你不需要担心这个)。

例如

的实现可能看起来更像这个(要记住,这只是我的东西放在一起,并且可以无耻的谎言!):

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()这需要一个视图模型,然后解决视图时,活页夹踢,但如果我的假设是好的,它应该工作

+0

感谢您的支持!我尝试过这种方法,但还没有完全实现。证明取得对改变孩子观点所需的框架的参考是困难的。另外获取对DataContext的引用也没有证明过于直接。 –

+0

我会把东西放在一起在WPF中,看看我能否以类似的方式工作 - 我只在Win7上,所以我不能使用WinRT。如果我能在WPF中找到一些工作,我相信它可以为您提供一个起点。我会尝试模拟Frame和Page类 – Charleh