WPF Async Pack 1.0

WPF Async Pack is a small library for creating asynchronous WPF applications. It's not a framework, it was created mainly for the small applications where installing heavy frameworks is just overkill. It doesn't have any dependencies and contains such the most used classes as AsyncCommand and BaseViewModel.

The library can be installed through the NuGet:

Install-Package WpfAsyncPack

The WpfAsyncPack is focused on asynchronous applications. It allows executing a long-running async code in the commands and handling asynchronously the event from the INotifyPropertyChanged.

Let's take a look at the small sample application that uses an async service for retrieving the weather.

The WeatherService is responsible for getting the current weather from the external source. In the sample we just run the Task.Delay() to simulate the long-running tasks:

internal class WeatherService
{
    public async Task<WeatherModel> GetWeatherAsync()
    {
        // ...
    }
}

The service is used in the GetWeatherCommand of the MainViewModel:

internal class MainViewModel : BaseViewModel
{
    private readonly WeatherService _service;
    private int _temperature;
    private int _wind;
    private string _condition;
 
    public MainViewModel(WeatherService service)
    {
        _service = service;
 
        InitCommand = new AsyncCommand(
            async () =>
            {
                // Some long-running initialization here.
                await Task.Delay(new TimeSpan(0, 0, 10));
            });
 
        GetWeatherCommand = new AsyncCommand(
            async () =>
            {
                // Call of the long-running external service.
                var weather = await _service.GetWeatherAsync();
 
                // Set the view model properties to display the result.
                Temperature = weather.Temperature;
                Wind = weather.Wind;
                Condition = weather.Condition;
            },
            _ => !InitCommand.IsExecuting());
    }
 
    public MainViewModel() : this(new WeatherService())
    {
    }
 
    public int Temperature
    {
        get { return _temperature; }
        set { SetProperty(ref _temperature, value); }
    }
 
    public int Wind
    {
        get { return _wind; }
        set { SetProperty(ref _wind, value); }
    }
 
    public string Condition
    {
        get { return _condition; }
        set { SetProperty(ref _condition, value); }
    }
 
    public IAsyncCommand InitCommand { get; }
 
    public IAsyncCommand GetWeatherCommand { get; }
}

There are three properties Temperature, Wind and Condition that are bound to the UI. And there are two commands: InitCommand is running when the window is loaded and does some long-running initialization of the data, and GetWeatherCommand calls the service and updates the properties with the new weather information.

Properties setters use SetProperty() of the BaseViewModel class. It automatically notifies about the property change when the new value is different from the current one.

The GetWeatherCommand can not be executed while InitCommand is running - this condition is defined in the second parameter of the constructor.

All properties and the GetWeatherCommand are bound as usual to the view. Nothing special here. The interesting part is that how we can change the UI depends on the command state. In the sample you can see how to show and hide the text that says about the execution of the initialization process:

<TextBlock Visibility="{Binding InitCommand.Execution.IsNotCompleted,
                                Converter={StaticResource BoolToVisConv}}">
  Initialization...
</TextBlock>

When the command is completed, the Execution.IsNotCompleted is updated and the TextBlock becomes hidden. Similarly, it is possible to check if the command has successfully completed or failed, the failure exception and its message, etc. and bind triggers in XAML to react on the different states.

More technical details and the full sample code can be found on the Github page.

It is planned to extend the library in the future with more useful stuff.