Xaml ObservationCollection,使用WinRT的MVVM体系结构在PCL内部的ViewModel中实现ISupportIncrementalLoading&;WP8/WinPRT支持
我将ViewModels放在PCL中,因为我正在并行开发Windows 8.1和Windows Phone应用程序。我在ViewModel中有一个作为可观察集合的列表 我在Windows8.1项目的页面中有一个GridView。我希望以增量方式从ViewModel中的列表中加载项目。通常我会在ObservaleCollection的自定义子类中实现iSupportIncrementLoading,但是,鉴于我的ViewModel在PCL中,iSupportIncrementLoading不可用(WP8不支持) 所以我的问题是,有没有人对我如何创建某种转换器有什么建议,GridView的ItemsSource绑定和my ViewModel的Observable Things属性之间的适配器或抽象层,该属性将实现ISupportIncrementalLoading,然后调用ViewModel的LoadMoreThings方法并将项传递给GridView 我觉得有一些解决方案,比如在我的视图模型PCL中创建自定义ISupportIncrementalLoading,然后将视图层委托给它Xaml ObservationCollection,使用WinRT的MVVM体系结构在PCL内部的ViewModel中实现ISupportIncrementalLoading&;WP8/WinPRT支持,xaml,windows-phone-8,windows-runtime,winrt-xaml,windows-8.1,Xaml,Windows Phone 8,Windows Runtime,Winrt Xaml,Windows 8.1,我将ViewModels放在PCL中,因为我正在并行开发Windows 8.1和Windows Phone应用程序。我在ViewModel中有一个作为可观察集合的列表 我在Windows8.1项目的页面中有一个GridView。我希望以增量方式从ViewModel中的列表中加载项目。通常我会在ObservaleCollection的自定义子类中实现iSupportIncrementLoading,但是,鉴于我的ViewModel在PCL中,iSupportIncrementLoading不可用(
谢谢最后,我使用了抽象工厂模式。事实是:
- 不能从PCL ViewModel层引用视图层,因为VM层不应与视图层相关。这样做的好处之一是,您可以创建ViewModel层的另一个使用者,而不依赖于目标平台。e、 g.在一个ViewModel库PCL项目的背面创建Windows 8和Windows Phone 8应用程序
是一个WinRT组件,它可以绑定到GridView
<代码>ObservableCollection在视图层和ViewModel层中都可用。如果您希望在应用程序内部支持增量加载(这是大型数据集的必要条件),那么您需要创建一个特殊的observedcollection
子类,该子类实现observedcollection
。我们要做的就是在ViewModel项目中创建该子类,就完成了。但是我们不能这样做,因为ISupportIncrementalLoading
仅在WinRT项目中可用ISupportIncrementalLoading
ObservableCollection
,但是视图层需要一个实现ISupportIncrementalLoading
的ObservableCollection。因此,答案是在ViewModel层中定义一个接口,该接口为ViewModel提供了它想要的确切内容;我们称之为IPortabilityFactory
。然后在视图层中定义一个名为PortabilityFactory
的IPortabilityFactory
的具体实现。在视图层中使用IoC将IPortabilityFactory
(视图模型界面)映射到PortabilityFactory
(视图层具体实现)
在ViewModel类的构造函数上,注入一个IPortabilityFactory
实例。现在ViewModel有了一个工厂,它将为它提供一个ObservableCollection
实例
现在,不再在调用工厂的视图模型中调用newobserveCollection()
。GetIncrementalCollection(…)
好了,我们已经完成了ViewModel层;现在我们需要可观察集合
的定制实现。它被称为IncrementalLoadingCollection
,在视图层中定义。它实现了ISupportIncrementalLoading
下面是代码和说明,以及ISupportIncrementalLoading的实现
在ViewModel层(PCL)中,我有一个抽象的factory界面
public interface IPortabilityFactory
{
ObservableCollection<T> GetIncrementalCollection<T>(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete);
}
公共接口IPortabilityFactory
{
ObservableCollection GetIncrementalCollection(int take、Func loadMoreItems、Action onBatchStart、Action onBatchComplete);
}
在视图层(本例中为Windows 8应用程序)中,我实现了如下具体工厂:
public class PortabilityFactory : IPortabilityFactory
{
public ObservableCollection<T> GetIncrementalCollection<T>(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete)
{
return new IncrementalLoadingCollection<T>(take, loadMoreItems, onBatchStart, onBatchComplete);
}
}
公共类PortabilityFactory:IPortabilityFactory
{
公共ObservableCollection GetIncrementalCollection(int-take、Func-loadMoreItems、Action onBatchStart、Action onBatchComplete)
{
返回新的IncrementalLoadingCollection(take、loadMoreItems、onBatchStart、onBatchComplete);
}
}
同样,在视图层中,我碰巧使用Unity作为我的IoC。创建IoC时,我将IPortabilityFactory(在PCL中)映射到PortabilityFactory(在视图层;应用程序项目中)
Container.RegisterType(新ContainerControlledLifetimeManager());
我们现在需要创建ObservableCollection的子类,下面是代码:
public class IncrementalLoadingCollection<T>
: ObservableCollection<T>, ISupportIncrementalLoading
{
private Func<int, Task<List<T>>> _loadMoreItems = null;
private Action<List<T>> _onBatchComplete = null;
private Action _onBatchStart = null;
/// <summary>
/// How many records to currently skip
/// </summary>
private int Skip { get; set; }
/// <summary>
/// The max number of items to get per batch
/// </summary>
private int Take { get; set; }
/// <summary>
/// The number of items in the last batch retrieved
/// </summary>
private int VirtualCount { get; set; }
/// <summary>
/// .ctor
/// </summary>
/// <param name="take">How many items to take per batch</param>
/// <param name="loadMoreItems">The load more items function</param>
public IncrementalLoadingCollection(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete)
{
Take = take;
_loadMoreItems = loadMoreItems;
_onBatchStart = onBatchStart;
_onBatchComplete = onBatchComplete;
VirtualCount = take;
}
/// <summary>
/// Returns whether there are more items (if the current batch size is equal to the amount retrieved then YES)
/// </summary>
public bool HasMoreItems
{
get { return this.VirtualCount >= Take; }
}
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
CoreDispatcher dispatcher = Window.Current.Dispatcher;
_onBatchStart(); // This is the UI thread
return Task.Run<LoadMoreItemsResult>(
async () =>
{
var result = await _loadMoreItems(Skip);
this.VirtualCount = result.Count;
Skip += Take;
await dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
foreach (T item in result) this.Add(item);
_onBatchComplete(result); // This is the UI thread
});
return new LoadMoreItemsResult() { Count = (uint)result.Count };
}).AsAsyncOperation<LoadMoreItemsResult>();
}
}
public类IncrementalLoadingCollection
:ObservableCollection,ISupportIncrementalLoading
{
private Func_loadmoreems=null;
私有操作_onBatchComplete=null;
私有操作_onBatchStart=null;
///
///当前要跳过多少条记录
///
private int Skip{get;set;}
///
///每批要获取的最大项目数
///
私有int Take{get;set;}
///
///检索到的上一批中的项目数
///
私有int虚拟帐户{get;set;}
///
///博士
///
///每批要带多少件
///“加载更多项”功能
public IncrementalLoadingCollection(int-take,Func-loadMoreItems,Action-BatchStart,Action-BatchComplete)
{
拿=拿;
_loadMoreItems=loadMoreItems;
_onBatchStart=onBatchStart;
_onBatchComplete=onBatchComplete;
VirtualCount=获取;
}
///
///返回是否有更多项(如果
public class IncrementalLoadingCollection<T>
: ObservableCollection<T>, ISupportIncrementalLoading
{
private Func<int, Task<List<T>>> _loadMoreItems = null;
private Action<List<T>> _onBatchComplete = null;
private Action _onBatchStart = null;
/// <summary>
/// How many records to currently skip
/// </summary>
private int Skip { get; set; }
/// <summary>
/// The max number of items to get per batch
/// </summary>
private int Take { get; set; }
/// <summary>
/// The number of items in the last batch retrieved
/// </summary>
private int VirtualCount { get; set; }
/// <summary>
/// .ctor
/// </summary>
/// <param name="take">How many items to take per batch</param>
/// <param name="loadMoreItems">The load more items function</param>
public IncrementalLoadingCollection(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete)
{
Take = take;
_loadMoreItems = loadMoreItems;
_onBatchStart = onBatchStart;
_onBatchComplete = onBatchComplete;
VirtualCount = take;
}
/// <summary>
/// Returns whether there are more items (if the current batch size is equal to the amount retrieved then YES)
/// </summary>
public bool HasMoreItems
{
get { return this.VirtualCount >= Take; }
}
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
CoreDispatcher dispatcher = Window.Current.Dispatcher;
_onBatchStart(); // This is the UI thread
return Task.Run<LoadMoreItemsResult>(
async () =>
{
var result = await _loadMoreItems(Skip);
this.VirtualCount = result.Count;
Skip += Take;
await dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
foreach (T item in result) this.Add(item);
_onBatchComplete(result); // This is the UI thread
});
return new LoadMoreItemsResult() { Count = (uint)result.Count };
}).AsAsyncOperation<LoadMoreItemsResult>();
}
}
public const string IsProcessingPropertyName = "IsProcessing";
private bool _isProcessing = false;
public bool IsProcessing
{
get
{
return _isProcessing;
}
set
{
if (_isProcessing == value)
{
return;
}
RaisePropertyChanging(IsProcessingPropertyName);
_isProcessing = value;
RaisePropertyChanged(IsProcessingPropertyName);
}
}
private IPortabilityFactory _factory = null;
public ViewModel(IPortabilityFactory factory)
{
_factory = factory;
Initialize();
}
private async void Initialize()
{
Things = _factory.GetIncrementalCollection<Thing>(10, LoadThings,
() => IsProcessing = true, BatchLoaded);
}
private void BatchLoaded(List<Thing> batch)
{
IsProcessing = false;
}
private async Task<List<Thing>> LoadThings(int skip)
{
var items = await _service.GetThings(skip, 10 /*page size*/);
return items;
}