Windows 8.1 RTM + Visual Studio 2013 RC時点の情報です。
また、試し始めたばっかりで試行錯誤中のメモです。
新しいViewの作成
CoreApplicationのCreateNewViewでいけるっぽい。
var v = CoreApplication.CreateNewView();
これで、CoreApplicationViewというクラスのインスタンスがとれるので、いろいろできる。この段階でApplicationクラスのWindowCreatedイベントが発生しているので、新しいWindowが作られてるっぽい。
新しいViewに画面を表示する
CoreApplicationViewからDispatcherがとれるのでRunAsyncでフレーム作って画面遷移させればいい。
var v = CoreApplication.CreateNewView(); var viewId = default(int); await v.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { var f = new Frame(); f.Navigate(typeof(BlankPage1)); Window.Current.Content = f; ApplicationView.GetForCurrentView().Title = "Windowのタイトル"; });
新しいViewを画面に表示する
1つ前の見出しと紛らわしいですが、上のコードでは、まだ画面には出てこない状態です。画面に表示させるには、ApplicationViewSwitcher.TryShowAsStandaloneAsync(int viewId)を呼び出す必要があります。viewIdは、CoreApplicationViewのDispatcherの処理の中でApplicationView.GetForCurrentView()で取得できるApplicationViewのIdプロパティで取得できるものです。なので、こんな感じのコードに…
var v = CoreApplication.CreateNewView(); var viewId = default(int); await v.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { var f = new Frame(); f.Navigate(typeof(BlankPage1)); Window.Current.Content = f; var applicationView = ApplicationView.GetForCurrentView(); applicationView.Title = "Windowのタイトル"; viewId = applicationView.Id; }); await ApplicationViewSwitcher.TryShowAsStandaloneAsync(viewId);
このコードをボタンクリックのイベントとかに書くと、BlankPage1が表示されたウィンドウが画面に表示されます。
複数ウィンドウに一気に処理をしたりする
マルチビューの環境で、他のWindowに対して処理をするには、CoreApplicationViewをとっておけばできそうです。なので、以下のようなフィールドをどこかに定義してCoreApplicationViewをとっておくようにします。
List<CoreApplicationView> views = new List<CoreApplicationView>();
そして、新しいViewを作成するコードの中でリストに保持するようにします。
var v = CoreApplication.CreateNewView(); var viewId = default(int); await v.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { var f = new Frame(); f.Navigate(typeof(BlankPage1)); Window.Current.Content = f; var applicationView = ApplicationView.GetForCurrentView(); applicationView.Title = "AppView: " + views.Count; viewId = applicationView.Id; }); // とっとく views.Add(v); await ApplicationViewSwitcher.TryShowAsStandaloneAsync(viewId);
あとは、CoreApplicationViewのDispatcherからRunAsyncすると、その中でWindow.Currentプロパティを使って、そのビューのWindowを取得できます。Windowが取得できたら後はお好きなように。
例えば、全てのビューのBlankPage1に対してSetというメソッドを呼ぶ場合は以下のようになります。
foreach (var v in this.views) { var data = DateTime.Now.ToString(); await v.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { var page = ((Windows.UI.Xaml.Controls.Frame)Window.Current.Content).Content as BlankPage1; page.Set(data); }); }
感想
ちゃんと作らないと、サスペンドからの復帰とか色々考えると頭が痛くなりそう。こんな風にCoreApplicationViewをリストで保持して、それを依り代にして操作をするのではなくて、どんなデータを元にしたビューを表示中なのかということをきちんとアプリケーションのロジック内で管理して、それを永続化しておく。そして、サスペンドからの復帰時には必要に応じて新しいビューを生成するといった形にしないと辛そう。
これは適当に作ると詰む系だと思いました。
あと、MSのサンプルだとCreateNewViewの後にWindowCreatedの完了を待って、WindowCreatedイベントハンドラの中でCoreDispatcerを取得するとかいう複雑怪奇なサンプルになってるんだけど、これは必須なのだろうか… Multiple Views Sample