GridViewで画面サイズに合わせて画像を拡大/縮小する

2015年11月11日(水)
薬師寺 国安

前回は、FlipViewコントロールを使って画像と説明テキストを表示し、画面のサイズによって説明テキストを縦横の位置に変更する方法を解説しました。第6回の今回は、「GridView」で画面サイズに合わせて画像の表示方法を変化させる方法を見ていきます。

GridViewとは

「GridView」は、行と列にデータ項目を表示するコントロールです。詳細については、下記のURLを参照してください。Windows 10より以前バージョンでは、GridViewの既定のレイアウトがWindowsでは水平方向、Windows Phoneでは垂直方向になっていました。Universal Windows Platform(UWP)アプリのGridViewでは、すべてのデバイス・ファミリに垂直方向のレイアウトが既定で使用されるようになっています。

リストビューおよびグリッドビューのガイドライン
https://msdn.microsoft.com/ja-jp/library/windows/apps/xaml/hh465465.aspx

プロジェクトの作成

Visual Studio Community 2015を起動し、新しいプロジェクトを作成します。詳細な手順は、第2回の「プロジェクトの作成」の項を参照してください。なお、今回の「プロジェクト名」は「UniversalApp5」と指定します。

[OK]ボタンをクリックすると、「UniversalApp5」のプロジェクトが起動します。ソリューションエクスプローラー内のMainPage.xamlをダブルクリックすると、デザイン画面とXAMLコードの記述された画面が表示されます。このデザイン画面にコントロールを配置していきます。

新しいフォルダーの作成と画像の追加

コントロールを配置する前に、ソリューションエクスプローラー内に「Image」というフォルダーを作成し、10枚の画像を追加します。詳細な手順は、第2回の「新しいフォルダーの作成と画像の追加」の項を参照してください。

なお、ここで追加する画像はサンプルファイルに含まれています。適当な画像がお手元にない場合はご利用ください。サンプルファイルはこちらからダウンロードできます(UniversalApp5.zip)。

XMLファイルの追加

今回は、第5回で作成した「photo_etc.xml」ファイルを使用します。ソリューションエクスプローラー内の「UniversalApp5(Universal Windows)」を選択した状態でマウスを右クリックして、メニューから「追加」→「既存の項目」と選択してphoto_etc.xmlを指定してください。ただし、今回はXMLファイル内の<説明>要素は使用しません。

コントロールの配置

続けて、コントロールを配置していきましょう。画面右のソリューションエクスプローラーから「MainPage.xaml」をダブルクリックすると、デザイン画面が表示されます。ここでデザイン画面が狭く表示されている場合は、デバイススケールの一覧から「23”Desktop(1920×1080)100%スケール」を選択してください。デザイン画面が広く表示されます(詳細は第2回の「コントロールの配置」の項を参照)。

ツールボックスの「すべてのXAMLコントロール」からデザイン画面上にScrollViewerコントロールを1個(図1)と、その中にGridViewコントロールを1個(図2)配置します。GridViewのNameに「GridView1」と指定し、プロパティから「レイアウト」を展開すると表示される「v」アイコンをクリックして、FlowDirectionに「LeftToRight」を指定してください。ここまでの操作で、MainPage.xamlはリスト1のようになります。

リスト1: MainPage.xaml

<Page
    x:Class="UniversalApp5.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UniversalApp5"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ScrollViewer>(1)
            <GridView x:Name="GridView1" HorizontalAlignment="Left" FlowDirection="LeftToRight" />(1)
        </ScrollViewer>(1)
    </Grid>
</Page>
  1. Scrollviwerを記述し、その子要素として「GridView1」という名前のGridViewを配置

GridView内に画像をバインドするため、リスト1をリスト2のように編集します。

リスト2: 編集されたXAML(MainPage.xaml)

<Page
    x:Class="UniversalApp5.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UniversalApp5"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>(1)
        <DataTemplate x:Key="GridViewTemplate">(2)
            <StackPanel Orientation="Horizontal" >(3)
                <Image Width="640" Height="480" Source="{Binding 画像名}" Stretch="Uniform"/>(4)
            </StackPanel>(3)
        </DataTemplate>(2)
        <DataTemplate x:Key="GridViewPhoneTemplate">(5)
            <StackPanel Orientation="Vertical" >(6)
                <Image Width="320" Height="240" Source="{Binding 画像名}" Stretch="Uniform"/>(7)
            </StackPanel>(6)
        </DataTemplate>(5)
    </Page.Resources>(1)
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ScrollViewer>
            <GridView x:Name="GridView1" HorizontalAlignment="Left" FlowDirection="LeftToRight" />
        </ScrollViewer>
    </Grid>
</Page>
  1. Page.Resourcesプロパティ要素を記述する
  2. Page.Resourcesプロパティ要素内にKey名が「GridViewTemplate」というDataTemplateを記述する
  3. DataTemplateの子要素としてStackPanelを記述し、Orientatonプロパティに「Horizontal」を指定してオブジェクトの配置を水平方向とする
  4. StackPanel要素の子要素としてImageを記述し、Widthを「640」、Heightを「480」と指定する。Sourceプロパティには「画像名」をバインドしておく。ここで指定するバインド名はVBコードのクラス内で定義したプロパティ名
  5. Key名が「GridViewPhoneTemplate」という名前のDataTemplateを記述する
  6. DataTemplateの子要素としてStackPanelを記述し、Orientatonプロパティに「Vertical」を指定してオブジェクトの配置を垂直方向とする
  7. StackPanel要素の子要素としてImageを記述し、Widthを「320」、Heightを「240」と指定する。Sourceプロパティには「画像名」をバインドしておく

リスト2のデザイン画面は図3のようになります。

次に、GridView内にバインドされた画像を画面のサイズによって横並びに表示させたり縦並びに表示させたりするために、DataTemplateで定義したテンプレートを切り替えるようにします。リスト2をリスト3のように編集します。

リスト3: 編集されたMainPage.xaml

<Page
    x:Class="UniversalApp5.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UniversalApp5"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <DataTemplate x:Key="GridViewTemplate">
            <StackPanel Orientation="Horizontal" >
                <Image Width="640" Height="480" Source="{Binding 画像名}" Stretch="Uniform"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="GridViewPhoneTemplate">
            <StackPanel Orientation="Vertical" >
                <Image Width="320" Height="240" Source="{Binding 画像名}" Stretch="Uniform"/>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ScrollViewer>
            <GridView x:Name="GridView1" HorizontalAlignment="Left" FlowDirection="LeftToRight" />
        </ScrollViewer>
        <VisualStateManager.VisualStateGroups>(1)
            <VisualStateGroup>
                <VisualState x:Name="WideState">
                    <VisualState.StateTriggers>(2)
                        <AdaptiveTrigger MinWindowWidth="600" />(3)
                    </VisualState.StateTriggers>(2)
                    <VisualState.Setters>(4)
                        <Setter Target="GridView1.ItemTemplate"
                            Value="{StaticResource GridViewTemplate}" />(5)
                    </VisualState.Setters>(4)
                </VisualState>
                <VisualState x:Name="NarrowState">
                    <VisualState.StateTriggers>(6)
                        <AdaptiveTrigger MinWindowWidth="0" />(7)
                    </VisualState.StateTriggers>(6)
                    <VisualState.Setters>(8)
                        <Setter Target="GridView1.ItemTemplate"
                            Value="{StaticResource GridViewPhoneTemplate}" />(9)
                    </VisualState.Setters>(8)
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>(1)
    </Grid>
</Page>
  1. レイアウトの変更にはVisualStateManagerを使用する
  2. 画面のサイズに応じてVisualStateを自動で切り替えるには、VisualStateに新しく追加されている「StateTriggers」というプロパティにAdaptiveTriggerを設定する
  3. AdaptiveTriggerには「MinWindowWidth」と「MinWindowHeight」というプロパティがあり、ここに設定した幅や高さよりも大きい時にそのVisualStateへ遷移する。<AdaptiveTrigger MinWindowWidth="600" />は「画面幅が600ピクセル以上なら」という意味になる
  4. (3)の条件の場合の処理をVisualState.Settersの中に記述する
  5. GridView1.ItemTemplateの値に"{StaticResource GridViewTemplate}"と指定する。StaticResourceではリスト2(2)で定義した「GridViewTemplate」を参照させる
  6. 次の新しい条件をVisualState.StateTriggers内に記述する
  7. <AdaptiveTrigger MinWindowWidth="0" />で「画面幅が0ピクセル以上なら」という意味になる
  8. (7)の条件の処理をVisualState.Setters内に記述する
  9. GridView1.ItemTemplateの値に"{StaticResource GridViewPhoneTemplate}"と指定する。StaticResourceではリスト2(5)で定義した「GridViewPhoneTemplate」を参照させる

リスト3のように編集すると、MainPage.xamlのデザイン画面は図4のようになります。

プログラムコードの記述(MainPage.xaml.vb)

次に、ソリューションエクスプローラーから「MainPage.xaml」を展開し、「MainPage.xaml.vb」をダブルクリックしてデザイン画面にコードを表示してリスト4のように編集します。

リスト4: プログラムコード(MainPage.xaml.vb)

‘ XML文書を扱うため、System.Xml.Linq名前空間をインポートしておきます。
Imports System.Xml.Linq

‘ ImageInfoクラス内に、文字列型の「画像名」プロパティを定義しておきます。このプロパティ
‘ 名がリスト2の(4)と(7)の中でSourceプロパティにバインドされています。
Public Class ImageInfo
    Property 画像名 As String
End Class

Public NotInheritable Class MainPage
    Inherits Page

‘ ●ページがアクティブになった時の処理
    Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs)
       ‘ XElementクラス型の変数xmldocを宣言し、XElement.Loadメソッドで
‘ 「photo_etc.xml」ファイル読み込みます。
        Dim xmldoc As XElement = XElement.Load("photo_etc.xml")

      ‘ ImageInfoクラス型の新しいリストであるmyImageInfoオブジェクトを作成します。
        Dim myImageInfo As List(Of ImageInfo) = New List(Of ImageInfo)

      ‘ Descendantsメソッドですべての子孫要素である、「情報」内の値を変数resultに格納し
‘ ながら、以下の処理を行います。

‘ 新しいImageIfoクラスの、「画像名」プロパティにXML文書の「画像名」要素の値を指定
‘ します。ソリューションエクスプローラー内のImageフォルダーにある画像を指定するには
‘ "ms-appx:///Image/"
‘ と指定します。
‘ この値の指定された、ImageInfoクラスを、AddメソッドでmyImageInfoオブジェクトに
‘ 追加します。
        For Each result In From c In xmldoc.Descendants("情報") Select c
            myImageInfo.Add(New ImageInfo With {.画像名 = "ms-appx:///Image/" & result.Element("画像名").Value})
        Next

     ‘ GridView1コントロールのItemsSourceにmyImageInfoオブジェクトを指定します。
     ‘ これで、GridViewの中に画像が表示され、マウスホールやタッチでスクロールが可能になります。
        GridView1.ItemsSource = myImageInfo
        MyBase.OnNavigatedTo(e)
    End Sub
End Class

App.xaml.vbの中のフレームレートカウンタにはFalseを指定しておいてください。

ここで、App.xaml.vbのフレームレートカウンタの設定も「False」に変更しておきましょう。詳細は第3回(http://thinkit.co.jp/story/2015/10/06/6442)の「コントロールの配置」の項を参照してください。それでは、編集したリスト4を実行してみましょう。「23”Desktop(1920×1080)100%スケール」を選択し、ローカルコンピューターを選択します。実行結果は図5のようになります。図5の状態から画面の幅を狭くすると図6のように表示されます。

次に、エミュレーターで表示させてみましょう。「6“Phone(1920×1080)250%スケール」を選択し、「ローカルコンピューター」の箇所を「Mobile Emulator 10.0.10240.0 WVGA 4 inch 512MB」に変更して実行すると、図7のようにエミュレーター内に画像が表示されます。

いかがでしょうか。皆さんの環境でも動作を確認できたでしょうか。なお、今回のサンプルファイルはこちらからダウンロードできます(UniversalApp5.zip)。

今回はここまでです。今回は、DataTemplateを2個用意し、その中に画面サイズが広い場合と狭い場合の画像の表示方法を定義して、DataTemplateを切り替えることで表示方法を変えてみました。このDataTemplateはよく利用されるので、ぜひ覚えておきましょう。

次回は最終回です。MapControlを使って、筆者の所在地の近所をさまざまな形で表示する方法を解説します。お楽しみに。

薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています