michielpost.nl

Windows 8: Binding a ProgressBar to a long running Task

13-09-2012

This blog is part of a series of blog post about the Q42.WinRT open source toolkit for Windows 8.

A really common scenario in a Windows 8 / WinRT app (or any app) is to load data from the web or do some other action that takes a while to complete. While loading our data, we also have to update the UI to show some sort of loader so the user knows a bunch of data is being loaded.
With Windows 8 and the Async / Task model it's really easy to do asynchronous task on another thread and not block the UI. But how do we show the user what's going on with the long running task?

This blog post will show an easy way to use databinding in combination with Tasks.

Let's say we have a service which loads an RSS feed. The service interface might look like this. This is a task that returns a List of RssItems:
Task<List<RssItem>> LoadRssFeed();

In out UI (XAML), we have a
<ProgressBar x:Id="progressbar" />.

We want to show the progressbar when we are loading our RssFeed and stop the progressbar when we're finished loading.

One way to do this is like this:
progressbar.IsIndeterminate = true;
var result = await LoadRssFeed();
progressbar.IsIndeterminate = false;

That works, but what if we're in a MVVM scenario and want to use proper databinding?

We can make a property IsBusy and bind the progressbar to that property:
<ProgressBar IsIndeterminate={Binding IsBusy} />

We can then use this in our ViewModel:
IsBusy = true;
var result = await LoadRssFeed();
IsBusy = false;

We're now using the power of databinding, that's nice. But it's still not fool proof. What if the LoadRssFeed() call throws an error? Then the loading will never stop. So we have to add a try/catch block. And what if we want to show some text when there's an error loading the RssFeed?

try
{
  IsBusy = true;
  var result = await LoadRssFeed();
}
catch
{
  IsError = true;
}
finally
{
  IsBusy = false;
}

That works! But it's a lot of code and we have to do this every time for all our long running tasks.

Meet the DataLoader.

The DataLoader is a wrapper around a Task<T>. It has properties like IsFinished, IsBusy and IsError which support databinding.

On our ViewModel, we create a DataLoader property:
public DataLoader DataLoader { get; set; }

In the constructor of our ViewModel, we initialize the DataLoader:
DataLoader = new DataLoader();

And finally, we can load our RssFeed, but with the DataLoader wrapped around it:
var result = await DataLoader.LoadAsync(() => LoadRssFeed());

In the UI / XAML, we can bind to the DataLoader's properties:
<ProgressBar IsIndeterminate={Binding DataLoader.IsBusy} />

And we get other properties, like IsFinished and IsError for free. This way we have a lot less code to write, and we can use the power of databinding and Async Tasks in Windows 8!

The DataLoader is part of the open source Q42.WinRT library. A fully working sample is available in the Q42.WinRT library on GitHub:
https://github.com/Q42/Q42.WinRT

Comments


No comments yet.

New Comment

Name
E-mail (not published)
Comment
Enter the code shown: