2012-12-05 28 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