2013-09-05 47 views
1

我有一個使用MvvmCross的WinRT應用,我想存儲當前會話狀態。暫停Windows應用商店應用:調用MvxSuspensionManager.SaveAsync()時出錯

在塔App.xaml.cs註冊我的應用程序與懸架經理內容框架的OnLaunch方法:

​​

每當我暫停應用程序,並在OnSuspending事件處理

運行代碼
var suspensionManager = Mvx.GetSingleton<IMvxSuspensionManager>() as MvxSuspensionManager; 

await suspensionManager.SaveAsync(); 

我收到以下異常。

Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManagerException "MvxSuspensionManager failed" 
at Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManager.<SaveAsync>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
at ****App.xaml.cs:line 129 
System.Runtime.InteropServices.COMException "Unbekannter Fehler 
" 
at Windows.UI.Xaml.Controls.Frame.GetNavigationState() 
at Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManager.SaveFrameNavigationState(Frame frame) 
at Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManager.<SaveAsync>d__0.MoveNext() 

我敢肯定,我可以縮小例外根到的WinRT API調用

Frame.GetNavigationState(); 
由該MvxSuspensionManager執行

。當我直接調用這個函數時,它會失敗並出現相同的錯誤。

我知道WinRT幀導航堆棧只能在非複雜類型用作導航參數時序列化。但即使我暫停在第一頁上,我的應用程序也會崩潰。

也許我用MvvmCross掛起的方法是錯誤的,或者我錯過了一些要正確設置的步驟。

任何幫助,高度讚賞!

回答

3

'未知錯誤'的時刻有兩個問題是禁用暫停經理。正如你所說,MvX用複雜的(ViewModelRequests)對象而不是字符串進行導航。您可以通過創建自己的ViewPresenter,解決這個問題應該是這樣的:

public class CustomViewPresenter : MvxStoreViewPresenter { 
    //XXX: Holding a ref here because base class's ref to the frame is for some reason private. 
    private Frame _curFrame; 
    public CustomViewPresenter(Frame RootFrame) : base(RootFrame) { 
     _curFrame = RootFrame; 
    } 

    public override void Show(MvxViewModelRequest request) { 
     try { 
      var requestTranslator = Mvx.Resolve<IMvxViewsContainer>(); 
      var viewType = requestTranslator.GetViewType(request.ViewModelType); 

      var converter = Mvx.Resolve<IMvxNavigationSerializer>(); 
      var requestText = converter.Serializer.SerializeObject(request); 

      _curFrame.Navigate(viewType, requestText); 
     } catch (Exception exception) { 
      MvxTrace.Trace("Error seen during navigation request to {0} - error {1}", request.ViewModelType.Name, 
          exception.ToString()); 
     } 
    } 
} 

在你的基地頁面對象,從MvxStorePage繼承,這反序列化字符串化VMRequest之一。不要打電話給基地方法:

protected override void OnNavigatedTo(NavigationEventArgs e) { 
     var reqData = (string)e.Parameter; 

     var converter = Mvx.Resolve<IMvxNavigationSerializer>(); 
     var req = converter.Serializer.DeserializeObject<MvxViewModelRequest>(reqData); 

     this.OnViewCreate(req,() => LoadStateBundle(e)); 
    } 

一旦你做完所有這些,你有另一個問題。 Mvx將捆綁包序列化爲Dictionary * string,string *,而與Mvx綁定的暫停管理器只能處理Dictionary * string,object *。你必須複製並粘貼標準懸掛管理器,微軟發佈到你的應用程序,並更改此:

private readonly List<Type> _knownTypes = new List<Type>(); 

要這樣:

private readonly List<Type> _knownTypes = new List<Type>() { typeof(Dictionary<string, string>) }; 

然後,你需要養活你的改變SuspensionManager到MVX通過添加以下行到你的setup.cs文件:

protected override Cirrious.MvvmCross.WindowsStore.Views.Suspension.IMvxSuspensionManager CreateSuspensionManager() { 
     return new MyFixedSuspensionManager(); 
    } 

這應該可以全部滾入MVX的未來版本中的一個,所以我們不必做這些b ackflips。

+0

非常感謝你。這讓我瘋狂,我的CustomPresenter並沒有真正的用處,因爲我缺少了這個:this.OnViewCreate(req,()=> LoadStateBundle(e));在我所有的觀點。 –

+0

此解決方案現在已合併到MvvmCross中 –

0

我猜這在你的使用中不是一個錯誤 - 而是在'標準'的MvvmCross適配中的一個錯誤SuspensionManager - 可能在保存的對象類型中。

內MvvmCross的SuspensionManager代碼是主要是基於Windows8.0 Common模板SuspensionManager - 但我記得有早期發育過程中有很多的挫折(使用不同的預覽版本)與COMException S的經常返回這種無益的消息如unknown error。在實踐中,Windows 8暫停尚未(迄今)在MvvmCross用戶的優先級列表中上升到很高 - 所以如果有這些當前適應需要添加或修復,我不會感到驚訝(尤其是Windows進入到LayoutAwarePage已被棄用的8.1)。 MvvmCross中的加載/恢復狀態用於許多應用程序中的「內存中」緩存狀態,但我個人並未使用它來從「暫停和關閉」終止狀態恢復應用程序。

如果您的應用程序需要拯救這個工作暫停功能/從盤,那麼相信MvxSuspensionManager和相關MvxStorePage.SaveStateBundleMvxStorePage.LoadStateBundle代碼可以做一個小的調試工作,而且我認爲,重要的方法是所有標記爲virtual,以便他們可以輕鬆地被覆蓋,但...悲傷...我相信讓他們工作可能是一個令人沮喪的調試體驗,包括從COMException