5

私は間違いなく悪い考えをしようとしていますが、それでも可能だと思います。WP8 が [戻る] ボタンを処理する方法をオーバーライドして、自分で実装しようとしています。私は次の場合にそれを理論化します:

計画

  1. アプリケーション全体で「フレーム」と「ページ」を 1 つだけ作成する
  2. PhoneApplicationPage.BackKeyPress彼らがアプリケーションを取り消そうとしていない限り、常に自分自身を処理してください。

リプロ

クラッシュするサンプル プロジェクトを次に示します。

コード

..それならうまくいくはずです。しかし、私の試みは Windows Phone によって妨げられています。コードは次のとおりです。

// This basically happens on PhoneApplicationService.OnLaunched
_viewModelChanged.StartWith(ViewModel).Where(x => x != null).Subscribe(vm => {
    var page = default(IViewFor);
    var frame = RootVisual as PhoneApplicationFrame;

    // Find the initial PhoneApplicationPage for the app
    page = RxApp.GetService<IViewFor>("InitialPage");

    // Depending on how we're being signalled (i.e. if this is cold start 
    // vs. resume), we need to create the PhoneApplicationFrame ourselves
    if (frame == null) {
        frame = new PhoneApplicationFrame() {
            Content = page,
        };
    }

    page.ViewModel = vm;
    var pg = page as PhoneApplicationPage;
    if (pg != null) {
        pg.BackKeyPress += (o, e) => {
            if (ViewModel.Router.NavigationStack.Count <= 1 ||
                ViewModel.Router.NavigateBack.CanExecute(null)) {
                return;
            }

            e.Cancel = true;
            ViewModel.Router.NavigateBack.Execute(null);
        };
    }

    // Finally, set Application.RootVisual
    RootVisual = frame;
});

悲しみ

これは、このコードが実行された直後に、フレームワークによってキューに入れられた DispatcherItem がアプリをクラッシュさせるまで、うまく機能ます。

System.NullReferenceException occurred
Message: A first chance exception of type 'System.NullReferenceException' occurred in Microsoft.Phone.ni.dll
Microsoft.Phone.ni.dll!Microsoft.Phone.Controls.PhoneApplicationPage.InternalOnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)   Unknown
Microsoft.Phone.ni.dll!Microsoft.Phone.Controls.PhoneApplicationPage.Microsoft.Phone.Controls.IPhoneApplicationPage.InternalOnNavigatedFromX(System.Windows.Navigation.NavigationEventArgs e)   Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.RaiseNavigated(object content, System.Uri uri, System.Windows.Navigation.NavigationMode mode, bool isNavigationInitiator, Microsoft.Phone.Controls.IPhoneApplicationPage existingContentPage, Microsoft.Phone.Controls.IPhoneApplicationPage newContentPage) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.CompleteNavigation(System.Windows.DependencyObject content, System.Windows.Navigation.NavigationMode mode)   Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.ContentLoader_BeginLoad_Callback(System.IAsyncResult result) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.PageResourceContentLoader.BeginLoad_OnUIThread(System.AsyncCallback userCallback, System.Windows.Navigation.PageResourceContentLoader.PageResourceContentLoaderAsyncResult result) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.PageResourceContentLoader.BeginLoad.AnonymousMethod__0(object args)    Unknown
[Native to Managed Transition]  
mscorlib.ni.dll!System.Delegate.DynamicInvokeImpl(object[] args)    Unknown
System.Windows.ni.dll!System.Windows.Threading.DispatcherOperation.Invoke() Unknown
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.Dispatch(System.Windows.Threading.DispatcherPriority priority)    Unknown
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.OnInvoke(object context)  Unknown
System.Windows.ni.dll!System.Windows.Hosting.CallbackCookie.Invoke(object[] args)   Unknown
System.Windows.RuntimeHost.ni.dll!System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(System.IntPtr pHandle, int nParamCount, System.Windows.Hosting.NativeMethods.ScriptParam* pParams, System.Windows.Hosting.NativeMethods.ScriptParam* pResult)   Unknown
4

3 に答える 3

5

だから、私はこれを解決しました-WP8がどのように機能するかを理解していなかったので、私のコードは問題がありました:)これが私が今理解していることです、これも間違っているかもしれませんが、とにかくそれを書きます

WP8アプリの初期化方法:

  1. OSは、App.xaml.csを再水和することでAppクラスを作成します
  2. つまり、コンストラクターが実行され、その一部として、PhoneApplicationFrame
  3. を作成すると、グローバル静的変数PhoneApplicationFrame設定されるようです( App.xamlでの作成でも同じことが起こり、設定されます)。PhoneApplicationServicePhoneApplicationService.Current
  4. NavigationService次に、リソース文字列(つまり)を介してXAMLビューの再作成を試みます'/MainPage.xaml'。以前にトゥームストーンされたものを再作成するか、そうでない場合は、デフォルトでWMAppManifestにあるものを再作成します(これは私が理解していなかった部分です)。
  5. PhoneApplicationFrame.NavigatedNavigationServiceによって呼び出されます-これは、実際に作業を開始できる場所です。これには、最も重要なこととして、Loading...画面を送信するApplication.RootVisualの設定が含まれます。
  6. PhoneApplicationService.LaunchedまたはPhoneApplicationService.Activated、アプリがどのようにウェイクアップされたかに応じて、基本的にすべてがセットアップされると、最終的に起動します。
于 2013-02-10T23:32:55.770 に答える
4

問題が見つかりました。まあ、氷山の一角。

InternalOnNavigatedFrom メソッドのコードは次のとおりです。

internal override void InternalOnNavigatedFrom(NavigationEventArgs e)
{
    PhoneApplicationPage content = e.Content as PhoneApplicationPage;
    string str = ((content == null) || (content.Title == null)) ? string.Empty : content.Title;
    PerfUtil.BeginLogMarker(MarkerEvents.TH_ONNAVIGATEDFROM_PAGE, string.Format("{0},{1},{2}", (base.Title == null) ? "" : base.Title, e.NavigationMode, str));
    this.OnNavigatedFrom(e);
    PerfUtil.EndLogMarker(MarkerEvents.TH_ONNAVIGATEDFROM_PAGE, string.Format("{0},{1},{2}", (base.Title == null) ? "" : base.Title, e.NavigationMode, str));
    DeviceStatus.KeyboardDeployedChanged -= new EventHandler(this.OnKeyboardDeployedChanged);
    Task rootTask = ApplicationHost.Current.RootTask;
    rootTask.OnVisibleRegionChange = (ITask.VisibleRegionChanged) Delegate.Remove(rootTask.OnVisibleRegionChange, new ITask.VisibleRegionChanged(this.OnVisibleRegionChange));
    Task task2 = ApplicationHost.Current.RootTask;
    task2.OnSipVisibilityChange = (ITask.SipVisibilityChange) Delegate.Remove(task2.OnSipVisibilityChange, new ITask.SipVisibilityChange(this.OnSipVisibilityChange));
    this._lastSipHeight = 0.0;
    this._dictionary = null;
}

e少しデバッグした後、どちらもApplication.Current.RootTasknullでもないと結論付けました。頭を悩ませた後、KeyboardDeployedChangedイベント ハンドラーのコードを確認しました。

public static  event EventHandler KeyboardDeployedChanged
{
    [SecuritySafeCritical] add
    {
        if (KeyboardDeployedSubscription == null)
        {
            KeyboardDeployedSubscription = new SubscriptionHandler(DeviceTypes.KeyBoard);
        }
        KeyboardDeployedSubscription.Changed += value;
    }
    [SecuritySafeCritical] remove
    {
        KeyboardDeployedSubscription.Changed -= value;
    }
}

このコードは書き方が悪いです。removeハンドラーの一部が の前addに呼び出されるKeyboardDeployedSubscriptionと、null になり、例外が発生します。私の理論をテストするために、私はAppのコンストラクターでイベントをサブスクライブしました。

    public App()
    {
        // Global handler for uncaught exceptions.
        UnhandledException += Application_UnhandledException;

        DeviceStatus.KeyboardDeployedChanged += (sender, e) => { };

案の定、例外はなくなりました。ここで、コードがこの問題を引き起こしている理由を理解するために、フレームワークのどの部分がイベントをサブスクライブすることになっているかをバックトレースしました。唯一の候補はInternalOnNavigatedToメソッドです。

したがって、あなたの問題は、呼び出されたことがないOnNavigatedFromにもかかわらず呼び出されるOnNavigatedToことです。

于 2013-02-10T00:31:56.800 に答える
1

WMAppManifest.xmlで定義されたページへのWindows Phoneの組み込みの自動ナビゲーションに苦労しているため、自動ナビゲーションを削除しようとしましたが、基本的には機能しました(例外なし)。

交換したばかり

<DefaultTask Name="_default" NavigationPage="MainPage.xaml" />

<DefaultTask Name="_default" />

これで問題が解決するかどうかはわかりませんが、少なくともクラッシュすることはありません。

于 2013-02-10T05:42:14.853 に答える