GridView のスクロールが右端まで到達したかどうかを判別する

Windows Phone の場合、画面をスクロールして一番下まで到達したかどうかの判別を行うことができます。

同様のことを Windows 8 で行う場合、ScrollViewer の ViewChanged イベントを使って実装できます。

ただ、GridView を使う場合、ScrollViewer の ViewChanged を触るためには、以下の方法を使う必要があります。

Grid テンプレートを使う場合、まず GroupedItemPage.xaml を開いていただき、GridView (標準では x:name = ItemGridView となっています) の中にstyle=”{StaticResource GridViewStyle1}” と追記いただき、そのページのリソース部分に、以下のタグをご記入ください。  

  <Style x:Key="GridViewStyle1" 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.IsHorizontalRailEnabled" Value="False"/>
 <Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled"/>
 <Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="False"/>
 <Setter Property="ScrollViewer.ZoomMode" Value="Disabled"/>
 <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
 <Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True"/>
 <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" BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}" IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" TabNavigation="{TemplateBinding TabNavigation}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}" ViewChanged="OnViewChanged" >
 <ItemsPresenter HeaderTemplate="{TemplateBinding HeaderTemplate}" Header="{TemplateBinding Header}" HeaderTransitions="{TemplateBinding HeaderTransitions}" Padding="{TemplateBinding Padding}"/>
 </ScrollViewer>
 </Border>
 </ControlTemplate>
 </Setter.Value>
 </Setter>
 </Style>
 
 
 

これはGridViewのテンプレートを、ハイライトの部分だけ変更したものになります。

(GridView のテンプレートを確認するには、Blend を開いていただき、itemGridView を右クリックして [テンプレートの編集] -> [コピーして編集] で確認いただけます)

次に ViewChangedイベントを取って以下のように処理することで右端まで行ったかどうかを判別することができます。

  private async void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
 {
 var sv = GetChild<ScrollViewer>(itemGridView);
 
 if (sv != null)
 {
 var horizontalOffset = sv.HorizontalOffset;
 var maxhorizontalOffset = sv.ExtentWidth - sv.ViewportWidth;
 
 if (maxhorizontalOffset < 0 || horizontalOffset == maxhorizontalOffset)
 {
 pageTitle.Text = "右端まで行きました";
 }
 }
 }
 
 private T GetChild<T>(DependencyObject obj) where T : FrameworkElement
 {
 var count = VisualTreeHelper.GetChildrenCount(obj);
 for (int i = 0; i < count; i++)
 {
 var child = VisualTreeHelper.GetChild(obj, i);
 if (child is T)
 {
 return child as T;
 }
 
 var result = GetChild<T>(child);
 if (result != null)
 {
 return result;
 }
 }
 return null;
 }
 

 以上です。