2016-06-16 19 views
2

ListViewをグループ化し、リストビューをスクロールするサンプルアプリケーションを作成しました。しかし、タッチベースのデバイスをスクロールし続けると、デバイス上に指を置いている限り、次のグループ(上部の目に見えるグループの隣に)が表示されます。私の指を外すと値が修正されます。ListViewで最初に表示されるグループが正常に動作しない

public sealed partial class MainPage : Page 
    { 
     public ViewModel MyVM = new ViewModel(); 
     public MainPage() 
     { 
      this.InitializeComponent(); 

      lv.SizeChanged += (s, e) => 
      { 
       ScrollViewer sv = FindVisualChildren<ScrollViewer>(lv).FirstOrDefault(); 
       if (sv != null) 
       { 
        sv.ViewChanged += (ss, ee) => 
        { 
         IEnumerable<TextBlock> tblocks = FindVisualChildren<TextBlock>(lv).Where(x => x.Name == "tbHeader"); 
         if (tblocks != null) 
         { 
          foreach (TextBlock tblock in tblocks) 
          { 
           if (IsVisibileToUser(tblock, sv)) 
           { 
            first.Text = tblock.Text; 
            break; 
           } 
          } 
         } 
        }; 
       } 
      }; 
     } 

     private static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject 
     { 
      if (depObj != null) 
      { 
       for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
       { 
        DependencyObject child = VisualTreeHelper.GetChild(depObj, i); 
        if (child != null && child is T) 
        { 
         yield return (T)child; 
        } 

        foreach (T childOfChild in FindVisualChildren<T>(child)) 
        { 
         yield return childOfChild; 
        } 
       } 
      } 
     } 

     private bool IsVisibileToUser(FrameworkElement element, FrameworkElement container) 
     { 
      if (element == null || container == null) 
       return false; 

      if (element.Visibility != Visibility.Visible) 
       return false; 

      Rect elementBounds = element.TransformToVisual(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight)); 
      Rect containerBounds = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight); 

      return (elementBounds.Top < containerBounds.Bottom && elementBounds.Bottom > containerBounds.Top); 
     } 
    } 

public class ClassA 
    { 
     public DateTime DateTimePropertyOfClassA { get; set; } 
    } 

public class ViewModel 
    { 
     public ViewModel() 
     { 
      //return a grouped collection: 
      Grouped = from x in CollectionOfClassA group x by x.DateTimePropertyOfClassA into grp orderby grp.Key select grp; 
     } 

     public IList<ClassA> CollectionOfClassA { get; set; } = new List<ClassA>() 
     { 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-01-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-03-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-04-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-05-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-06-01")}, 
      new ClassA(){ DateTimePropertyOfClassA =DateTime.Parse("2016-07-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-08-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-09-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-11-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-12-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-03-01")}, 
      new ClassA(){ DateTimePropertyOfClassA =DateTime.Parse("2016-06-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-01-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-03-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-03-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-03-01")}, 
      new ClassA(){ DateTimePropertyOfClassA = DateTime.Parse("2016-03-01")}, 
      new ClassA(){ DateTimePropertyOfClassA =DateTime.Parse("2016-06-01")} 
     }; 

     public IEnumerable<object> Grouped { get; } 
    } 

XAML:

<Page.Resources> 
    <CollectionViewSource x:Name="cvs" 
         IsSourceGrouped="True" 
         Source="{x:Bind MyVM.Grouped, Mode=OneWay}"/> 
</Page.Resources> 

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"></RowDefinition> 
     <RowDefinition Height="*"></RowDefinition> 
    </Grid.RowDefinitions> 
    <TextBlock Name="first" HorizontalAlignment="Center" Visibility="Visible" FontSize="12"></TextBlock> 
    <ListView Grid.Row="1" Name="lv" ItemsSource="{Binding Source={StaticResource cvs}}" ScrollViewer.VerticalScrollBarVisibility="Visible"> 
     <ListView.GroupStyle> 
      <GroupStyle> 
       <GroupStyle.HeaderTemplate> 
        <DataTemplate> 
         <TextBlock x:Name="tbHeader" FontSize="15" FontWeight="Bold" Text="{Binding Key}"/> 
        </DataTemplate> 
       </GroupStyle.HeaderTemplate> 
      </GroupStyle> 
     </ListView.GroupStyle> 
    </ListView> 
</Grid> 

私は、この機能を改善するために何かできることはあるサンプルからhttps://onedrive.live.com/redir?resid=91B2B9D9EA21A110!615&authkey=!AKJV0b_q7g-YZF4&ithint=file%2czip

コード: は、ここに私のサンプルアプリですか!

+0

は、いくつかのコードスニペットを追加する代わりに考えてみましょうあなたのサンプルアプリケーションをダウンロードするためのリンク、これは人々にあなたを助けてくれるでしょう。 – Kinani

答えて

2

ScrollViewer.ViewChanged eventは、スクロール中に何度も実行されるため、コード内でIsVisibileToUserメソッドが呼び出される回数を制御することはできません。

Rect elementBoundsが動的にここに、スクロール中に変更されますが、あなたが試すことができます回避策は次のとおりです。一つだけTextBlockのサイズにScrollViewer領域を減らす、例えば:

private bool IsVisibileToUser(FrameworkElement element, FrameworkElement container) 
{ 
    if (element == null || container == null) 
     return false; 

    if (element.Visibility != Visibility.Visible) 
     return false; 

    Rect elementBounds = element.TransformToVisual(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight)); 
    Rect containerBounds = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight); 

    return (elementBounds.Top <= element.ActualHeight && elementBounds.Bottom > containerBounds.Top); 
} 
+0

私は実際に間違ったコードを投稿しました。私は戻ってきた(elementBounds.Top containerBounds.Top);それでも同じ問題がありました。問題は、非常に次のグループがスクロールされているときです。先頭のテキストブロックはIsVisibleToUserからfalseを返します。なぜなら、elementBounds.Bottomは負でcontainerBounds.Topは 'elementBounds.Bottom> containerBounds.Top'という条件に失敗します。 0 – tavier

+0

@AshishAgrawal、私はあなたの投稿されたサンプルではなく、投稿されたコードをテストしました。戻り値の条件を 'return(elementBounds.Top <= element.ActualHeight && elementBounds.Bottom> containerBounds.Top);に変更したことに注目してください。 –

+0

@AshishAgrawal、どうしたの?私のコードをテストしましたか?その他の問題? –

関連する問題