2013-07-20 55 views
3

我在WP8的LongListSelector中顯示圖像集合,並且我已經實現了使用LLS的ItemRealized事件的well known lazy loading pattern在LayoutMode中使用LongListSelector進行延遲加載= Grid

在下面的代碼中,OnItemRealized函數會針對圖片集合中的每個項目調用 - 即使對於明顯不在屏幕中的項目。在這種情況下,24個項目適合屏幕,但LLS實現了40個項目,這觸發了ViewModel的ResumeGetPictures()。當圖片集合改變時(INotifyCollectionChanged),LLS也會實現這些項目,直到它用完了項目,觸發下一個ResumeGetPictures() - 這將一直持續到ViewModel無法加載更多項目。

只要LLS在LayoutMode = List中,所有似乎都沒問題。但是當我切換到網格時,控件似乎吞噬了列表中的每個項目並立即實現。無法進行任何類型的延遲加載。

我希望我只是做了一件非常非常錯誤的事情 - 雖然我懷疑是因爲我已經三重檢查了一切,就像我說的切換到「列表」,立即解決了問題 - 不幸的是沒有一個照片庫的選項分類。

視圖模型:

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

查看代碼隱藏

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(); 
    } 
} 

XAML:

<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; 
}