Artykuły

A A A
Drukuj Ekportuj do PDF
Opublikowane: 2011.12.29 8:00 | Tomasz Telepko | Aktualizacja: 2011.12.29 7:33

Dynamiczne doczytywanie elementów w ListBoxie

Artykuł opisuje w jaki sposób możemy stworzyć mechanizm automatycznego pobierania kolejnej paczki danych wyświetlanych w ListBoxie w momencie gdy zostanie on przewinięty do samego dołu.

O co chodzi z tym dynamicznym doczytywaniem?

Jakiś czas temu miałem okazję napisać raczej prostą aplikację na WP7, która m.in. pobierała dane z jakiejś strony internetowej (w tej chwili mniejsza o szczegóły dotyczące samej aplikacji). Ponieważ dane na tej stronie były stronicowane i każda strona miała inny URL, a ja nie chciałem też zaciągać całości za jednym razem, chciałem zrobić jakieś stronicowanie w aplikacji.

Oczywiście mogłem zrobić jakieś przyciski dla poszczególnych stron, przycisk pobierający następną paczkę czy coś w tym stylu, ale lepsze wydało mi się rozwiązanie gdzie w momencie przewinięcia listy do samego dołu automatycznie zaczną pobierać się kolejne elementy.

Nie ma lekko...

Z początku zadanie wydaje się łatwe, wystarczy tylko jakoś sprawdzić czy ListBox został przewinięty do końca. No właśnie, jakoś... tylko jak? Przeglądając właściwości kontrolki ListBox dla WP7 nie znajdziemy nic, co by nam pomogło. Można by myśleć o kombinowaniu i np. wstawieniu ListBoxa do środka ScrollViewera i sprawdzania, czy on został przewinięty do końca, tylko że... on też nie ma takiej właściwości.

Trzeba było sięgnąć trochę głębiej. Tu się przyznam że rozwiązanie to nie jest mojego autorstwa, bo zanim zdążyłem na nie wpaść (zakładając że bym wpadł ;)) znalazłem je gdzieś na forach. Niemniej myślę że jest warte przedstawienia.

...ale da się zrobić

Rozwiązanie polega na stworzeniu własnej kontrolki dziedziczącej po ListBoxie, i "dobrania się" do ScrollBara siedzącego w jej wnętrzu.

public class DynamicListBox : ListBox
{
    private ScrollBar verticalScrollbar;
    private double lastValue;
 
    public event EventHandler NeedMoreData;
    protected virtual void RaiseNeedMoreData()
    {
        if (NeedMoreData != null)
            NeedMoreData(thisEventArgs.Empty);
    }
 
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate(); 
         
        ScrollViewer viewer = base.GetTemplateChild("ScrollViewer"as ScrollViewer;
        viewer.Loaded += (sender, args) =>
        {
            FrameworkElement viewerRoot = (FrameworkElement)VisualTreeHelper.GetChild(viewer, 0);
            verticalScrollbar = ((ScrollBar)viewerRoot.FindName("VerticalScrollBar"));
            if (verticalScrollbar != null)
                verticalScrollbar.ValueChanged += new RoutedPropertyChangedEventHandler<double>(VerticalScrollbar_ValueChanged);
        };
    }
 
    private void VerticalScrollbar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        ScrollBar scrollBar = (ScrollBar)sender;
        if (e.NewValue == scrollBar.Maximum && e.NewValue != lastValue)
        {
            lastValue = e.NewValue;
            RaiseNeedMoreData();
        }
    }
}

Jak widać z pomocą przychodzi nam fakt, że:

  1. Możemy dostać się do wewnętrznych części kontrolki znając ich nazwę i używając chronionej metody GetTemplateChild.
  2. Kontrolki mają na tyle standardowe nazwy, że łatwo się do nich dobrać.

Czyli jak wynika z kodu, wystarczy dostać się do ScrollBara, który znajduje się (a raczej jest częścią) ScrollViewera, który z kolei jest częścią ListaBoxa. Teraz wystarczy już tylko przypiąć się do zdarzenia ValueChanged, i w momencie gdy wartość ScrollBara będzie maksymalna, wywołać nasze zdarzenie NeedMoreData które zasygnalizuje naszej aplikacji że lista potrzebuje kolejnej paczki danych.

Podsumowanie

Jak widać rozwiązanie nie jest skomplikowane, wystarczy tylko wiedzieć jak dostać się do wewnętrznych części kontrolek. Mam nadzieję że komuś się to przyda. Oprócz WP7 można go użyć zarówno w Silverlight jak i WPF, choć niewykluczone że tam da się to zrobić łatwiej bo mogą być dostępne jakieś dodatkowe metody/właściwości.


Komentarze 1 Masz uwagi do tej strony? Napisz

estebano 2012.01.01 0:32
0 oceń pozytywnie   oceń negatywnie 0
avatar
 
Z pozoru banalne. Jednak dzięki za art bo wskazuje ciekawy obszar do przeszukiwania sieci i msdn. Inspirujący choć prosty :)

Dodaj komentarz

avatar

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.

Autor Tomasz Telepko
avatar
 

Załóż konto
CodeGuru to miejsce dla każdego programisty. Przez lata portal rozwijany był siłami społeczności i to właśnie społeczność programistów jest tutaj najważniejsza. CG od wielu lat gromadzi wokół siebie coraz większą grupę pasjonatów. Warto być jej częścią!

Dowiedz się więcej o CodeGuru

Geek Club - Windows Phone

 

MetroOne

Idź na górę strony