分割アプリテンプレートを例に、SnapViewデザインのXAML記述をじっくりみてみよう
Windows 8 ストアアプリの実装がほぼ終わり、ダッシュボードに登録しようと思って、あ、SnapView対応忘れてた…なんてことありませんか?Windows 8の画面はFull Landscape、Full Portraite、Fill、SnapViewといくつか種類があり、少なくともFull画面とSnapViewはそれなりの見栄えがないと駄目です。表示する項目をなるべく共通にして、配置や見栄えだけ変えるのが一番効率的ですね。このポストでは、Visual Studio 2012に標準で提供されている”分割アプリケーション”テンプレートのSplitViewを例に、どうやって表示項目は同じで項目の配置やスタイルを変えているか、解説してみます。
先ずは、読者の皆さんも、Visual Studio 2012で、C#ストアアプリの”分割アプリケーション(XAML)”テンプレートを使って一つプロジェクトを作成してください。F5実行してグループの画像を一個タップします。
SplitViewページのFull画面表示とSnap画面は、
こういう画面です。対応は、以下の様になっています。
対応しているコントロールは同一のものが使われています。では、この画面を定義しているSplitPage.xamlをエディターで開いてください。
28行目~99行目までが、Full画面のデザイン指定がされた表示コントロール一式の定義です。この部分をよう~っくみてください。配置用の格子(Grid)やコントロールにフォーカスをあてると、下のような図になります。
ページにはまず、2×2のGridが定義されています。※33行目付近
左側のカラム(Column)にはprimaryColumnという名前が付けられていて、他の場所で参照可能になっています。Grid上の位置を(行、列)で書きますね。
(0,0)の位置には戻りボタンとページタイトルを表示するための、”titlePanel”と名前の付いた格子が定義されています。(1,0)のセルには、itemListViewと名前付けられた、ListViewコントロールが配置され、同一グループに属す項目リストを表示しています。右側には、上下のセルを二つつなげてitemDetailと名付けられた選択項目の詳細を表示するScrollViewerが配置されています。このScrollViewer内ではさらにGridを使って3行×2列のセルが定義されています。
これで、一通りFull画面のデザインの説明が終わりました。ここまでのことをしっかり理解して頭に入れてくださいね。
さて、各Viewのデザインは<VisualStateManager.VisualStateGroups>…</VisualStateManager.VisualStateGroups>の子要素として、各Viewごとのデザインが定義されています。Snap Viewのデザインは、215~262行目まで定義されています。
例として、217~219行目を取り上げると、
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
という記述があります。これは、「Snap Viewになった時に、戻りボタン(backButton:48~52行で定義)のStyleプロパティをSnappedBackButtonStyle(StandardStyles.xamlで定義)にしなさい」という意味です。この様な定義が列記されてSnap Viewの時のデザインを指定しているわけです。
Snap Viewのデザイン定義内容を下表に書き下ろしてみました。
No | XAML定義項目 | 部品クラス | プロパティ | Fill時の指定 | Snap時の指定 |
1 | backButton | Button | Style | BackButtonStyle | SnappedBackButtonStyle |
2 | pageTitle | TextBlock | Style | PageHeaderTextStyle | SnappedHeaderTextStyle |
3 | primaryColumn | Grid.ColumnDefinition | Width | 610 | 0 |
4 | itemListView | ListView | Visibility | Visible | Collapsed |
5 | itemDetail | ScrollViewer | Grid.Row | 0 | 1 |
6 | itemDetail | ScrollViewer | Grid.RowSpan | 2 | 1 |
7 | titlePanel | Grid | Grid.Column | 0 | 1 |
8 | imageDetailTitlePanel | StackPanel | Grid.Row | 1 | 0 |
9 | imageDetailTitlePanel | StackPanel | Grid.Column | 1 | 0 |
10 | imageDetail | ScrollViewer | Padding | 70,0,120,0 | 20,0,20,0 |
11 | imageDetailGrid | Grid | Margine | 0,60,0,50 | 0,0,0,60 |
12 | itemTitle | TextBlock | Style | SubheaderTextStyle | TitleTextStyle |
13 | itemTitle | TextBlock | Margine | 0,-10,0,0 | 0,0,0,0 |
14 | itemSubtitle | TextBlock | Style | SubtitleTextStyle | CaptionTextStyle |
この表のXAML定義項目に出てくるコントロールは、前出の図にあります。図とこの表を突き合わせて、主な部分を説明していきます。
3.primaryColumnのWidthを0に指定しています。これで、Full表示のtitlePanelとitemListViewを表示していた左側のカラムがなくなります。更に4.でitemListViewのVisibilityをCollaspedに変えて表示上消しています。
5.、6.で、itemDetail(Full表示の時は右側のカラム全部で表示)のRowを1に、RowSpanを1にしているので、Full画面の右下のセルにitemDetailが移動させられて表示されます。
7.で、titlePanel(Full表示の時は、左上のセルに表示)のColumnを1にしているので、右上のセルに移ります。3.の指定で、左側のカラムは消失しているので、新たな場所で表示されます。※itemDetail(ScrollViewer)内のGridであることに注意
8.、9.でitemDetailTitlePanelのRowとColumnをどちらも0にしています。これにより、Full画面の時にイメージ画像の右横に配置されていたItem TitleとItem Sub Titleが、イメージ画像の真上に配置されます。
10.、11.、13.は、表示するセルの位置を変えたり、12.や14.でのスタイル変更により、微妙に醜い配置を微調整してきれいに整えています。
この結果、下図に示すような配置になるわけです。
お分かりでしょうか。このSnap Viewは、Full表示の時の2x2のGridの右側だけを表示し、右側2つのセルを使っていたitemDetailを右下のセルに押し込めて、右上にtitlePanelを移動し、itemDetail(ScrollViewer)のGrid内でItemDetailTitlePanelをFull表示では使っていなかったRowに移動している、というわけです。
ここまで、読んできて、なるほどと思った方も大勢いるかなと思いますが、「あれ?そもそもなんで、<VisualState x:Name="Snapped_Detail".../>で、こんなことできるの?」と疑問に思う方も多ですよね。
SplitPage.xaml.csの方に目を転じてみると、このファイルの163行目に、
protected override string DetermineVisualState(ApplicationViewState viewState)
というメソッドが定義されていて、何やらやっています。更にこのメソッドをキーワードで調べていくと、Commonフォルダーの下のLayoutAwarePage.csの中でもこの辺に関係しそうな実装を見つけることができます。この辺の仕掛けはまた、後日ポストするということで、Visual Studio 2012の標準テンプレート(”新しいアプリケーション”は除く)を使ったアプリ開発では、このポストを参照して、効率よくSnap Viewをデザインしてください。Blendを使えば、もっと効率的です。