1

現在のセッション状態を保存する MvvmCross を使用する WinRT アプリがあります。

App.xaml.cs の OnLaunch メソッドで、アプリのコンテンツ フレームを一時停止マネージャーに登録します。

...
var setup = new Setup(_contentFrame);
setup.Initialize();

var suspensionManager = Mvx.GetSingleton<IMvxSuspensionManager>() as MvxSuspensionManager;
suspensionManager.RegisterFrame(_contentFrame, "FrameNav");
...         

アプリを一時停止し、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 でサスペンドする私のアプローチが間違っているか、正しくセットアップするためのいくつかの手順を逃したのかもしれません。

どんな助けでも大歓迎です!

4

2 に答える 2

3

サスペンション マネージャーを無効にする 2 つの問題があります。あなたが言ったように、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 を逆シリアル化します。ベースの onnavigatedto メソッドを呼び出さないでください。

    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* のみを処理できます。Microsoft がアプリに同梱する標準の一時停止マネージャーをコピーして貼り付け、これを変更する必要があります。

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

これに:

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

次に、次の行を setup.cs ファイルに追加して、変更した SuspensionManager を MvX にフィードする必要があります。

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

うまくいけば、これはすべて Mvx の将来のリリースの 1 つに組み込まれ、これらすべてのバク転を行う必要がなくなります。

于 2014-01-12T23:13:02.670 に答える
0

これはあなたの使用上のエラーではないと思いますが、代わりに「標準」の MvvmCross 適応のどこかでエラーが発生していますSuspensionManager-おそらく保存されているオブジェクトタイプにあります。

SuspensionManagerMvvmCross 内のコードは、大部分が -Common用の Windows8.0 テンプレートに基づいていましたが、(さまざまなプレビュー リリースを使用して) 初期の開発中に、のような役に立たないメッセージを頻繁に返す s にSuspensionManager多くのフラストレーションがあったことを思い出します。COMExceptionunknown error

実際には、Windows 8 の一時停止は (これまでのところ) MvvmCross ユーザーの優先順位リストでそれほど高くなっていません。そのため、この現在の適応に必要な追加や修正があったとしても (特に Windows が 8.1 に移行するにつれて)、驚かないでしょう。 LayoutAwarePage は廃止されました)。MvvmCross 内からのロード/復元状態は、多くのアプリで「メモリ内」キャッシュ状態に使用されますが、私は個人的に、アプリを「一時停止およびシャットダウン」終了状態から再開するために使用したことはありません。

あなたのアプリがディスクへの/からの保存を伴うこの機能を停止する機能を必要MvxSuspensionManagerとする場合、関連付けられMvxStorePage.SaveStateBundleMvxStorePage.LoadStateBundleコードは少しのデバッグで動作するように作成できると信じています。また、重要なメソッドはすべてマークされvirtualているため、簡単にオーバーライドできます。 、しかし...悲しいことに...それらを機能させることは、COMException

于 2013-09-05T20:43:32.673 に答える