In our app (blog Park UAP), added a ListView pull-up to get more content (the GridView can also), this feature is implemented through the Isupportincrementalloading interface, which is a Windows 8 Start with the interface (of course you can do this through the ScrollViewer, just a little bit of trouble, but also to encapsulate themselves. )。
The definition of this interface is simple:
Public Interface isupportincrementalloading { boolget;} Iasyncoperation<LoadMoreItemsResult> loadmoreitemsasync (uint count); }
Loadmoreitemsasync is automatically called by the ListView (When Incrementalloadingtrigger = Incrementalloadingtrigger.edge), the Count parameter indicates how many items to fetch each time , this parameter is determined by Listview.datafetchsize and Listview.incrementalloadingthreshold, Hasmoreitems is used to tell the ListView if there are more items to load, False if Listv Iew has rolled to the end and will no longer trigger loadmoreiemsasync.
PS: In the process of using isupportincrementalloading, you will find that Loadmoreitemsasync is continuously called 2 times, and the first call is always count= 1, this is because the ListView needs to use the first project to determine the number of virtualized projects (there is a bit more about virtualization, please refer to MSDN, simply say that the effect is your listview/gridview even if you want to show tens of thousands of items, the memory will not explode). This is not a problem for sample on MSDN, because the data comes out quickly, but in applications that need to be networked you will find that there is only one project, and in a moment the other dozens of comes out again, although it is justified, but it looks a little weird, So we ignored the count parameter in the implementation and loaded a fixed number of items each time.
Realize
A simple, generic implementation is provided on MSDN, which stores data by implementing IList and then implements INotifyCollectionChanged to inform the project of changes.
Public Abstract classincrementalloadingbase:ilist, isupportincrementalloading, inotifycollectionchanged {//omitting the implementation of IList//implementation of omitting inotifycollectionchanged Public BOOLHasmoreitems {Get{returnhasmoreitemsoverride ();} } PublicWindows.foundation.iasyncoperation<loadmoreitemsresult> Loadmoreitemsasync (UINTcount) { if(_busy) {Throw NewInvalidOperationException ("Only one operation in flight at a time"); } _busy=true; returnAsyncinfo.run ((c) =Loadmoreitemsasync (c, Count)); } AsyncTask<loadmoreitemsresult> Loadmoreitemsasync (CancellationToken C,UINTcount) { Try { varItems =awaitLoadmoreitemsoverrideasync (c, Count); varBaseIndex =_storage. Count; _storage. AddRange (items); Notifyofinserteditems (BaseIndex, items. Count); return NewLoadmoreitemsresult {Count = (UINT) items. Count}; } finally{_busy=false; } } }
To simplify the implementation, we have inherited the observablecollection<t> to achieve the purpose of storing items, notifying changes, and adding onloadmorestarted and onloadmorecompleted events, facilitates updating the UI (such as a progress bar).
Public Abstract classIncrementalloadingbase<t>: observablecollection<t>, isupportincrementalloading { Public BOOLHasmoreitems {Get{returnhasmoreitemsoverride ();} } PublicIasyncoperation<loadmoreitemsresult> Loadmoreitemsasync (UINTcount) { if(_busy) {Throw NewInvalidOperationException ("Only one operation in flight at a time"); } _busy=true; returnAsyncinfo.run ((c) =Loadmoreitemsasync (c, Count)); } protected AsyncTask<loadmoreitemsresult> Loadmoreitemsasync (CancellationToken C,UINTcount) { Try { //Load Start Event if( This. Onloadmorestarted! =NULL) { This. Onloadmorestarted (count); } varItems =awaitLoadmoreitemsoverrideasync (c, Count); Additems (items); //Load Complete Event if( This. Onloadmorecompleted! =NULL) { This. onloadmorecompleted (items = =NULL?0: Items. Count); } return NewLoadmoreitemsresult {Count = items = =NULL?0: (UINT) items. Count}; } finally{_busy=false; } } Public Delegate voidLoadmorestarted (UINTcount); Public Delegate voidLoadmorecompleted (intcount); Public Eventloadmorestarted onloadmorestarted; Public Eventloadmorecompleted onloadmorecompleted; /// <summary> ///Add new items, the reason is virtual is to facilitate special requirements, such as non-repetition/// </summary> protected Virtual voidAdditems (ilist<t>items) { if(Items! =NULL) { foreach(varIteminchitems) { This. ADD (item); } } } protected AbstractTask<ilist<t>> Loadmoreitemsoverrideasync (CancellationToken C,UINTcount); protected Abstract BOOLhasmoreitemsoverride (); protected BOOL_busy =false; }
Such a simple incremental load base class would have to implement the Loadmoreitemsoverrideasync method in the subclass, and bind to the Listview.itemssource.
Use the following two images (note the number changes in the top right corner of the home page and the scroll bar at the bottom right):
Do you like MVVM? Then you need to modify it on the basis of this class, separating the logic from the data and using it as a collection, and here is a simple implementation.
Public classIncrementalloadingcollection<t>: observablecollection<t>, isupportincrementalloading{//here in order to simply use the tuple<ilist<t>, bool> as the return value, the first item is the new item collection, whether the second item has more, or you can customize the entity classfunc<UINT, Task<tuple<list<t>,BOOL>>> _datafetchdelegate =NULL; PublicIncrementalloadingcollection (func<UINT, Task<tuple<list<t>,BOOL>>>datafetchdelegate) { if(Datafetchdelegate = =NULL)Throw NewArgumentNullException ("datafetchdelegate"); This. _datafetchdelegate =datafetchdelegate; } Public BOOLHasmoreitems {Get; Private Set; } PublicIasyncoperation<loadmoreitemsresult> Loadmoreitemsasync (UINTcount) { if(_busy) {Throw NewInvalidOperationException ("Only one operation in flight at a time"); } _busy=true; returnAsyncinfo.run ((c) =Loadmoreitemsasync (c, Count)); } protected AsyncTask<loadmoreitemsresult> Loadmoreitemsasync (CancellationToken C,UINTcount) { Try { if( This. Onloadmorestarted! =NULL) { This. Onloadmorestarted (count); } //We ignore the cancellationtoken, because we do not need to cancel at the moment, we need to add varresult =await This. _datafetchdelegate (count); varItems =result. Item1; if(Items! =NULL) { foreach(varIteminchitems) { This. ADD (item); } } //do you have more This. Hasmoreitems =result. ITEM2; //Load Complete Event if( This. Onloadmorecompleted! =NULL) { This. onloadmorecompleted (items = =NULL?0: Items. Count); } return NewLoadmoreitemsresult {Count = items = =NULL?0: (UINT) items. Count}; } finally{_busy=false; } } Public Delegate voidLoadmorestarted (UINTcount); Public Delegate voidLoadmorecompleted (intcount); Public Eventloadmorestarted onloadmorestarted; Public Eventloadmorecompleted onloadmorecompleted; protected BOOL_busy =false;}
Now this guy becomes a collection, when you create an instance, pass in the corresponding proxy, and then bind it to the ItemsSource in your view.
var New incrementalloadingcollection<String> (count + = { // corresponding get more logic return task.run (() = Tuple.create (new list<string ) I am false data "true"); });
Summary
Incremental loading can give users a smoother experience when they need to display large amounts of data, and by using isupportincrementalloading, we only need to implement the logic to fetch the data, and when the call does not need our attention. We welcome your continued attention.
Windows Phone Store App Link:
http://www.windowsphone.com/zh-cn/store/app/Blog Park-UAP/500F08F0-5BE8-4723-AFF9-A397BEEE52FC
Windows Store App Link:
http://apps.microsoft.com/windows/zh-cn/app/c76b99a0-9abd-4a4e-86f0-b29bfcc51059
GitHub Open Source Link:
Https://github.com/MS-UAP/cnblogs-UAP
MSDN Sample Code:
Https://code.msdn.microsoft.com/CNBlogs-Client-Universal-9c9692d1
Blog Park Client (Universal App) Development essay--Incremental load (incremental loading)