Nel .NET Framework 3.5 SP1 è presente una nuova funzionalità, volta ad ottimizzare lo scrolling delle liste, che si attiva con la proprietà ScrollViewer.IsDeferredScrolling. Impostandola a true quando si sposta la scrollbar con il mouse non si ottiene l'immediato scrolling fino a quando non si rilascia il pulsante del mouse, evitando di caricare tutti gli elementi sfogliati.
In questo script si propone, sfruttando la tecnica degli attached behavior vista nello script #66, un modo per rendere intelligente questa funzionalità in base a quanti elementi l'ItemsControl destinatario contiene. Si definisce quindi un attached property per specificare quanti elementi massimi sono consentiti per non attivare il deferred scrolling:
public static readonly DependencyProperty AutoDeferredScrollingProperty = DependencyProperty.RegisterAttached("AutoDeferredScrolling", typeof(Int32?), typeof(ScrollViewerEx), new PropertyMetadata(null, new PropertyChangedCallback(OnAutoDeferredLoadingChanged))); public static void SetAutoDeferredScrolling(DependencyObject d, Int32? value) { d.SetValue(AutoDeferredScrollingProperty, value); } public static Int32? GetAutoDeferredScrolling(DependencyObject d) { return (Int32?)d.GetValue(AutoDeferredScrollingProperty); }
Sul cambio della proprietà AutoDeferredScrolling non resta far altro che valutare quanti elementi ci sono nella lista e impostare l'attached property IsDeferredScrolling. Si intercetta inoltre l'evento ItemsChanged così da rivalutare la condizione quando la sorgente dati cambia:
private static void OnAutoDeferredLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ItemsControl itemsControl = d as ItemsControl; if (itemsControl == null) return; // Se cambia la sorgente dati, rivaluto se applicare la proprietà itemsControl.ItemContainerGenerator.ItemsChanged += delegate(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs ex) { SetDeferredScrolling(itemsControl, (Int32?)e.NewValue); }; SetDeferredScrolling(itemsControl, (Int32?)e.NewValue); } private static void SetDeferredScrolling(ItemsControl itemsControl, Int32? max) { bool enabled = false; if (max.HasValue) enabled = (itemsControl.Items.Count > max); ScrollViewer.SetIsDeferredScrollingEnabled(itemsControl, enabled); }
L'utilizzo poi è molto banale poiché basta specificare qual'è il limite massimo di elementi prima che si attivi il deferred loading.
<ListBox ItemsSource="{Binding}" c:ScrollViewerEx.AutoDeferredScrolling="120"> </ListBox>
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.