Add the ability to specifiy additional paramenters when requesting items to IncrementalLoadingCollection

This commit is contained in:
Marco Minerva 2016-10-24 12:27:40 +02:00
Родитель 21d6d11d98
Коммит 0480710c88
9 изменённых файлов: 203 добавлений и 29 удалений

Просмотреть файл

@ -6,10 +6,12 @@ public class Person
public string Name { get; set; }
}
public class PeopleSource : IIncrementalSource<Person>
public class PeopleSource : IIncrementalSource<Person, string>
{
private readonly List<Person> people;
public string Arguments { get; set; }
public PeopleSource()
{
// Creates an example collection.
@ -24,9 +26,14 @@ public class PeopleSource : IIncrementalSource<Person>
public async Task<IEnumerable<Person>> GetPagedItemsAsync(int pageIndex, int pageSize)
{
// Gets items from the collection according to pageIndex and pageSize parameters.
var result = (from p in people
select p).Skip(pageIndex * pageSize).Take(pageSize);
// Gets items from the collection according to pageIndex and pageSize parameters, taking
// care of the Arguments property.
var result = (from p in _people
select p).Skip(pageIndex * pageSize).Take(pageSize)
.Select(p => new Person
{
Name = $"{p.Name} (requested at: {Arguments})"
});
// Simulates a longer request...
await Task.Delay(1000);
@ -37,7 +44,13 @@ public class PeopleSource : IIncrementalSource<Person>
// IncrementalLoadingCollection can be bound to a GridView or a ListView. In this case it is a ListView called PeopleListView.
var collection = new IncrementalLoadingCollection<PeopleSource, Person>();
var collection = new IncrementalLoadingCollection<PeopleSource, Person, string>(() =>
{
// Simulates a method that sends additional paremeters to the source.
var now = DateTime.Now;
return Task.FromResult(now.ToString());
});
PeopleListView.ItemsSource = collection;
// Binds the collection to the page DataContext in order to use its IsLoading and HasMoreItems properties.

Просмотреть файл

@ -11,6 +11,7 @@
// ******************************************************************
using System;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml.Navigation;
@ -40,7 +41,12 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
base.OnNavigatedTo(e);
// IncrementalLoadingCollection can be bound to a GridView or a ListView. In this case it is a ListView called PeopleListView.
var collection = new IncrementalLoadingCollection<PeopleSource, Person>();
var collection = new IncrementalLoadingCollection<PeopleSource, Person, string>(() =>
{
// Simulates a method that sends additional paremeters to the source.
var now = DateTime.Now;
return Task.FromResult(now.ToString());
});
PeopleListView.ItemsSource = collection;

Просмотреть файл

@ -19,13 +19,18 @@ using System.Threading.Tasks;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// A sample implementation of the <see cref="IIncrementalSource{TSource}"/> interface.
/// A sample implementation of the <see cref="IIncrementalSource{TSource,TArgs}"/> interface.
/// </summary>
/// <seealso cref="IIncrementalSource{TSource}"/>
public class PeopleSource : IIncrementalSource<Person>
/// <seealso cref="IIncrementalSource{TSource,TArgs}"/>
public class PeopleSource : IIncrementalSource<Person, string>
{
private readonly List<Person> _people;
/// <summary>
/// Gets or sets a value indicating additional arguments used to perform data pagination (for example, they can be search paramenters).
/// </summary>
public string Arguments { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="PeopleSource"/> class.
/// </summary>
@ -55,11 +60,17 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
/// </param>
/// <returns>
/// Returns a collection of <see cref="Person"/>.
/// </returns>
public async Task<IEnumerable<Person>> GetPagedItemsAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default(CancellationToken))
{
// Gets items from the collection according to pageIndex and pageSize parameters.
// Gets items from the collection according to pageIndex and pageSize parameters, taking
// care of the Arguments property.
var result = (from p in _people
select p).Skip(pageIndex * pageSize).Take(pageSize);
select p).Skip(pageIndex * pageSize).Take(pageSize)
.Select(p => new Person
{
Name = $"{p.Name} (requested at: {Arguments})"
});
// Simulates a longer request...
await Task.Delay(1000);

Просмотреть файл

@ -33,7 +33,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
private Uri _uri;
private bool _isHttpSource;
/// <summary>
/// Gets or sets get or set the source used by the image
/// </summary>

Просмотреть файл

@ -0,0 +1,33 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Toolkit.Uwp
{
/// <summary>
/// This interface represents a data source whose items can be loaded incrementally using the specified arguments as input (for example, they can be a search parameter).
/// </summary>
/// <typeparam name="TSource">Type of collection element.</typeparam>
/// <typeparam name="TArgs">Type of input arguments.</typeparam>
/// <seealso cref="IncrementalLoadingCollection{TSource, IType}"/>
public interface IIncrementalSource<TSource, TArgs> : IIncrementalSource<TSource>
{
/// <summary>
/// Gets or sets a value of <typeparamref name="TArgs"/> type that specifies additional loading parameters.
/// </summary>
TArgs Arguments { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,90 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
namespace Microsoft.Toolkit.Uwp
{
/// <summary>
/// This class represents an <see cref="ObservableCollection{IType}"/> whose items can be loaded incrementally using the specified arguments as input (for example, they can be a search parameter).
/// </summary>
/// <typeparam name="TSource">
/// The data source that must be loaded incrementally.
/// </typeparam>
/// <typeparam name="IType">
/// The type of collection items.
/// </typeparam>
/// <typeparam name="TArgs">
/// Type of input arguments.
/// </typeparam>
/// <seealso cref="IIncrementalSource{TSource,TArgs}"/>
/// <seealso cref="ISupportIncrementalLoading"/>
public class IncrementalLoadingCollection<TSource, IType, TArgs> : IncrementalLoadingCollection<TSource, IType>
where TSource : IIncrementalSource<IType, TArgs>, new()
{
private readonly Func<Task<TArgs>> _onGetArguments;
/// <summary>
/// Initializes a new instance of the <see cref="IncrementalLoadingCollection{TSource, IType, TArgs}"/> class, specifiyng a method that will be invoked to provide additional parameters for incremental loading (for example, a search query) and, optionally, how many items to load for each data page.
/// </summary>
/// <param name="onGetArguments">
/// An asynchronous <see cref="Task"/> that will be invoked to provide additional parameters for incremental loading (for example, a search query).
/// </param>
/// <param name="itemsPerPage">
/// The number of items to retrieve for each call. Default is 20.
/// </param>
/// <param name="onStartLoading">
/// An <see cref="Action"/> that is called when a retrieval operation begins.
/// </param>
/// <param name="onEndLoading">
/// An <see cref="Action"/> that is called when a retrieval operation ends.
/// </param>
/// <param name="onError">
/// An <see cref="Action"/> that is called if an error occours during data retrieval.
/// </param>
public IncrementalLoadingCollection(Func<Task<TArgs>> onGetArguments, int itemsPerPage = 20, Action onStartLoading = null, Action onEndLoading = null, Action<Exception> onError = null)
: base(itemsPerPage, onStartLoading, onEndLoading, onError)
{
_onGetArguments = onGetArguments;
}
/// <summary>
/// Actually performs the incremental loading using the specified arguments as input.
/// </summary>
/// <param name="cancellationToken">
/// Used to propagate notification that operation should be canceled.
/// </param>
/// <returns>
/// Returns a collection of <typeparamref name="IType"/>.
/// </returns>
protected override async Task<IEnumerable<IType>> LoadDataAsync(CancellationToken cancellationToken)
{
// Before call the actual pagination method, sets the source arguments.
var args = await _onGetArguments.Invoke();
Source.Arguments = args;
var result = await Source.GetPagedItemsAsync(CurrentPageIndex++, ItemsPerPage, cancellationToken);
return result;
}
}
}

Просмотреть файл

@ -40,18 +40,28 @@ namespace Microsoft.Toolkit.Uwp
ISupportIncrementalLoading
where TSource : IIncrementalSource<IType>, new()
{
private readonly TSource _source;
/// <summary>
/// Gets a value indicating the source of incremental loading.
/// </summary>
protected TSource Source { get; }
/// <summary>
/// Gets a value indicating how many items that must be retrieved for each incremental call.
/// </summary>
protected int ItemsPerPage { get; }
/// <summary>
/// Gets or sets a value indicating The zero-based index of the current items page.
/// </summary>
protected int CurrentPageIndex { get; set; }
private readonly Action _onStartLoading;
private readonly Action _onEndLoading;
private readonly Action<Exception> _onError;
private readonly int _itemsPerPage;
private int _currentPageIndex;
private CancellationToken _cancellationToken;
private bool _isLoading;
private bool _hasMoreItems;
private CancellationToken _cancellationToken;
/// <summary>
/// Gets a value indicating whether new items are being loaded.
@ -124,13 +134,13 @@ namespace Microsoft.Toolkit.Uwp
/// </param>
public IncrementalLoadingCollection(int itemsPerPage = 20, Action onStartLoading = null, Action onEndLoading = null, Action<Exception> onError = null)
{
_source = new TSource();
Source = new TSource();
_onStartLoading = onStartLoading;
_onEndLoading = onEndLoading;
_onError = onError;
_itemsPerPage = itemsPerPage;
ItemsPerPage = itemsPerPage;
_hasMoreItems = true;
}
@ -146,6 +156,21 @@ namespace Microsoft.Toolkit.Uwp
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
=> AsyncInfo.Run((c) => LoadMoreItemsAsync(count, c));
/// <summary>
/// Actually performs the incremental loading.
/// </summary>
/// <param name="cancellationToken">
/// Used to propagate notification that operation should be canceled.
/// </param>
/// <returns>
/// Returns a collection of <typeparamref name="IType"/>.
/// </returns>
protected virtual async Task<IEnumerable<IType>> LoadDataAsync(CancellationToken cancellationToken)
{
var result = await Source.GetPagedItemsAsync(CurrentPageIndex++, ItemsPerPage, cancellationToken);
return result;
}
private async Task<LoadMoreItemsResult> LoadMoreItemsAsync(uint count, CancellationToken cancellationToken)
{
uint resultCount = 0;
@ -159,7 +184,7 @@ namespace Microsoft.Toolkit.Uwp
try
{
IsLoading = true;
data = await LoadDataAsync(count, _cancellationToken);
data = await LoadDataAsync(_cancellationToken);
}
catch (OperationCanceledException)
{
@ -198,11 +223,5 @@ namespace Microsoft.Toolkit.Uwp
return new LoadMoreItemsResult { Count = resultCount };
}
private async Task<IEnumerable<IType>> LoadDataAsync(uint count, CancellationToken cancellationToken)
{
var result = await _source.GetPagedItemsAsync(_currentPageIndex++, _itemsPerPage, cancellationToken);
return result;
}
}
}

Просмотреть файл

@ -63,8 +63,10 @@
<Compile Include="Helpers\HttpHelperResponse.cs" />
<Compile Include="Helpers\StorageFileHelper.cs" />
<Compile Include="Helpers\WeakEventListener.cs" />
<Compile Include="IncrementalLoadingCollection\IIncrementalSource.cs" />
<Compile Include="IncrementalLoadingCollection\IncrementalLoadingCollection.cs" />
<Compile Include="IncrementalLoadingCollection\IIncrementalSource{TSource,TArgs}.cs" />
<Compile Include="IncrementalLoadingCollection\IIncrementalSource{TSource}.cs" />
<Compile Include="IncrementalLoadingCollection\IncrementalLoadingCollection{TSource,IType,TArgs}.cs" />
<Compile Include="IncrementalLoadingCollection\IncrementalLoadingCollection{TSource,IType}.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Helpers\StreamHelper.cs" />
<Compile Include="Structures\HslColor.cs" />