LoginSignup
0
1

More than 3 years have passed since last update.

Prism.UnityでNavigationAsyncしてもページのViewModelが生成されない問題への対処

Last updated at Posted at 2019-04-23

概要

  • 自前でアプリのメニュー+Frameを準備して、そのFrameからNavigationServiceを生成するケース
  • メニュー部分とFrame部分で別々のDataContext(ViewModel)を扱う必要があるが
  • FrameのDataContextがnull以外だとNavigationService側の実装が「もうViewModel注入済みやな」と判断してViewModelが生成されない
  • 結論:自前FrameからNavigationServiceを生成する場合はDataContext伝播に気を付けよう

環境

Uno.Prism.Unity.Uno 7.1-pre4
(本家のPrism.Unity.Windowsと同じなはず)

問題: NavigationAsyncしても xxxPageViewModelが生成されない

Prism.Unityでは自前定義のFrameに対してNavigationServiceを都度生成することができます。アプリで複数のFrameでページ表現を別々に管理したり、あるいは複数ウィンドウで別々のFrameをもたせてそこでページを管理する場合に活躍します。(ページナビゲーションのパラメータ渡しがやりやすいだとか、ページVMの注入を自動で紐づけてくれるだとか)

そこで以下のようなNavigationServiceを作ってみると…


// PrismApplicationを継承したAppクラス内として読んでください

public static IPlatformNavigationService NavigationService { get; private set; }

public override void OnInitialized()
{
    // アプリのルートUIを作成
    var layout = new ApplicationCoreLayout();
    NavigationService = Prism.Navigation.NavigationService.Create(layout.MyFrame, Gestures.Back, Gestures.Forward, Gestures.Refresh);
    Container.GetContainer().RegisterInstance<INavigationService>(NavigationService);
    Window.Current.Content = layout;
    Window.Current.Activate();
}

ApplicationCoreLayoutはアプリ側で作成したNavigationView等Frame x:Name="MyFrame"を持っていて、MyFrameと紐付いたNavigationServiceを作成してDIコンテナに登録しています。

このとき、ApplicationCoreLayoutもMVVMでやりたいので、DataContextに対してApplicationCoreLayoutViewModelを設定します。そうするとApplicationCoreLayout.DataContextがMyFrameのDataContextに伝播します

それだけなら問題ありませんが、MyFrameで読み込まれる「××Page」にまでMyFrameのDataContextが伝播してしまうことが問題になります。

Prism.UnityのFrameFacadeによるViewModelのDIはPage.DataContextがnullならページナビゲーション向けのViewModelをDIするよ」と判断しているため、Page.DataContextがFrameから伝播してしまっているとViewModelがページに設定されない(ViewModelがそもそも生成されない)ことになります。

(実際の処理は Prism.Windows/Navigation/FrameFacade.cs のOrchestrateAsync を参照のこと)

解決:Frame.DataContext = null を明示的に設定

この問題を回避するにはFrame.DataContext = nullを明示的に設定するだけで十分のようです。

<!-- Frame内のPage.DataContextにDataContextを伝播させないようnullを明示的に設定
     Prism.Unityの -->
<Frame x:Name="MyFrame" DataContext="{x:Null}" />

これでOK。

以上、Frameが絡むDataContext伝播で事故った話でした。

あと Uno Platform がすごそうなんでよかったらチェックして見てね。UWPアプリをC#+Xamlで作ったらAndroidとiOSもアプリが出来る!(XamarinベースでUWPのUIを各プラットフォームでエミュレートしてるっぽい)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1