我的ViewModels在PCL内,因为我正在并行地开发Windows8.1和Windows应用程序。我的ViewModel中有一个ObservableCollection列表。
我在Windows8.1项目中的页面中有一个GridView。我希望从我的ViewModel中的内容列表中递增地加载项。通常,我会在ObservableCollection的自定义子类中实现ObservableCollection,但是,考虑到我的ViewModel在PCL中,ISupportIncrementalLoading是不可用的(WP8不支持它)。
因此,我的问题是,有没有人建议我如何在GridView的GridView绑定和我的ViewModel的可观察的Things属性之间创建某种转换器、适配器或抽象层,从而实现ISupportIncrementalLoading,然后调用ViewModel的LoadMoreThings方法并将项传递给GridView。
我觉得有一些解决方案,比如在我的视图模型中创建一个自定义的ISupportIncrementalLoading,然后将视图层委托给它。
谢谢
发布于 2013-11-28 09:47:52
最后,我使用了抽象的工厂模式。事实是:
GridView是一个可以绑定到ObservableCollection<T>的WinRT组件。ObservableCollection<T>可以在视图层和ViewModel层中使用。如果您希望在应用程序中支持增量加载(对于大型数据集来说这是必需的),那么您需要创建一个实现ObservableCollection<T>的特殊子类来实现ISupportIncrementalLoading。我们要做的就是在ViewModel项目中创建这个子类,您就完成了。但是我们不能这样做,因为ISupportIncrementalLoading只在WinRT项目中可用。这个问题可以通过抽象工厂模式来解决。ViewModel真正想要的只是一个ObservableCollection<T>,但是视图层需要一个实现ISupportIncrementalLoading的ObservableCollection。因此,答案是在ViewModel层中定义一个接口,让ViewModel准确地得到它想要的东西;让我们把它称为IPortabilityFactory。然后在视图层中定义一个IPortabilityFactory的具体实现,称为PortabilityFactory。使用视图层中的IoC将IPortabilityFactory (ViewModel接口)映射到PortabilityFactory (查看层具体文件)。
在ViewModel类的构造函数上,注入一个IPortabilityFactory实例。现在,ViewModel有了一个工厂,它将为它提供一个ObservableCollection<T>实例。
现在,不是在new ObservableCollection<Thing>()中调用ViewModel,而是调用factory.GetIncrementalCollection<Thing>(...)。
好的,我们已经完成了ViewModel层;现在我们需要ObservableCollection<T>的自定义实现。它被称为IncrementalLoadingCollection,它在视图层中定义。它实现了ISupportIncrementalLoading。
下面是代码和解释,以及ISupportIncrementalLoading的实现。
在ViewModel层中,我有一个抽象的工厂接口。
public interface IPortabilityFactory
{
ObservableCollection<T> GetIncrementalCollection<T>(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> 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);
}
}同样,在视图层中,我碰巧在我的IoC中使用了统一。创建IoC时,我将IPortabilityFactory (在PCL中)映射到PortabilityFactory (视图层;应用程序项目)。
Container.RegisterType<IPortabilityFactory, PortabilityFactory>(new 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>();
}
}IncrementalLoadingCollection的构造函数要求获得由ViewModel通过工厂提供的四个参数:
在ViewModel层中,我的ViewModel有一个构造函数,它接受IPortabilityFactory对象:
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;
}我希望这能帮上忙。
https://stackoverflow.com/questions/20243139
复制相似问题