在MVVM中使用ISupportIncrementalLoading的最佳实践是什么?

时间:2016-05-12 13:14:14

标签: listview mvvm scroll win-universal-app prism

这可能听起来很奇怪,我知道使用ISupportIncrementalLoading是用于MVVM的视图层。

每当ViewModel中的集合属性更新时,我现在在xaml.cs中刷新ListView的itemssource。是否还有其他(更好的)解决方案可满足这种需求?

1 个答案:

答案 0 :(得分:0)

您好我多次使用MVVM模式使用ISupportIncrementalLoading。

我喜欢创建和独立的Class,它封装了所有加载所有数据的逻辑我在这里提供了一个我希望这样做有帮助的类的例子。

我创建了一个IncrementalCollectionBase来重用我所有自定义集合中的所有代码。

  public class IncrementalCollectionBase<T> : ObservableCollection<T>,
    ISupportIncrementalLoading,
    INotifyPropertyChanged,
    IIncrementalCollection<T>, IDisposable
{
    private long totalRecordCount;



    public int PageNo { get; set; }
    public int PageSize { get; set; }
    public int PageCount { get; set; }
    public long TotalRecordCount
    {
        get
        {
            return this.totalRecordCount;
        }

        set
        {
            this.totalRecordCount = value;
            OnPropertyChanged(new PropertyChangedEventArgs("TotalRecordCount"));
        }
    }

    public IncrementalCollectionBase()
    {
        this.FeedSize = 10;
    }
    public CancellationTokenSource CancelToken { get; set; }


    public bool HasMoreItems { get; set; }


    private bool isLoading { get; set; }
    public bool IsLoading
    {
        get
        {
            return isLoading;
        }

        set
        {
            isLoading = value;
            OnPropertyChanged(new PropertyChangedEventArgs("IsLoading"));

        }
    }

    public int FeedSize { get; set; }

    public event EventHandler<LoadIncrementalCollectionChanged> OnLoadIncrementalCollectionChanged;

    public void Cancel()
    {
        try
        {
            CancelToken?.Cancel();
        }
        catch (Exception ex)
        {


        }
    }

    public virtual Task<IEnumerable<T>> LoadDataAsync()
    {
        throw new NotImplementedException();
    }

    public virtual IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        throw new NotImplementedException();
    }

    public virtual void Setup(CancellationTokenSource cancelToken = null)
    {

        CancelToken = cancelToken;
    }

    public void Dispose()
    {
        try
        {
            Cancel();
            Items.Clear();
        }
        catch (Exception)
        {


        }
    }
}

执行此操作后,我创建了自定义集合

    public class MyCustomEntityIncrementalCollection : IncrementalCollectionBase<CustomEntity>
{

    private ISearchentityService searchentityService = null;
    private bool searchMode = false;
    private string key = "";
    private bool IsFirstSearchResult = true;
    private IentityService entityService = null;
    private ILoginService loginService = null;
    private IToastService toastService = null;
    public MyCustomEntityIncrementalCollection(CancellationTokenSource cancelToken, int feedSize = 10)
    {
        Setup(cancelToken);
        this.FeedSize = feedSize;
        toastService = IoC.Get<IToastService>();
        searchentityService = IoC.Get<ISearchentityService>();
        loginService = IoC.Get<ILoginService>();
        entityService = IoC.Get<IentityService>();
    }

    private async Task<IEnumerable<CustomEntity>> Search()
    {
        try
        {
            if (IsFirstSearchResult)
            {

                var result = await searchentityService.SearchAsync(key, loginService.CurrentUser.Id, CancelToken, loginService.CurrentToken.AccessToken, 1, 50);
                if (result == null)
                {
                    toastService.ShowAsync("Sin resultados", "No se han encontrado coincidencias");
                }
                PageNo = result.paging.pageNo;
                PageCount = result.paging.pageCount;
                PageSize = result.paging.pageSize;
                TotalRecordCount = result.paging.totalRecordCount;
                IsFirstSearchResult = false;
                return result.data;
            }
            else
            {
                var result = await searchentityService.SearchAsync(key, loginService.CurrentUser.Id, CancelToken, loginService.CurrentToken.AccessToken, (PageNo + 1), 50);
                PageNo = result.paging.pageNo;
                PageCount = result.paging.pageCount;
                PageSize = result.paging.pageSize;
                TotalRecordCount = result.paging.totalRecordCount;
                return result.data;
            }
        }
        catch (Exception)
        {


        }
        return null;
    }

    public async Task TurnOnSearchMode( string keyword)
    {
        if (string.IsNullOrEmpty(keyword) || string.IsNullOrWhiteSpace(keyword))
            throw new Exception(" keyword is invalid");
        searchMode = true;
        key = keyword;
        IsFirstSearchResult = true;
        this.ClearItems();
        await Task.Delay(500);
       await LoadMoreItemsAsync(1);
    }
    public async Task TurnOffSearchMode()
    {

       searchMode = false;
        IsFirstSearchResult = true;
        key = "";
        this.ClearItems();
        await LoadMoreItemsAsync(1);
    }
    public override async Task<IEnumerable<CustomEntity>> LoadDataAsync()
    {
        try
        {
            if (this.Items.Count == 0)
            {
                var result = await entityService.MyEntities(CancelToken, loginService.CurrentToken.AccessToken, 1, FeedSize);
                if (result != null && result.data != null)
                {
                    PageNo = result.paging.pageNo;
                    PageCount = result.paging.pageCount;
                    PageSize = result.paging.pageSize;
                    TotalRecordCount = result.paging.totalRecordCount;
                    return result.data;
                }
            }
            else
            {
                var result = await entityService.MyEntities(CancelToken, loginService.CurrentToken.AccessToken, (PageNo + 1), FeedSize);

                PageNo = result.paging.pageNo;
                PageCount = result.paging.pageCount;
                PageSize = result.paging.pageSize;
                TotalRecordCount = result.paging.totalRecordCount;
                return result.data;
            }
        }
        catch (Exception)
        {


        }

        return null;
    }

    public override IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return AsyncInfo.Run(async c =>
        {
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, ( () =>
            {
                IsLoading = true;
            }));

            if (searchMode == false)
            {
                try
                {
                    var data = await LoadDataAsync();
                    if (data != null && data.Any())
                    {

                        HasMoreItems = true;
                    }
                    else
                    {
                        HasMoreItems = false;
                    }

                    if (data != null)
                    {
                        await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, (() =>
                        {

                            foreach (var item in data)
                            {

                                this.Add(item);
                            }
                        })).AsTask().ContinueWith(z => { data = null; });

                    }

                }
                catch (Exception ex)
                {

                    Debug.WriteLine("Se ha producido un error al buscar videos");
                }
            }

            else
            {
                try
                {
                    var data = await Search();
                    if (data != null && data.Any())
                    {

                        HasMoreItems = true;
                    }
                    else
                    {
                        HasMoreItems = false;
                    }

                    if (data != null)
                    {
                        await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, (() =>
                        {

                            foreach (var item in data)
                            {

                                this.Add(item);
                            }
                        })).AsTask().ContinueWith(z => { data = null; });

                    }

                }
                catch (Exception ex)
                {

                    Debug.WriteLine("Se ha producido un error al buscar videos");
                }
            }

            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, ( () =>
            {
                IsLoading = false;
            }));
            return new LoadMoreItemsResult() { Count = count };
        });

    }


}

最后,我只是在构造函数或其他地方调用View Model中的初始加载。

 this.MyEntities = new Infrastructure.Collections.MyCustomEntityAppraisalIncrementalCollection(cancelToken, 20);

await MyEntities.LoadMoreItemsAsync(1);