0
这听起来很奇怪,我知道使用ISupportIncrementalLoading是MVVM的视图层。在MVVM中使用ISupportIncrementalLoading的最佳做法是什么?
无论何时在ViewModel中更新集合属性,我现在都会刷新ListView的xaml.cs中的itemssource。这种需求是否还有其他(更好的)解决方案?
这听起来很奇怪,我知道使用ISupportIncrementalLoading是MVVM的视图层。在MVVM中使用ISupportIncrementalLoading的最佳做法是什么?
无论何时在ViewModel中更新集合属性,我现在都会刷新ListView的xaml.cs中的itemssource。这种需求是否还有其他(更好的)解决方案?
你好,我一直在使用MVVM模式多次使用ISupportIncrementalLoading。
我喜欢创建和独立的类封装所有的逻辑来加载所有的数据我让我在这里举一个我的类的例子,我希望这有助于。
我创建了一个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 };
});
}
}
最后,我只是叫初始加载在构造函数或别的地方我的视图模型。
this.MyEntities = new Infrastructure.Collections.MyCustomEntityAppraisalIncrementalCollection(cancelToken, 20);
await MyEntities.LoadMoreItemsAsync(1);