PRISM 4 MVVM data paging

Topics: Prism v4 - Silverlight 4
Nov 5, 2010 at 7:35 PM

Hi,

I have been looking all over the net to find a good example on how I can use Prism 4(drop 10) with a MVVM approach and have data paged on the screen. Most of the example I found would result in bringing the complete data on to the client and then have it paged on client when we go the MVVM way. is there any example on the net I can use to understand how to build it?

Regards, Kiran

 

Nov 5, 2010 at 9:13 PM

Hi,

There is not guidance on this topic in Prism out-of-the-box. But you can find the following forum thread interesting:

Hope this helps.

Fernando Antivero
http://blogs.southworks.net/fantivero

Nov 6, 2010 at 9:53 AM

Hi,

Thanks for the link, I tried to follow all these discussions but closest I found for the topic was here  http://blogs.msdn.com/b/brada/archive/2009/09/07/business-apps-example-for-silverlight-3-rtm-and-net-ria-services-july-update-viewmodel.aspx. but looks like this post is not out of date and I was ubable to find the class PagedEntityCollectionView. any idea if this is renamed or replaced with another class that I can use?

Thanks, Kiran

Nov 10, 2010 at 7:40 PM

Hi Kiran,

As I mentioned, there is no guidance on this topic in Prism out-of-the-box. If you need to to provide paging capabilities to a collection, you could take a look at the following documentation section on MSDN: IPagedCollectionView.

Additionally, you can find the following John Papa's post interesting: WCF RIA Services - Hands On Lab. Although it is not strictly related to MVVM, the proposed application implements paging.

Hope this helps.

Fernando Antivero
http://blogs.southworks.net/fantivero

Nov 11, 2010 at 11:24 AM

You can do something like that

1 - MVVM Class:

public class MyMVVM
{
  protected ObservableCollection<TEntity> _entities;
  protected PagedEntityView<TEntity> _entitiesView;

  public MyMVVM()
  {
     _entities = new ObservableCollection<TEntity>();
     _entitiesView = new PagedEntityView<TEntity>(_entities);  
  }
{

2 - The Paged EntityView Class

 public class PagedEntityView<TEntity> : NotificationObject,
        IPagedCollectionView,
        ICollectionView,
        IEditableCollectionView,
        INotifyCollectionChanged,
        IEnumerable<TEntity>
        where TEntity : Entity, IEditableObject, new()
    {

        #region Fields and properties
        
        private readonly ObservableCollection<TEntity> _itens;
        private TEntity _currentAddItem;
        private TEntity _currentEditItem;

        private SortDescriptionCollection _sortDescriptions;

        private IEnumerable<TEntity> Enumerable
        {
            get { return _itens; }
        }

        /// <summary>
        /// Retorna a quantidade da cole��o
        /// </summary>
        public int Count
        {
            get { return _itens.Count; }
        }

        #endregion

        #region Constructors

        public PagedEntityView(ObservableCollection<TEntity> itens)
        {
            _itens = itens;
            _itens.CollectionChanged += (sender, args) =>
                                        {
                                            RaiseCollectionChangedEvent(args);
                                            if ((!IsCurrentBeforeFirst ||
                                                 args.Action != NotifyCollectionChangedAction.Add) &&
                                                 args.Action != NotifyCollectionChangedAction.Reset) return;
                                            MoveCurrentToFirst();
                                            RaisePropertyChanged(() => IsCurrentBeforeFirst);
                                        };
        }

        #endregion

        #region IPagedCollectionView

        public bool MoveToFirstPage()
        {
            return (MoveToPage(0));
        }

        public bool MoveToLastPage()
        {
            return (MoveToPage(TotalItemCount / PageSize));
        }

        public bool MoveToNextPage()
        {
            return (MoveToPage(PageIndex + 1));
        }

        public bool MoveToPreviousPage()
        {
            return (MoveToPage(PageIndex - 1));
        }

        public bool MoveToPage(int pageIndex)
        {
            if (pageIndex == PageIndex || pageIndex < 0 || pageIndex > TotalItemCount / PageSize) return false;

            var args = new PageChangingEventArgs(PageIndex);

            try
            {
                IsPageChanging = true;
                RaisePageChangingEvent(args);

                if (!args.Cancel)
                {
                    _pageIndex = pageIndex;
                    RaiseLoadDataEvent(EventArgs.Empty);

                    RaisePropertyChanged(() => PageIndex);
                    RaisePageChangedEvent(args);

                    return (true);
                }
                return (false);
            }
            finally
            {
                IsPageChanging = false;
            }
        }

        public bool CanChangePage
        {
            get { return (true); }
        }

        private bool _isPageChanging;
        public bool IsPageChanging
        {
            get { return (_isPageChanging); }
            set
            {
                if (_isPageChanging == value) return;
                _isPageChanging = value;
                RaisePropertyChanged(() => IsPageChanging);
            }
        }

        private int _itemCount;
        public int ItemCount
        {
            get { return (_itemCount); }
            set
            {
                if (_itemCount == value) return;
                _itemCount = value;
                RaisePropertyChanged(() => ItemCount);
            }
        }

        private int _pageIndex;
        public int PageIndex
        {
            get { return (_pageIndex); }
            set
            {
                if (_pageIndex == value) return;
                _pageIndex = value;
                RaisePropertyChanged(() => PageIndex);
            }
        }

        private int _pageSize = 10; // Default page size = 10
        public int PageSize
        {
            get { return (_pageSize); }
            set
            {
                if (_pageSize == value) return;
                _pageSize = value;
                RaisePropertyChanged(() => PageSize);
            }
        }

        private int _totalItemCount;

        public int TotalItemCount
        {
            get { return (_totalItemCount); }
            set
            {
                if (_totalItemCount == value) return;
                _totalItemCount = value;
                RaisePropertyChanged(() => TotalItemCount);
            }
        }

        public event EventHandler<EventArgs> PageChanged;
        public event EventHandler<PageChangingEventArgs> PageChanging;
        public event EventHandler<EventArgs> LoadData;

        private void RaisePageChangedEvent(PageChangingEventArgs args)
        {
            var handler = PageChanged;
            if (handler != null)
                handler(this, args);
        }

        private void RaiseLoadDataEvent(EventArgs args)
        {
            var handler = LoadData;
            if (handler != null)
                handler(this, args);
        }

        private void RaisePageChangingEvent(PageChangingEventArgs args)
        {
            var handler = PageChanging;
            if (handler != null)
                handler(this, args);
        }

        private void RaiseCollectionChangedEvent(NotifyCollectionChangedEventArgs args)
        {
            var handler = CollectionChanged;
            if (handler != null)
                handler(this, args);
        }


        #endregion

        #region Implementation of IEnumerable

        /// <summary>
        /// Returns an enumerator that iterates through the collection.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
        /// </returns>
        public IEnumerator<TEntity> GetEnumerator()
        {
            return (_itens.GetEnumerator());
        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        #region Implementation of INotifyCollectionChanged

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        #endregion

        #region Implementation of ICollectionView

        /// <summary>
        /// Indicates whether the specified item belongs to this collection view. 
        /// </summary>
        /// <returns>
        /// true if the item belongs to this collection view; otherwise, false.
        /// </returns>
        /// <param name="item">The object to check. </param>
        public bool Contains(object item)
        {
            return (Enumerable.Contains((TEntity)item));
        }

        /// <summary>
        /// Recreates the view.
        /// </summary>
        public void Refresh()
        {
            Refreshed(this, EventArgs.Empty);
        }

        /// <summary>
        /// Enters a defer cycle that you can use to merge changes to the view and delay automatic refresh. 
        /// </summary>
        /// <returns>
        /// The typical usage is to create a using scope with an implementation of this method and then include multiple view-changing calls within the scope. The implementation should delay automatic refresh until after the using scope exits. 
        /// </returns>
        public IDisposable DeferRefresh()
        {
            return (new DeferRefreshHelper(Refresh));
        }

        /// <summary>
        /// Sets the first item in the view as the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/>.
        /// </summary>
        /// <returns>
        /// true if the resulting <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> is an item in the view; otherwise, false.
        /// </returns>
        public bool MoveCurrentToFirst()
        {
            return (MoveCurrentToPosition(0));
        }

        /// <summary>
        /// Sets the last item in the view as the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/>.
        /// </summary>
        /// <returns>
        /// true if the resulting <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> is an item in the view; otherwise, false.
        /// </returns>
        public bool MoveCurrentToLast()
        {
            return (MoveCurrentToPosition(Count - 1));
        }

        /// <summary>
        /// Sets the item after the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> in the view as the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/>.
        /// </summary>
        /// <returns>
        /// true if the resulting <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> is an item in the view; otherwise, false.
        /// </returns>
        public bool MoveCurrentToNext()
        {
            if (CurrentPosition < Count - 1)
            {
                return (MoveCurrentToPosition(CurrentPosition + 1));
            }
            return (false);
        }

        /// <summary>
        /// Sets the item before the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> in the view to the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/>.
        /// </summary>
        /// <returns>
        /// true if the resulting <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> is an item in the view; otherwise, false.
        /// </returns>
        public bool MoveCurrentToPrevious()
        {
            if (CurrentPosition > 0)
            {
                return this.MoveCurrentToPosition(this.CurrentPosition - 1);
            }

            return false;
        }

        /// <summary>
        /// Sets the specified item in the view as the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/>.
        /// </summary>
        /// <returns>
        /// true if the resulting <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> is an item in the view; otherwise, false.
        /// </returns>
        /// <param name="item">The item to set as the current item.</param>
        public bool MoveCurrentTo(object item)
        {
            if (IsEmpty || Equals(CurrentItem, item)) return (false);

            for (var i = 0; i < Count; ++i)
            {
                if (Enumerable.ElementAt(i).Equals(item))
                {
                    var args = new CurrentChangingEventArgs();
                    RaiseCurrentChangingEvent(args);

                    if (!args.Cancel)
                    {
                        CurrentItem = item;
                        CurrentPosition = i;

                        RaisePropertyChanged(() => CurrentPosition);
                        RaiseCurrentChangedEvent(EventArgs.Empty);

                        return (true);
                    }
                    return (false);
                }
            }
            return (false);
        }

        /// <summary>
        /// Sets the item at the specified index to be the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> in the view.
        /// </summary>
        /// <returns>
        /// true if the resulting <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> is an item in the view; otherwise, false.
        /// </returns>
        /// <param name="position">The index to set the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> to.</param>
        public bool MoveCurrentToPosition(int position)
        {
            if (IsEmpty) return (false);


            var args = new CurrentChangingEventArgs(true);
            RaiseCurrentChangingEvent(args);

            if (args.Cancel) return false;

            if (position == -1)
            {
                CurrentItem = null;
            }
            else
            {
                CurrentItem = Enumerable.ElementAt(position);
            }

            CurrentPosition = position;

            RaisePropertyChanged(() => CurrentItem);
            RaisePropertyChanged(() => CurrentPosition);
            RaiseCurrentChangedEvent(EventArgs.Empty);

            return (true);
        }

        /// <summary>
        /// Gets or sets the cultural information for any operations of the view that may differ by culture, such as sorting.
        /// </summary>
        /// <returns>
        /// The culture information to use during culture-sensitive operations. 
        /// </returns>
        public CultureInfo Culture
        {
            get { throw new NotSupportedException(); }
            set { throw new NotSupportedException(); }
        }

        /// <summary>
        /// Gets the underlying collection.
        /// </summary>
        /// <returns>
        /// The underlying collection.
        /// </returns>
        public IEnumerable SourceCollection
        {
            get { return (_itens); }
        }

        /// <summary>
        /// Gets or sets a callback that is used to determine whether an item is appropriate for inclusion in the view. 
        /// </summary>
        /// <returns>
        /// A method that is used to determine whether an item is appropriate for inclusion in the view.
        /// </returns>
        public Predicate<object> Filter
        {
            get { throw new NotSupportedException(); }
            set { throw new NotSupportedException(); }
        }

        /// <summary>
        /// Gets a value that indicates whether this view supports filtering by way of the <see cref="P:System.ComponentModel.ICollectionView.Filter"/> property.
        /// </summary>
        /// <returns>
        /// true if this view supports filtering; otherwise, false.
        /// </returns>
        public bool CanFilter
        {
            get { return (false); }
        }

        /// <summary>
        /// Gets a collection of <see cref="T:System.ComponentModel.SortDescription"/> instances that describe how the items in the collection are sorted in the view.
        /// </summary>
        /// <returns>
        /// A collection of values that describe how the items in the collection are sorted in the view.
        /// </returns>
        public SortDescriptionCollection SortDescriptions
        {
            get { return _sortDescriptions ?? (_sortDescriptions = new SortDescriptionCollection()); }
        }

        /// <summary>
        /// Gets a value that indicates whether this view supports sorting by way of the <see cref="P:System.ComponentModel.ICollectionView.SortDescriptions"/> property.
        /// </summary>
        /// <returns>
        /// true if this view supports sorting; otherwise, false.
        /// </returns>
        public bool CanSort
        {
            get { return (true); }
        }

        /// <summary>
        /// Gets a value that indicates whether this view supports grouping by way of the <see cref="P:System.ComponentModel.ICollectionView.GroupDescriptions"/> property.
        /// </summary>
        /// <returns>
        /// true if this view supports grouping; otherwise, false.
        /// </returns>
        public bool CanGroup
        {
            get { return (false); }
        }

        /// <summary>
        /// Gets a collection of <see cref="T:System.ComponentModel.GroupDescription"/> objects that describe how the items in the collection are grouped in the view. 
        /// </summary>
        /// <returns>
        /// A collection of objects that describe how the items in the collection are grouped in the view. 
        /// </returns>
        public ObservableCollection<GroupDescription> GroupDescriptions
        {
            get { return (null); }
        }

        /// <summary>
        /// Gets the top-level groups.
        /// </summary>
        /// <returns>
        /// A read-only collection of the top-level groups or null if there are no groups.
        /// </returns>
        public ReadOnlyObservableCollection<object> Groups
        {
            get { return (null); }
        }

        /// <summary>
        /// Gets a value that indicates whether the view is empty.
        /// </summary>
        /// <returns>
        /// true if the view is empty; otherwise, false.
        /// </returns>
        public bool IsEmpty
        {
            get { return (_itens.Count == 0); }
        }

        /// <summary>
        /// Gets the current item in the view.
        /// </summary>
        /// <returns>
        /// The current item in the view or null if there is no current item.
        /// </returns>
        public object CurrentItem
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the ordinal position of the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> in the view.
        /// </summary>
        /// <returns>
        /// The ordinal position of the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> in the view.
        /// </returns>
        public int CurrentPosition
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets a value that indicates whether the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> of the view is beyond the end of the collection.
        /// </summary>
        /// <returns>
        /// true if the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> of the view is beyond the end of the collection; otherwise, false.
        /// </returns>
        public bool IsCurrentAfterLast
        {
            get { return (false); }
        }

        /// <summary>
        /// Gets a value that indicates whether the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> of the view is beyond the start of the collection.
        /// </summary>
        /// <returns>
        /// true if the <see cref="P:System.ComponentModel.ICollectionView.CurrentItem"/> of the view is beyond the start of the collection; otherwise, false.
        /// </returns>
        public bool IsCurrentBeforeFirst
        {
            get { return (CurrentItem == null); }
        }

        public event CurrentChangingEventHandler CurrentChanging;
        public event EventHandler CurrentChanged;

        private void RaiseCurrentChangedEvent(EventArgs args)
        {
            var handler = CurrentChanged;
            if (handler != null)
                handler(this, args);
        }

        private void RaiseCurrentChangingEvent(CurrentChangingEventArgs args)
        {
            var handler = CurrentChanging;
            if (handler != null)
                handler(this, args);
        }

        #endregion

        #region Implementation of IEditableCollectionView

        /// <summary>
        /// Adds a new item to the underlying collection.
        /// </summary>
        /// <returns>
        /// The new item that is added to the collection.
        /// </returns>
        public object AddNew()
        {
            CommitNew();
            CommitEdit();

            _currentAddItem = new TEntity();
            _itens.Add(_currentAddItem);

            _currentAddItem.BeginEdit();
            MoveCurrentToFirst();

            return (_currentAddItem);
        }

        /// <summary>
        /// Ends the add transaction and saves the pending new item.
        /// </summary>
        public void CommitNew()
        {
            if (IsAddingNew)
            {
                _currentAddItem.EndEdit();
                _currentAddItem = null;
            }
        }

        /// <summary>
        /// Ends the add transaction and discards the pending new item.
        /// </summary>
        public void CancelNew()
        {
            if (IsAddingNew)
            {
                _currentAddItem.CancelEdit();
                MoveCurrentToLast();

                Remove(_currentAddItem);
                _currentAddItem = null;
            }
        }

        /// <summary>
        /// Removes the item at the specified position from the collection.
        /// </summary>
        /// <param name="index">Index of item to remove.</param>
        public void RemoveAt(int index)
        {
            if (index < 0 || index >= this._itens.Count)
            {
                throw new IndexOutOfRangeException("index must be at least 0 and less than the Count");
            }

            Remove(_itens.ElementAt(index));
        }

        /// <summary>
        /// Removes the specified item from the collection.
        /// </summary>
        /// <param name="item">The item to remove.</param>
        public void Remove(object item)
        {
            var entity = item as TEntity;

            if (entity != null)
            {
                _itens.Remove(entity);

                if (IsEmpty)
                {
                    CurrentItem = null;
                    CurrentPosition = -1;

                    RaiseCurrentChangingEvent(new CurrentChangingEventArgs(false));

                    RaisePropertyChanged(() => CurrentItem);
                    RaisePropertyChanged(() => CurrentPosition);
                    RaisePropertyChanged(() => IsCurrentBeforeFirst);

                    RaiseCurrentChangedEvent(EventArgs.Empty);
                }
                else
                {
                    MoveCurrentTo(CurrentPosition);
                }
            }
        }

        /// <summary>
        /// Begins an edit transaction on the specified item.
        /// </summary>
        /// <param name="item">The item to edit.</param>
        public void EditItem(object item)
        {
            CommitNew();
            CommitEdit();

            _currentEditItem = item as TEntity;
            MoveCurrentTo(item);

            if (_currentEditItem != null)
            {
                _currentEditItem.BeginEdit();
            }
        }

        /// <summary>
        /// Ends the edit transaction and saves the pending changes.
        /// </summary>
        public void CommitEdit()
        {
            if (IsEditingItem)
            {
                _currentEditItem.EndEdit();
                _currentEditItem = null;
            }
        }

        /// <summary>
        /// Ends the edit transaction and, if possible, restores the original value of the item.
        /// </summary>
        public void CancelEdit()
        {
            if (IsEditingItem)
            {
                _currentEditItem.CancelEdit();
            }
        }

        /// <summary>
        /// Gets or sets the position of the new item placeholder in the collection view.
        /// </summary>
        /// <returns>
        /// An enumeration value that specifies the position of the new item placeholder in the collection view.
        /// </returns>
        public NewItemPlaceholderPosition NewItemPlaceholderPosition
        {
            get { return (NewItemPlaceholderPosition.None); }
            set { throw new NotSupportedException(); }
        }

        /// <summary>
        /// Gets a value that indicates whether a new item can be added to the collection.
        /// </summary>
        /// <returns>
        /// true if a new item can be added to the collection; otherwise, false.
        /// </returns>
        public bool CanAddNew
        {
            get { return (true); }
        }

        /// <summary>
        /// Gets a value that indicates whether an add transaction is in progress.
        /// </summary>
        /// <returns>
        /// true if an add transaction is in progress; otherwise, false.
        /// </returns>
        public bool IsAddingNew
        {
            get { return (_currentAddItem != null); }
        }

        /// <summary>
        /// Gets the item that is being added during the current add transaction.
        /// </summary>
        /// <returns>
        /// The item that is being added if <see cref="P:System.ComponentModel.IEditableCollectionView.IsAddingNew"/> is true; otherwise, null.
        /// </returns>
        public object CurrentAddItem
        {
            get { return (_currentAddItem); }
        }

        /// <summary>
        /// Gets a value that indicates whether an item can be removed from the collection.
        /// </summary>
        /// <returns>
        /// true if an item can be removed from the collection; otherwise, false.
        /// </returns>
        public bool CanRemove
        {
            get { return (true); }
        }

        /// <summary>
        /// Gets a value that indicates whether the collection view can discard pending changes and restore the original values of an edited object.
        /// </summary>
        /// <returns>
        /// true if the collection view can discard pending changes and restore the original values of an edited object; otherwise, false.
        /// </returns>
        public bool CanCancelEdit
        {
            get { return (true); }
        }

        /// <summary>
        /// Gets a value that indicates whether an edit transaction is in progress.
        /// </summary>
        /// <returns>
        /// true if an edit transaction is in progress; otherwise, false.
        /// </returns>
        public bool IsEditingItem
        {
            get { return (_currentEditItem != null); }
        }

        /// <summary>
        /// Gets the item in the collection that is being edited.
        /// </summary>
        /// <returns>
        /// The item that is being edited if <see cref="P:System.ComponentModel.IEditableCollectionView.IsEditingItem"/> is true; otherwise, null.
        /// </returns>
        public object CurrentEditItem
        {
            get { return (_currentEditItem); }
        }

        #endregion

        #region Public Events

        public event EventHandler Refreshed = delegate { };

        #endregion

        #region Private class DeferRefreshHelper

        private class DeferRefreshHelper : IDisposable
        {
            private Action _callback;

            public DeferRefreshHelper(Action callback)
            {
                _callback = callback;
            }

            public void Dispose()
            {
                _callback();
            }
        }

        #endregion

    }

 

Nov 13, 2010 at 11:55 AM

lucianotcorreia,

Thanks for the solution. I have one question if you can help me understand.

in your ViewModel there is this code

     _entities = new ObservableCollection<TEntity>();
     _entitiesView = new PagedEntityView<TEntity>(_entities); 

It looks to me that we firstload all the entities and then let it page, is this correct? would it not be a lot of unnesery fetching of data upfront?

Regards, Kiran

 

Nov 13, 2010 at 8:34 PM

You need a LoadData Methods in your viewmodel, something lije that:

 

public void LoadData()
{
  var data = GETDATA;

  foreach(var item in data)
  {
     _entities.Add(item);
   }
}

You need to bind the DataGrid and and The DataPager to the _entitiesView

Nov 14, 2010 at 5:08 AM

I understand that, my question is that we are loading all the data upfront and loos the benifit of using the DomainDataSource. suppose if my table has 100,000 records, this would mean I have to load all the data in my LoadData method.

Is that correct, or is  there a way we can make it smarter and load only pages we need.

Regards, Kiran

Nov 16, 2010 at 1:53 PM
Edited Nov 16, 2010 at 3:20 PM

that class is a "DomainDataSource" u dont need to use that DomainDataSource Anymor.

If u configure the Paged to load only 10 itens, it will load only 10 itens...

I ll put my View Model Base Class:

1 - this is my view model base:

 

 public abstract class ViewModelBase : NotificationObject
    {

        #region Fields
 
        protected IDataService _dataService;

        #endregion

        #region Constructors

        [ImportingConstructor]
        protected ViewModelBase(IDataService dataService)
        {
            _dataService = dataService;
        }

        #endregion

        #region Properties and fields

        private bool _isLoading;
        public bool IsLoading
        {
            get { return (_isLoading); }
            set
            {
                if (_isLoading == value) return;
                _isLoading = value;
                RaisePropertyChanged(() => IsLoading);
            }
        }

        private string _busyContent;
        public string BusyContent
        {
            get { return (_busyContent); }
            set
            {
                if (_busyContent == value) return;
                _busyContent = value;
                RaisePropertyChanged(() => BusyContent);
            }
        }

        #endregion

        #region Abstract methods

        public abstract void LoadData();

        #endregion

    }

 

2 - this a Generic ViewModel:

 

  public abstract class ViewModelBase<TEntity> : ViewModelBase, IViewModel, ISecurityPermission
        where TEntity : Entity, IEditableObject, new()
    {

        #region Protected fields

        protected ObservableCollection<TEntity> _entities;
        protected PagedEntityView<TEntity> _entitiesView;

        #endregion

        #region Constructors

        [ImportingConstructor]
        public ViewModelBase(IDataService dataService)
            : base(dataService)
        {
            _entities = new ObservableCollection<TEntity>();
            _entitiesView = new PagedEntityView<TEntity>(_entities);

            _entitiesView.LoadData += (sender, args) => LoadData();
            _entitiesView.Refreshed += (sender, args) => LoadData();

            // Todo: Pegar o "PageSize" de par�metros
            _entitiesView.PageSize = 10;
        }

        #endregion

        #region Properties

        public PagedEntityView<TEntity> Entities
        {
            get { return (_entitiesView); }
        }

        private TEntity _selectedEntity;
        public TEntity SelectedEntity
        {
            get { return (_entitiesView.CurrentItem as TEntity); }
            set
            {
                if (_selectedEntity != value)
                {
                    _entitiesView.MoveCurrentTo(value);
                    _selectedEntity = value;
                    RaisePropertyChanged(() => SelectedEntity);
                }
            }
        }

        #endregion

        #region Private fields

        private string _entityName;

        #endregion

        #region IViewModel implementation

        public string ScreenDescriptionPlural { get; set; }
        public string ScreenDescriptionSingular { get; set; }

        public void SubmitChanges()
        {
            _dataService.Context.SubmitChanges((submitOperation) =>
                                               {
                                                   if (submitOperation.HasError) return;

                                                   MessageBoxDialog.Show(submitOperation.Error.Message, "Erro",
                                                       MessageBoxDialogButtons.OK,
                                                       MessageBoxDialogIcons.Critical,
                                                       (s, e) => { });
                                                   submitOperation.MarkErrorAsHandled();
                                                   LoadData();
                                               }, null);
        }

        public void RejectChanges()
        {
            _dataService.Context.RejectChanges();
            IsLoading = false;
        }

    

        private bool _canSubmitChanges;
        public bool CanSubmitChanges
        {
            get { return _canSubmitChanges; }
            set
            {
                if (_canSubmitChanges == value) return;
                _canSubmitChanges = value;
                RaisePropertyChanged(() => CanSubmitChanges);
            }
        }

        private string _idFilter;
        public string IdFilter
        {
            get { return _idFilter; }
            set
            {
                if (_idFilter == value) return;
                _idFilter = value;
                RaisePropertyChanged(() => IdFilter);
                _entitiesView.PageIndex = 0;
                LoadData();
            }
        }

        private string _textFilter;
        public string TextFilter
        {
            get { return _textFilter; }
            set
            {
                if (_textFilter == value) return;
                _textFilter = value;
                RaisePropertyChanged(() => TextFilter);
                _entitiesView.PageIndex = 0;
                LoadData();
            }
        }

        private string _textFilterField;
        public string TextFilterField
        {
            get { return _textFilterField; }
            set
            {
                if (_textFilterField == value) return;
                _textFilterField = value;
                RaisePropertyChanged(() => TextFilterField);
            }
        }

        #endregion

        #region Public abstract methods

        public abstract void AddEntity(TEntity entity);

        public abstract void DeleteEntity(TEntity entity);

        public abstract EntityQuery<TEntity> OrderBy(EntityQuery<TEntity> query, bool isFirst, string propertyName, bool descending);

        public abstract Expression<Func<TEntity, bool>> BuildWhere(string textFilterField, string textFilter);

        public abstract override void LoadData();

        #endregion
}

 

 

3- thats is a implementation of the view model (my table name is Linhas)

 

[Export]
    [PartCreationPolicy(CreationPolicy.Shared)]
    [RegionMemberLifetime(KeepAlive = false)]
    public class LinhasViewModel : ViewModelBase<Linha>
    {

        #region Costructors

        public static int count = 0;
        
        [ImportingConstructor]
        public LinhasViewModel(IDataService dataService) : base(dataService)
        {
            LinhasViewModel.count++;
        }

        #endregion

        #region Override methods

        public override void AddEntity(Linha entity)
        {
            throw new NotImplementedException();
        }

        public override void DeleteEntity(Linha entity)
        {
            throw new NotImplementedException();
        }

        public override EntityQuery<Linha> OrderBy(EntityQuery<Linha> query, bool isFirst, string propertyName, bool descending)
        {
            throw new NotImplementedException();
        }

        public override Expression<Func<Linha, bool>> BuildWhere(string textFilterField, string textFilter)
        {
            throw new NotImplementedException();
        }

        public override void LoadData()
        {
            IsLoading = true;

            var query = _dataService.Context.GetLinhasQuery();

            query = query.OrderBy(linha => linha.Descricao);

            if (_entitiesView.PageSize > 0)
            {
                query = query.Skip(_entitiesView.PageSize * _entitiesView.PageIndex);
                query = query.Take(_entitiesView.PageSize);
            }

            query.IncludeTotalCount = true;

            _dataService.Context.Load(query,
                                     (linhasLoadOpe) =>
                                     {
                                         if (linhasLoadOpe.HasError)
                                         {
                                             // Todo: Mostrar erro numa tela padr�o
                                             MessageBox.Show(linhasLoadOpe.Error.ToString());
                                             return;
                                         }

                                         _entities.Clear();
                                         foreach (var entity in linhasLoadOpe.Entities)
                                         {
                                             _entities.Add(entity);
                                         }
                                         
                                         _entitiesView.MoveCurrentToFirst();

                                         _entitiesView.TotalItemCount = linhasLoadOpe.TotalEntityCount;
                                         _entitiesView.ItemCount = linhasLoadOpe.TotalEntityCount;
                                         
                                         IsLoading = false;
                                     }, null);
        }

        #endregion

    }

 

Look at the LoadData Method, it does de paging.

 

You need to bind your controls (datagrid and datapager) to the property called: 'Entities"

Nov 16, 2010 at 4:52 PM

lucianotcorreia,

Now I understand, sound like a good way to handle it, I espically like the generic ViewModel base. I am going to give this a try first thing tomorrow.

Thanks, Kiran

 

Aug 8, 2014 at 5:14 AM
Hi lucianotcorreia & Kiran
Is this only work with Silverlight ? I tried this in WPF. When I set the reference to 'System.Windows.Data.dll' in Silverlight SDK folder (for IPagedCollectionView) It gives following compilation error.
Unknown build error, 'Cannot resolve dependency to assembly 'System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.

I'm using Visual Studio 2010 Ultimate. If it is not possible with WPF is there any other solution for loading data dynamically in WPF ?

Thanks