コントロールがウィンドウサイズに対して一定の割合となるように設定したいことはよくある。本稿では、これを実現するための方法を二つ紹介する。
powered by Insider.NET
UIコントロールの幅や高さをウィンドウのサイズの一定割合にしたいと思ったことはないだろうか? 例えば、コントロールの幅をウィンドウ幅の半分にしたいといった場合だ。Gridコントロール(Windows.UI.Xaml.Controls名前空間)の比例分割でうまくいくことも多いが、うまくできないときはどうしたらよいだろうか? 本稿では、コードビハインドで制御する方法とカスタムビヘイビアーを利用する方法を紹介する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #105」からダウンロードできる。
ユニバーサルプロジェクトを使ってユニバーサルWindowsアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Community 2013 with Update 4を使っている。
*1 SLAT対応ハードウエアは、Windows Phone 8.1エミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドと実機でのデバッグは可能だ。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウエアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。
*2 事前には「Windows 8.1 Update 1」と呼ばれていたアップデート。スタート画面の右上に検索ボタンが(環境によっては電源ボタンも)表示されるようになるので、適用済みかどうかは簡単に見分けられる。ちなみに公式呼称は「the Windows RT 8.1, Windows 8.1, and Windows Server 2012 R2 update that is dated April, 2014」というようである。
*3 Windows Phone 8.1エミュレーターを使用しないのであれば、32bit版のWindows 8.1でもよい。
*4 マイクロソフトのダウンロードページから誰でも入手できる(このURLはUpdate 4のもの)。
*5 本稿に掲載したコードを試すだけなら、無償のExpressエディションやCommunityエディションで構わない。Visual Studio Express 2013 with Update 4 for Windows(製品版)はマイクロソフトのページから無償で入手できる。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、Windowsランタイムアプリの開発には「for Windows」を使う(「for Windows Desktop」はデスクトップで動作するアプリ用)。また、2014年11月12日(米国時間)に新しくリリースされたVisual Studio Community 2013 with Update 4(製品版)もマイクロソフトのページから無償で入手できる。Communityエディションは本稿執筆時点では英語版だけなので、同じ場所にあるVisual Studio 2013 Language Packの日本語版を追加インストールし、[オプション]ダイアログで言語を切り替える必要がある。
Visual Studio 2013 Update 2(Update 3/4も)では、残念なことにVB用のユニバーサルプロジェクトのテンプレートは含まれていない*6。そのため、本稿で紹介するVBのコードはユニバーサルプロジェクトではなく、PCL(ポータブルクラスライブラリ)を使ったプロジェクトのものである。
*6 VB用のユニバーサルプロジェクトは、2015年の夏にリリースされるといわれているVisual Studio 2015(開発コード「Visual Studio 14」)からの提供となるようだ。プレビュー版で、すでに共有プロジェクトは利用可能になっている。「特集:次期Visual Studioの全貌を探る:Visual Basic 14の新機能ベスト10〜もう「VBだから」とは言わせない!」参照。
例えば、画面幅いっぱいにGridコントロールを置き、その中で列を比例配分すれば、そのセルに入れたコントロールの幅はウィンドウのサイズに応じて変化することになる(次のコードと画像)。
<Grid ……省略……>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.6*"/>
<ColumnDefinition Width="0.4*"/>
</Grid.ColumnDefinitions>
<Image Source="Assets/hayashi_09.JPG" Stretch="UniformToFill" />
<TextBlock Grid.Column="1" TextWrapping="Wrap" FontSize="30">
……省略(長い文字列)……
</TextBlock>
</Grid>
ところが、場合によってはセルに入れたコントロールが「いうことを聞かない」ことがあるのだ。例えば、Hubコントロール(Windows.UI.Xaml.Controls名前空間)に先ほどのGridコントロールを入れてみよう(次のコードと画像)。
<Hub VerticalAlignment="Top">
<Hub.Header>
<TextBlock Text="{StaticResource AppName}" ……省略…… />
</Hub.Header>
<HubSection Header="SECTION 01" x:Name="Section01">
<HubSection.ContentTemplate>
<DataTemplate>
<Grid Background="Gray" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.6*" />
<ColumnDefinition Width="0.4*" />
</Grid.ColumnDefinitions>
<Image Source="Assets/hayashi_12.JPG" Stretch="Uniform" />
<TextBlock Grid.Column="1" TextWrapping="Wrap">
……省略(長い文字列)……
</TextBlock>
</Grid>
</DataTemplate>
</HubSection.ContentTemplate>
</HubSection>
……省略(二つ目のHubSection)……
</Hub>
この例では、HubSectionコントロールの幅をウィンドウのサイズに比例して設定できればよさそうである。それにはどうすればよいのだろうか?
ウィンドウのサイズが変わるときに、コントロールの幅を調整すればよいのである。Pageコントロール(Windows.UI.Xaml.Controls名前空間)でもユーザーコントロールでも、サイズが変わるときにSizeChangedイベントが発生するので、そこでウィンドウの幅を取得して、その値を基に算出した幅を目的のコントロールに設定すればよい(次のコードと画像)。
<UserControl
x:Class="MetroTips105CS.MyUserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
……省略……
SizeChanged="UserControl_SizeChanged"
>
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
double newWidth = Window.Current.Bounds.Width * 0.9; // ウィンドウの幅を取得し、その90%を求める
this.Section01.Width = newWidth; // 一つ目のHubSectionコントロールの幅を設定
this.Section02.Width = newWidth; // 二つ目のHubSectionコントロールの幅を設定
}
Private Sub UserControl_SizeChanged(sender As Object, e As SizeChangedEventArgs)
Dim newWidth As Double = Window.Current.Bounds.Width * 0.9 ' ウィンドウの幅を取得し、その90%を求める
Me.Section01.Width = newWidth ' 一つ目のHubSectionコントロールの幅を設定
Me.Section02.Width = newWidth ' 二つ目のHubSectionコントロールの幅を設定
End Sub
調整する対象のコントロールが増えてくると、コードビハインドでサイズを調整するのが面倒になってくる。そんなときは、カスタムビヘイビアーを作成して使うとよい。
そのようなカスタムビヘイビアーのサンプルは、探せばいくつも見つかるだろう。ここでは「Tips and tricks for using XAML controls in your universal Windows apps」というブログ記事の「Window-based width adaption」という項に掲載されている「WindowDimensionBehavior」クラスというカスタムビヘイビアーを使わせてもらうことにする。そのC#のコードは長いのでここでは省略させていただくが、別途公開のサンプルには収録してある。なお、カスタムビヘイビアーはPCLでは使えないため、別途公開サンプルのVBのコードにはこの方法を含めていない(Windows/Phone個別のプロジェクトならば利用可)。
カスタムビヘイビアーを使うには、あらかじめプロジェクトに「Behaviors SDK (XAML)」への参照を追加しておく(次の画像)。
WindowDimensionBehaviorカスタムビヘイビアーを使ってコントロールの幅を調整するXAMLコードは、次のようになる。
<UserControl
x:Class="MetroTips105CS.MyUserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
……省略……
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
>
……省略……
<HubSection Header="SECTION 01">
<!-- HubSectionコントロールの幅を、画面幅の90%にする -->
<Interactivity:Interaction.Behaviors>
<local:WindowDimensionBehavior WidthPercentage="0.9"/>
</Interactivity:Interaction.Behaviors>
<HubSection.ContentTemplate>
<DataTemplate>
<Grid Background="Gray" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.6*" />
<ColumnDefinition Width="0.4*" />
</Grid.ColumnDefinitions>
……省略……
実行結果は、前述のコードビハインドで調整したときと同様になる。
ウィンドウ幅を基準にしてコントロールの幅を調整するには、コードビハインドで調整するか、カスタムビヘイビアーを作成して使用するとよい。調整対象のコントロールが多数あるときは、XAMLコードの書き換えだけで済むカスタムビヘイビアーが楽だ。
本稿では幅だけを扱ったが、高さでも同様である。Windows 8.1/Windows Phone 8.1用に作ったユニバーサルWindowsアプリをWindows 10で動かすと、高さも思いの他小さくなり得る(画面によるが、1024×768ピクセルのモニターではウィンドウの高さが500ピクセルほどになるようだ)。ウィンドウサイズに応じたUIが求められたときには、このTIPSも思い出してほしい。
Copyright© Digital Advantage Corp. All Rights Reserved.