2014-01-22 12 views
0

我創建了一個基於Caliburn.Micro(alpha2)的WinRT 8.1應用程序,並且正在爲它實現一個簡單的狀態管理機制。它所需要的只是爲其兩個或三個頁面中的每一個保存一對名稱/值對,並在恢復時恢復當前頁面。所以我正在使用下面總結的戰略;因爲看起來CM/WinRT沒有預定義的機制,所以得到任何有關這方面的社區建議都很有意思,或者這對希望像我這樣的RT新手有用。 1)我定義了一個接口IHaveSimpleState),由具有一些簡單狀態的VM來實現以進行保存和恢復。狀態由一個字典表示,其中每個值都是一個字符串,表示任何序列化的值,接口只有2個方法,一個用於將狀態保存到此字典中,另一個用於從字典中恢復狀態。我所有的有狀態虛擬機(每個對應一個視圖)都實現了這一點。在Caliburn Micro WinRT 8.1中管理簡單狀態:導航到之前的活動頁面

2)在我應用的.cs(從Caliburn.Application派生),我創建了一個List<WeakReference<IHaveSimpleState>>保留所有的虛擬機需要國家管理的軌道:在GetInstance覆蓋該實例的虛擬機(使用CM簡單的容器),我添加到此列表中每個新生成的實例IHaveSimpleState

3)節約狀態:在應用OnSuspending覆蓋,通過所有的虛擬機我循環在此列表中,並調用其SaveState方法收集有關其狀態的數據在一個共同的字典。一旦循環完成,我得到ApplicationData.Current.LocalSettings,我將這些數據複製到它的Values字典中,從而有效地保存它們。

4)恢復狀態:在該應用OnResuming倍率和在OnActivated倍率(在後一種情況下,僅當args.PreviousExecutionState等於Running,即,應用程序不是由用戶終止也不崩潰),I調用一個ResumeState方法循環訪問列表中的所有虛擬機,並調用它們的LoadState方法從應用程序數據本地設置加載狀態。

所有這些看起來都很好,我只想念一個觀點:恢復當前「頁面」的正確位置是什麼,即告訴Caliburn導航到暫停時激活的視圖後面的VM?我試圖在我的ResumeState方法(nr.4)結束時這樣做,但似乎爲時過早,因爲當我嘗試導航到虛擬機時,出現異常,告訴我無法找到相應的視圖。下面是該方法的相關代碼:

private void ResumeState() 
{ 
    // ... state is a dictionary wrapper class with state data 

    // restore state for each tracked VM 
    foreach (WeakReference<IHaveSimpleState> reference in _statefulViewModels) 
    { 
     IHaveSimpleState stateful; 
     if (reference.TryGetTarget(out stateful)) stateful.LoadState(state); 
    } 

    // move to the page which was current when the state was saved 
    string sType = state.Get(APP_CURRENTVM_KEY, null); 
    if (sType != null) 
    { 
     // not so elegant... 
     INavigationService navigation = IoC.Get<INavigationService>(); 
     Type t = Type.GetType(sType); 
     navigation.NavigateToViewModel(t); 
    } 
} 
+0

奇怪 - 我可以看到,如果應用纔剛剛裝(新實例),因爲引導程序可能沒有踢和註冊的所有意見,但話又說回來,這可能發生我不知道RT,所以我不能肯定地告訴你應用恢復時事件的順序。你有沒有嘗試把這個引導程序放在'Configure'方法中(在調用base.Configure()之後?) - 我在想,至少這會在應用程序初始化之後進行,所以視圖應該準備好去 – Charleh

+0

謝謝,但是如果我嘗試在Configure的末尾插入導航到VM代碼(甚至在調用base.Configure()之後;這是否需要重寫CM中的Configure方法?),我得到的所有內容都是另一個異常告訴我IoC尚未配置。 – Naftis

+0

CM的創建者有一篇有趣的文章[here](http://caliburnmicro.com/announcements/application-state-part-3/)。它提出了一些想法,但沒有提供實施。它雖然開了一個討論。也請看[this](https://github.com/Caliburn-Micro/Caliburn.Micro/issues/95) – Corcus

回答

0

我嘗試這樣做,似乎工作,但我覺得有點不安全。因爲在CM生命週期處理的8.1似乎並沒有成爲我的應用程序的健壯性明確記錄,所以我想從社區獲得評論或更正。首先覆蓋PrepareViewFirst方法:

protected override void PrepareViewFirst(Frame rootFrame) 
{ 
    _container.RegisterNavigationService(rootFrame); 
} 

然後在OnLaunched覆蓋,在那裏之前,我剛剛打電話DisplayRootView<MainView>(),我測試的參數傳遞給檢查我們是否從暫停狀態恢復,如果是這樣我瀏覽到以前的活動頁面;別的我只是去像以前一樣:

protected override void OnLaunched(LaunchActivatedEventArgs args) 
{ 
    bool bResumed = false; 
    if (args.PreviousExecutionState == ApplicationExecutionState.Suspended) 
    { 
     AppSimpleState state = LoadState(); 
     string sType = state.Get(APP_CURRENTVM_KEY); 
     if (sType != null) 
     { 
      INavigationService navigation = IoC.Get<INavigationService>(); 
      Type t = Type.GetType(sType); 
      Debug.Assert(t != null); 
      navigation.NavigateToViewModel(t); 
      bResumed = true; 
     } //eif 
    } 

    if (!bResumed) DisplayRootView<MainView>(); 
} 
+0

當我開始寫一些RT應用程序時,我會回來告訴你,如果我找到了一個更好的方法來做到這一點 - 我目前正在編寫一些機器人的東西,所以沒有達到RT部分,如果你找到一個更好的地方來放置它,請做更新。替代方案(以及我經常做的事情)是查看CodePlex上的CM源,並從引導程序開始通過它運行。它寫得很好,容易遵循,所以你會學到很多關於事件的順序。 – Charleh