Skip to content
This repository has been archived by the owner on Aug 27, 2020. It is now read-only.

RefreshingCollection

Mark Smith edited this page Aug 29, 2016 · 1 revision

RefreshingCollection<T>

The RefreshingCollection is an observable collection type that is populated and refreshed through an asynchronous callback. When using MVVM, most things have to be exposed through properties, which prohibits the use of async and await. This class allows you to integrate asynchronous filling of the collection through a set of callback delegates.

When you create the collection, you pass an asynchronous refresh function in the form of Func<Task<IEnumerable<T>>>. This will be called anytime a refresh is needed and the results from the call (IEnumerable<T>) will be used to populate the collection. Note that this always replaces all the existing data.

Once the refresh is complete and the collection has been populated, the normal collection change notifications will be raised.

Properties

  • BeforeRefresh : Delegate invoked before a refresh occurs. Can return a single "state" object.
  • EndRefresh : Delegate invoked after a refresh completes successfully. Passed the state object from BeforeRefresh.
  • RefreshFailed : Delegate invoke if the refresh call throws an exception.

Note that EndRefresh is not called if the refresh fails. Therefore you should make sure to duplicate any cleanup code in the RefreshFailed handler.

Methods

  • RefreshAsync : async method which initiates a refresh operation. This will replace the contents of the collection with the results of the refresh function.

Example

var todoList = new RefreshingCollection<Todo>( todoService.GetItemsAsync )
{
    // Called when refresh function fails; passed exception
    RefreshFailed = async (s, ex) => {
        IsLoadingData = false;
        await dependencyService.Get<IMessageVisualizerService>()
            .ShowMessage("Error", "Failed to get questions: " + ex.Message, "OK");
    },

    // Called before the refresh - can return single object "state"
    BeforeRefresh = s => {
        IsLoadingData = true;
        return selectedTodo;
    },

    // Called after refresh is finished, passed "state"
    AfterRefresh = (s, todo) => {
        IsLoadingData = false;
        if (todo == null)
            selectedTodo = todoList.FirstOrDefault();
        else
            selectedTodo = todoList.SingleOrDefault(t => t.Id == ((Todo)t).Id);
    }
};