WP7 – How To Extend ListBox When Reaching Last Item

06/04/2011

WP7 – How To Extend ListBox When Reaching Last Item

imageI’m building a WP7 application that contains a ListBox with search results,right now when the user reached the end of the ListBox he need to press the “Next Button” to bring more results from the server, however this is a bad solution and I wanted to extend the list automatically when the user reaches the last item on the list.

There are many way to to implement this, and here is the simplest way how to listen ListBox Vertical Offset Event and update your ListBox automatically when the user reaches the last item on the list.

Download Demo Project

So How?

Step 1: First you need to create a ListBox in your application, than register the Loaded Event of this Listbox.

public MainPage()
{
    InitializeComponent();
    ListBoxDemo.Loaded += new RoutedEventHandler(ListBoxDemo_Loaded);
}

Step 2: Than create a DependencyProperty called – ListVerticalOffsetProperty, so we can use it later to perform action upon reaching the Last Item in the Listbox.

public readonly DependencyProperty ListVerticalOffsetProperty = DependencyProperty.Register("ListVerticalOffset", 
typeof(double), typeof(MainPage),      new PropertyMetadata(new PropertyChangedCallback(OnListVerticalOffsetChanged))); public double ListVerticalOffset {    
get { return (double)this.GetValue(ListVerticalOffsetProperty); }
    set { this.SetValue(ListVerticalOffsetProperty, value); } }

Step 3: Use the following method to find the ScrollViewer object

/// <summary>
/// Finding the ScrollViewer
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="root"></param>
/// <returns></returns>
static T FindChildOfType<T>(DependencyObject root) where T : class
{
    var queue = new Queue<DependencyObject>();
    queue.Enqueue(root);
 
    while (queue.Count > 0)
    {
        DependencyObject current = queue.Dequeue();
        for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)
        {
            var child = VisualTreeHelper.GetChild(current, i);
            var typedChild = child as T;
            if (typedChild != null)
            {
                return typedChild;
            }
            queue.Enqueue(child);
        }
    }
    return null;
}

Step 4: Now we connect all the dots together, getting the FrameworkElement (the ListBox), searching for the ScrollViewer object and register to the VerticalOffset changed event.

void ListBoxDemo_Loaded(object sender, RoutedEventArgs e)
{   
   FrameworkElement element = (FrameworkElement)sender; 
    element.Loaded -= ListBoxDemo_Loaded;   
scrollViewer = FindChildOfType<ScrollViewer>(element);
    if (scrollViewer == null
   {       
throw new InvalidOperationException("ScrollViewer not found."); 
   }    

Binding binding = new Binding(); 
   binding.Source = scrollViewer;  
  binding.Path = new PropertyPath("VerticalOffset");
    binding.Mode = BindingMode.OneWay;
    this.SetBinding(ListVerticalOffsetProperty, binding); }
Step 5: Implement the OnListVerticalOffsetChanged to check if the ListBox has reached the last item and if so, create new items.
private static void OnListVerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{     
     MainPage page = obj as MainPage;
     ScrollViewer viewer = page.scrollViewer;
    //Checks if the Scroll has reached the last item based on the ScrollableHeight 
    bool atBottom = viewer.VerticalOffset >= viewer.ScrollableHeight; 
   if (atBottom)    
{      
  //ViewModel will be better........ 
       int Count = page.ListBoxDemo.Items.Count;   
     int end = Count + 10;    
    for (int i = Count; i < end; i++)    
    {                             

   page.ListBoxDemo.Items.Add("Dummy Item " + i);  
      }  
  } }

Download Demo Project

Add comment
facebook linkedin twitter email

Leave a Reply

3 comments

  1. Adam07/04/2011 ב 18:44

    Cool :)

    Some suggestions for improvements:
    1. Pack the functionality in an attached property/behavior on top of the ListBox, so that it can be re-used for everyone using this functionality – the developer will only supply the event handler to be called when the ListBox reaches the end.
    2. Make the solution work for any ItemsControl, not just a ListBox (DataGrid, ListView, ComboBox, ItemsControl…) in the attached property.
    3. Provide change notification/event popping for when reaching the beginning of the list also, and also for general “scrolling” event (raise the same information the internal ScrollViewer raises), this way some developers can do general functionality around scrolling (like showing a pop-up next to the scroll of the current items amounts each time the user scrolls).

    This problem and solution exists for all XAML related frameworks (WPF, Silverlight, WP7) – so packing it neatly will be very beneficial :)

  2. Andrey08/10/2012 ב 14:28

    You a my hero, dude. Thank you for this guide.

  3. yama12/11/2012 ב 16:13

    When I load more items, listbox doesnot show the load more items. I must scroll up, then down to see them. How to fix this ?