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);