2013-07-20 1 views
3

WP8의 LongListSelector에 이미지 컬렉션을 표시하고 LLS의 ItemRealized 이벤트를 사용하여 well known lazy loading pattern을 구현했습니다.LayoutMode = Grid에서 LongListSelector를 사용하여 지연로드

아래의 코드에서 OnItemRealized는 Pictures 컬렉션의 모든 항목에 대해 호출됩니다. 이는 분명히 화면이 꺼진 항목에도 적용됩니다. 이 시나리오에서는 24 개의 항목이 화면에 표시되지만 LLS는 40 개의 항목을 인식하며 ViewModel의 ResumeGetPictures()를 트리거합니다. 그림 컬렉션이 변경되면 (INotifyCollectionChanged), LLS는 항목이 부족하여 다음 ResumeGetPictures()를 트리거 할 때까지 해당 항목을 인식합니다. 이는 ViewModel이 더 많은 항목을로드 할 수 없을 때까지 계속됩니다.

LLS가 LayoutMode = List에있는 한 모두 괜찮은 것처럼 보입니다. 그러나 Grid로 전환하면 컨트롤이 목록의 모든 항목을 삼켜 버리고 즉시이를 인식합니다. 어떤 종류의 게으른로드도 불가능하게 만듭니다.

내가 방금 매우 잘못된 것을했기를 바란다. 나는 모든 것을 세 번 검사했기 때문에 "List"로 전환하면 즉시 문제를 해결할 수 있다고 생각하지만 - 불행히도 일부 사진 갤러리에서는 옵션이 아닙니다. 종류.

는 뷰 모델 :

public IReactiveDerivedList<TPicture> Pictures 
{ 
    get { return pictures; } 
} 

보기 코드 숨김는 : XAML

lls.ItemRealized += OnItemRealized; 

private void OnItemRealized(object sender, ItemRealizationEventArgs e) 
{ 
    var picture = e.Container.Content as Picture; 

    if (picture != null) 
    { 
    // get index 
    var pictureIndex = lls.ItemsSource.IndexOf(picture); 

    if (pictureIndex >= lls.ItemsSource.Count * 0.95f) 
     ViewModel.ResumeGetPictures(); 
    } 
} 

:

<phone:LongListSelector Name="lls" Margin="13,-30,0,0" 
    ItemsSource="{Binding Pictures}" 
    Tap="OnListItemTapped" 
    ItemTemplate="{StaticResource ItemTemplate}"   
    IsGroupingEnabled="False" 
    LayoutMode="Grid" 
    GridCellSize="108,108"/> 
+0

, 그리고 당신의 방법을 목록의 마지막 항목을 결정합니다. 여기에 코드와 XAML을 게시해야합니다. –

+0

@ ClausJørgensen 코드가 추가되었습니다. –

+0

우선, 'Count'가 정수이므로 곱셈은 아무런 효과가 없습니다. 당신은 하나를 곱한 것일 수도 있습니다. 당신의 질문에 관해서는, 당신은 당신이 그것 내의 모든 논리를 제거한다면'OnItemRealized'가 40 번 호출된다는 말입니까? –

답변

1

나는 GE 할 수 있었다 LLS 내부의 ScrollBar를 관찰하여 원하는 효과를 얻을 수 있습니다. 나는 쉽게 다시 사용할 행동에 기능을 추출했습니다

완성도를 위해서
public class LLSIncrementalLoadingBehavior : Behavior<LongListSelector> 
    { 
    private ScrollBar llsScrollBar; 

    #region Dependency Properties 

    public static readonly DependencyProperty RequestMoreDataProperty = DependencyProperty.Register(
     "RequestMoreData", typeof(Action), typeof(LLSIncrementalLoadingBehavior), new PropertyMetadata(null, OnRequestMoreDataChanged)); 

    /// <summary> 
    /// The action to invoke to initiate loading of more data 
    /// </summary> 
    public Action RequestMoreData 
    { 
     get { return (Action) this.GetValue(RequestMoreDataProperty); } 
     set { this.SetValue(RequestMoreDataProperty, value); } 
    } 

    private static void OnRequestMoreDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((LLSIncrementalLoadingBehavior)d).RequestMoreData = (Action)e.NewValue; 
    } 

    public static readonly DependencyProperty ThresholdProperty = DependencyProperty.Register(
     "Threshold", typeof(double), typeof(LLSIncrementalLoadingBehavior), new PropertyMetadata(0.8, OnThresholdChanged)); 

    /// <summary> 
    /// A value between 0 and 1 that controls how early more data is requested. Use 1 to only trigger it at the very end 
    /// </summary> 
    public double Threshold 
    { 
     get { return (double)this.GetValue(ThresholdProperty); } 
     set { this.SetValue(ThresholdProperty, value); } 
    } 

    private static void OnThresholdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((LLSIncrementalLoadingBehavior)d).Threshold = (double)e.NewValue; 
    } 

    #endregion 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     AssociatedObject.Loaded += OnLoaded; 
    } 

    private void OnLoaded(object sender, RoutedEventArgs e) 
    { 
     llsScrollBar = VisualTreeHelperExtensions.FindFirstElementInVisualTree<ScrollBar>(AssociatedObject); 

     llsScrollBar.ValueChanged += OnLlsScrollBarValueChanged; 
    } 

    private void OnLlsScrollBarValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) 
    { 
     var bottomEdge = (float)(e.NewValue + AssociatedObject.ActualHeight); 
     var bottom = llsScrollBar.Maximum + AssociatedObject.ActualHeight; 
     var threshold = bottom * Threshold; 

     if (bottomEdge >= threshold) 
     RequestMoreData(); 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 

     if (llsScrollBar != null) 
     { 
     llsScrollBar.ValueChanged -= OnLlsScrollBarValueChanged; 
     } 
    } 
    } 

:

public static T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject 
{ 
    if (parentElement != null) 
    { 
    var count = VisualTreeHelper.GetChildrenCount(parentElement); 
    if (count == 0) 
     return null; 

    for (int i = 0; i < count; i++) 
    { 
     var child = VisualTreeHelper.GetChild(parentElement, i); 

     if (child != null && child is T) 
     return (T)child; 
     else 
     { 
     var result = FindFirstElementInVisualTree<T>(child); 
     if (result != null) 
     { 
      return result; 
     } 
     } 
    } 
    } 
    return null; 
} 
이 크게 그리드에있는 항목의 크기에 따라 달라집니다
관련 문제