Tag Archives: WindowsPhone7

Continuous paging in Windows Phone 7

Here’s a quick and dirty implementation of continuous paging with Windows Phone 7. These code snippets are from a project using the GalaSoft MVVM Light Toolkit and Ninject, however you can adapt to fit your model. The paging and data binding functionality is abstracted in the base class PagedListViewModelBase so that the paging functionality can be easily applied to different kinds of lists – the lists inherit from PagedObject, which has a NumberOfResults property.

XAML:

 

XAML.cs:

private void profiles_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            ((SomeViewModel)(this.DataContext)).RowTouchedCommandHandled(e); // this just calls the method in the viewmodel - you can call it directly if your aren't using MVVM
        }

SomeViewModel.cs: inherits from PagedListViewModelBase

/// This is the only view-specific code you need for rendering and paging.  All the paging and databinding is handled by PagedListViewModelBase
/// SelectionChanged handlers can go here or in the base class
 public override void GetDataFromWebService(object obj)
        {
            // Get Data:
            if (!IsLoading)
            {
                IsLoading = true;
                var svc = new ProfileWebService(_userService.Current(), webService);
                svc.GetSearchResults(CurrentPage, OnItemsRetrieved);
            }
        }

PagedListViewModelBase.cs: contains the databinding and paging functionality

protected ObservableCollection _pagedObjectList;
 
// An ObservableCollection object generates NotifyPropertyChanged events to let the UI know when to update
 public ObservableCollection PagedObjectList
        {
            get
            {
                if (_pagedObjectList == null && !IsLoading)
                {
                    if (!IsInDesignMode)
                    {
                        GetDataFromWebService(null);
                    }
                    else
                    {
                        // design mode
                        GenDesignTimeMockProfiles();
 
                        RaisePropertyChanged("PagedObjectList");
                    }
                }
                return _pagedObjectList;
            }
            set
            {
                _pagedObjectList = value;
            }
        }
 
protected int CurrentPage { get; set; }
protected bool IsLoading;
 
        ///  Handles touches from user and decided when to add the next page to the list
       public void RowTouchedCommandHandled(MouseButtonEventArgs obj)
        {
            var personalProfile = ((PagedObject)(((FrameworkElement)obj.OriginalSource).DataContext));
 
            if (personalProfile.GetType() != typeof(PersonalProfile))
                return;
 
            int index = PagedObjectList.IndexOf(personalProfile);
            Debug.WriteLine("Current index: " + index);
            Debug.WriteLine("NumberOfResults: " + personalProfile.NumberOfResults);
 
            if (!IsLoading && personalProfile.NumberOfResults > PagedObjectList.Count && index > PagedObjectList.Count - 6) // if less than six items from the end, get the next page
            {
                CurrentPage += 1;
                Debug.WriteLine("Next page: " + CurrentPage);
                GetDataFromWebService(0);
            }
        }
 
 
public abstract void GetDataFromWebService(object obj);        
 
  protected void OnItemsRetrieved(List pagedObjects, Error error)
        {
            if (error == null)
            {
                if (_pagedObjectList == null)
                {
                    _pagedObjectList = new ObservableCollection();
                }
                pagedObjects.ForEach(p => _pagedObjectList.Add(p));
 
                RaisePropertyChanged("PagedObjectList");
                IsLoading = false;
            }
            else
            {
                Error = error;
            }
        }
    }
 
/// You don't need all these conversions if you use a single type for your lists.            
/// .Net 4.0 adds support for co-variance, which allows casting a generic collection to base type
 protected void OnItemsRetrieved(List profileList, Error error)
        {
            var objList = new List();
            profileList.ForEach(objList.Add);
            OnItemsRetrieved(objList, error);
        }

PagedObject.cs:

[DataContract]
    public class PagedObject : ModelBase
    {
        /// <summary>
        /// Total number of results for this search
        /// </summary>
        [DataMember]
        public int NumberOfResults { get; set; }
    }