Continúo la serie de scroll infinito. En la implementación del artículo anterior, usaba un LoadItemsResult para devolver la carga asíncrona de la fuente de datos. Sin embargo, hay ocasiones en que esto se nos queda corto, como por ejemplo cuando ocurre una excepción en la carga o queremos limitar los elementos que se van cargando. Es por ello que crearemos un nuevo tipo que implemente IAsyncOperation<LoadMoreItemsResult> que nos permita tener más control sobre lo que devolvemos. Esta interfaz dispone de un método y una propiedad:
-
GetResults: Devuelve el resultado de la operación
-
Completed: Una propiedad de tipo IAsyncOperationHandler.
La idea es sencilla. Anteriormente teníamos un método que se encargaba de obtener los datos. Ahora nosotros vamos a hacer ese método a través de esa interfaz, permitiendo el control absoluto de lo que queremos devolver. Tendremos un método asíncrono que es el encargado de obtener los datos y añadirlos al IncrementalSource (que recordemos, es una ObservableCollection) tal que así:
- private async void LoadItems(IncrementalSource<T> source, uint count)
- {
- try
- {
- var result = await SourceManager.Load(count);
- foreach (var item in result)
- {
- source.Add(item);
- }
- results.Count = count;
- asyncStatus = AsyncStatus.Completed;
- if (Completed != null)
- this.Completed(this, asyncStatus);
- }
- catch (Exception ex)
- {
- // Gesti?n de excepciones
- }
- }
Básicamente lo que hacemos es cargar los datos y cuando ya lo están:
-
Notificar cuántos elementos se han cargado.
-
Lanzar el evento Completed para notificar que la carga se ha completado. Le el objeto actual como sender y un parámetro de AsyncStatus que lo asignamos como Completed, lo cual notifica al subscriptor del evento que la parte asíncrona ya ha terminado. El resto de la clase sería así:
- public class DataAsyncLoader<T> : IAsyncOperation<LoadMoreItemsResult>
- {
- private AsyncStatus asyncStatus = AsyncStatus.Started;
- private LoadMoreItemsResult results;
- public DataAsyncLoader(IncrementalSource<T> source, uint count)
- {
- LoadItems(source, count);
- }
- public AsyncOperationCompletedHandler<LoadMoreItemsResult> Completed { get; set; }
- public LoadMoreItemsResult GetResults()
- {
- return results;
- }
- public AsyncStatus Status
- {
- get { return this.asyncStatus; }
- }
- }
Y por último y recordando el artículo anterior, en el método dentro de IncrementalSource que teníamos la carga de elementos debemos cambiarlo por:
- public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
- {
- return new DataAsyncLoader<T>(this, count);
- }
Y ya está. Con esto estamos externalizando la carga de elementos y teniendo un control absoluto de lo que ocurre antes, durante y después de la carga.