概要
PowerAppsで、Navigate関数でスクリーンを遷移する際、Dropdownコントロールで選択したスクリーンに遷移する方法です。
Dropdownコントロールのソースに、Screenコントロールをぶち込んで、
準備
こんな感じで、メインスクリーンのほか、遷移先となるスクリーンを3つほど作成します。(もっとたくさん作っても構いません)
メインスクリーン
メインスクリーンは、遷移先を選択するDropdownと、Navigate関数を実行するButtonコントロールを配置。
画面A・B・C
画面Aには、画面Aであることが分かるようにするLabelと、戻るアイコンを配置。
戻るアイコンには、OnSelectに、Back()関数を記述
画面Bと画面Cも同様。
失敗
ここから、ロジックを記述していきます。
App の OnStart
Clear(SelectScreen);
ForAll([画面A,画面B,画面C],Collect(SelectScreen,ThisRecord))
注意は、ForAllの最初の引数で画面Aから画面Cの配列を渡していますが、この要素は引用符で囲まないことです。
それによって、Screenコントロールの名前ではなく、Screenコントロール自体を配列の要素として指定します。
Dropdownコントロール
続いて、Dropdownコントロールのソースを指定します。
DropdownコントロールのItemsプロパティにSelectScreenコレクションを指定
「別のコレクション レコードの構造体が必要です。」と怒られました。
SelectScreen.Valueを渡しても、・・・
やっぱりダメ。
Comboboxコントロールならどうだ?
新たにCombobox コントロールを配置して、ItemsプロパティにSelectScreen.Valueを設定。
エラーにはならないが、・・・
ドロップダウンに表示されない、・・・。
3個あるので、何やら3つは入っているらしい。
Labelコントロールで確認すると、
確かにScreenコントロールが入っている。
ちなみにButtonコントロールにNavigate関数を書くと、動作します。
修正
Comboboxを使ったやり方で動作はするものの、DisplayFieldを弄ったりしてもどうにも表示が見えないので、少しやり方を変えます。
App の OnStart を修正
OnStart の動作を修正し、SelectScreenコレクションに、NameとControlという2つのプロパティを持つレコードを格納してやるようにします。
Clear(SelectScreen);
ForAll([画面A,画面B,画面C],Collect(SelectScreen,{Name:ThisRecord.Value.Name,Control:ThisRecord.Value}))
DropdownやComboboxのソース(Itemsプロパティ)は、SelectScreen.Valueではなく、SelectScreenを設定
Dropdownのソースを修正すると、何やら表示されました。
ComboboxもソースをSelectScreen.ValueからSelectScreenに修正すると項目名が正しく表示されるようになります。
下図で [object Object]とか表示されているのは、修正前に選択した状態が残っているためです。
プレビューで、[object Object] を×で選択解除すると、これ以降は出てきません。
ほかの場所も修正して完成
DropdownでもComboboxでも(あるいはほかのコントロールでも)、スクリーンを選択できるようになります。
いちいち選択して、ボタンをクリックするのは面倒なので、それぞれのコントロールのOnChangeプロパティに、Navigate関数を記述していきます。
先ほどボタンのOnSelectに記述したのは、[Control名].Selected.Valueでしたが、[Control名.Selected.Controlになります。
ソース(Itemsプロパティ)は、SelectScreenコレクションになります。
動作確認
ついでにRadioボタンもつけてみました。
いづれの方法でも、選択した画面に遷移できることが確認できると思います。
まとめ
ポイントは以下の通りです。
- OnStartで、NameとControlの2つのプロパティを持ったScreenコントロールのコレクションを作成する
- 遷移先の選択用コントロールのItemsプロパティに、Screenのコレクションを指定する
- 選択用コントロールのValueやDisplayNameに、ScreenコレクションのNameプロパティを指定する
- 選択用コントロールのOnChangeに、Navigate関数を記述して、第一引数に"Self.Selected.Control"を指定する。(別にボタンを用意しても可)
このようなやり方をしなくても、Switch関数とかで場合分けして遷移先を選んでやれば、これと同じ動作をさせることはなんぼでもできます。
ただ、画面が今後も増えていったり、遷移する方法を変えたりといったことがあるたびに、Itemsプロパティを修正したり、Navigate関数を修正したりするのは、修正漏れが出てきたりしてメンテナンス性がかなり悪くなります。
このやり方だと、スクリーンの追加をした場合でもコレクションに追加するだけで、Dropdown等のコントロールを修正する必要はなくなります。
なので、画面の追加や修正がかなり楽になるのではないでしょうか。
(迷路ゲームとか脱出ゲームに使えそうな気がします。作りませんが...)