Async, just baked right into the framework... lovely

Async Binding

You know when sometimes you hear something and it reminds you about something you used to know?

Carl Franklin's 'Better Know a Framework' snippet on Dot Net Rocks recently reminded me that I used to know about the IsAsync property on WPF Bindings.

Here's how it works:

Say you have a public property on your viewmodel whose getter goes off and does some long-running piece of work to get its data, such as calling into a web service or database. If you create a Binding to that property. then doing that work will freeze the UI and give your users a sad face. Like this :(

The good news is that right out the box WPF allows you to push that long-running piece of work onto a background thread and safely marshall the result back into the UI simply by setting the IsAsync preoperty on that Binding.

The UI thread will continue running and the data will populate when it's good and ready.

This does create the additional issue of having UI controls that appear to be blank, but in actual fact are trying to populate, but we have a solution for that too... Set the FallbackValue on the Binding to be something that can act as a plcaceholder whilst you're waiting for the real data to return.

Here's how you might populate a ListBox

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    Title="Things" Height="350" Width="525">
    <Window.Resources>
        <x:Array x:Key="loadingItems" Type="{x:Type System:String}">
            <System:String>Loading....</System:String>
        </x:Array>
    </Window.Resources>
    <Grid>
        <ListBox
            x:Name="listBox"
            ItemsSource="{Binding AllThings, IsAsync=True, FallbackValue={StaticResource loadingItems}}" />
    </Grid>
</Window>

and the ViewModel:

public class ViewModel : ObservableObject
{
    private ObservableCollection<string> _allThings;

    public ViewModel()
    {
        AllThings = new ObservableCollection<string>(new[] { "A thing", "another thing", "some thing" });
    }

    public ObservableCollection<string> AllThings
    {
        get
        {
            Thread.Sleep(3000); // Hit web service, or database or whatever here...
            return _allThings;
        }
        private set
        {
            if (value == _allThings) return;
            _allThings = value;
            RaisePropertyChanged(() => AllThings);
        }
    }
}

Enjoy :)

xaml wpf async binding
Posted by: Ian Randall
Last revised: 01 Mar, 2011 10:40 p.m.

Comments

No comments yet. Be the first!

Your Comments

Used for your gravatar. Not required. Will not be public.
Posting code? Indent it by four spaces to make it look nice. Learn more about Markdown.

Preview