Xaml ObservationCollection,使用WinRT的MVVM体系结构在PCL内部的ViewModel中实现ISupportIncrementalLoading&;WP8/WinPRT支持

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不可用(

我将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,然后将视图层委托给它


谢谢

最后,我使用了抽象工厂模式。事实是:

  • 不能从PCL ViewModel层引用视图层,因为VM层不应与视图层相关。这样做的好处之一是,您可以创建ViewModel层的另一个使用者,而不依赖于目标平台。e、 g.在一个ViewModel库PCL项目的背面创建Windows 8和Windows Phone 8应用程序

  • GridView
    是一个WinRT组件,它可以绑定到
    observedcollection
    <代码>ObservableCollection在视图层和ViewModel层中都可用。如果您希望在应用程序内部支持增量加载(这是大型数据集的必要条件),那么您需要创建一个特殊的
    observedcollection
    子类,该子类实现
    ISupportIncrementalLoading
    。我们要做的就是在ViewModel项目中创建该子类,就完成了。但是我们不能这样做,因为
    ISupportIncrementalLoading
    仅在WinRT项目中可用

这个问题可以通过使用抽象工厂模式来解决。ViewModel真正想要的只是一个
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;
    }