かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

程よい余白を持ったGridViewを定義しよう

Windows 8 CP時点の情報です。

グリッドアプリケーションのテンプレートでアプリケーションを作るとこんな感じの構造でアプリが作られてます。

<ScrillViewer ...>
  <GridView ... >
    ...
  </GridView>
</ScrollViewer>

要は、ScrollViewerの中にGridViewが入ってる感じです。GridView自体も中身があふれたらスクロールバーを出せるというのに。これは個人的な予測だと、メトロアプリっぽい余白を確保するためだと思うんですよね。前の記事で書いたあの余白です。

これを、確保するためにScrollViewerを置いて、その中にマージンを確保したGridViewを置いてる感じです。グリッドのアプリケーションを新規作成の状態で実行するとこんな感じです。

ここでポイントなのは、少しスクロールさせたときは左側の余白は流れて画面外に消えちゃうってところです。

単純にGridViewにマージンやパディングを設定して余白をとっちゃうと以下のように悲しい感じになってしまうのです。

余白残りっぱなし・・・そして画面下のスクロールバーが中途半端な位置にある・・・。

とりあえずこんな感じで回避

なので、ScrollViewerを置いて、その中にマージンとかを設定したGridViewを置くのは解決策の1つなのですが、ちょっとこれだとセマンティックズームに対応させようとすると動きが変な風になってしまうという問題がありました。(これについては後日書くかも)なので、GridViewのTemplateをいじる以下のようなStyleを定義してGridViewに適用することでGridView単体でも程よい余白を持ちつつスクロールしてもいい感じに見えるようにできました。

<Style x:Key="GridViewStyle" TargetType="GridView">
    <Setter Property="Padding" Value="0,0,0,10"/>
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="TabNavigation" Value="Once"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled"/>
    <Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled"/>
    <Setter Property="ScrollViewer.ZoomMode" Value="Disabled"/>
    <Setter Property="IsSwipeEnabled" Value="True"/>
    <Setter Property="ItemContainerTransitions">
        <Setter.Value>
            <TransitionCollection>
                <AddDeleteThemeTransition/>
                <ContentThemeTransition/>
                <ReorderThemeTransition/>
                <EntranceThemeTransition IsStaggeringEnabled="False"/>
            </TransitionCollection>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <WrapGrid Orientation="Vertical"/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="GridView">
                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                    <ScrollViewer x:Name="ScrollViewer" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" Padding="{TemplateBinding Padding}" TabNavigation="{TemplateBinding TabNavigation}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition Height="50"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100"/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <ItemsPresenter Grid.Column="1"/>
                        </Grid>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ポイントはTemplateのScrollViewer内にGridを置いて余白を定義しているところです。余白を定義してコンテンツを表示する領域にItemsPresenterを置いています。これを適用したGridViewは、こんな感じになります。

うん、いい感じ。