18

My view contains a ListView which display some data from internet, I create an async method to load data and call the method in my viewmodel's constructor. It has an warning prompt me now use await keyword.

Any other solution to load data asynchronously in the constructor?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Allen4Tech
  • 2,094
  • 3
  • 26
  • 66
  • 1
    You should show your code as well as including the actual warning in your question. – Daniel Kelley Jul 04 '14 at 10:22
  • 3
    For a solution to this, read Stephen Cleary's ["Patterns for Asynchronous MVVM Applications: Data Binding"](http://msdn.microsoft.com/en-us/magazine/dn605875.aspx) and ["Async OOP 2: Constructors"](http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html). – noseratio Jul 04 '14 at 10:22
  • Closed as duplicate. It doesn't matter whether your constructor is for a view model or whatever. The issue is the same. Constructors cannot be async. – usr Jul 05 '14 at 10:40

2 Answers2

27

There are a couple of patterns which can be applied, all mentioned in the post by Stephan Cleary.

However, let me propose something a bit different:

Since you are in a WPF application, i would use the FrameworkElement.Loaded event and bind it to a ICommand inside you ViewModel. The bounded command would be an Awaitable DelegateCommand which can be awaited. I'll also take advantage of System.Windows.Interactivity.InvokeCommandAction

View XAML:

<Grid>
 <interactivity:Interaction.Triggers>
     <interactivity:EventTrigger EventName="Loaded">
         <interactivity:InvokeCommandAction Command="{Binding MyCommand}"/>
     </interactivity:EventTrigger>
 </interactivity:Interaction.Triggers>
</Grid>

ViewModel:

public class ViewModel
{
    public ICommand MyCommand { get; set; }

    public ViewModel()
    {
        MyCommand = new AwaitableDelegateCommand(LoadDataAsync);
    }

    public async Task LoadDataAsync()
    {
        //await the loading of the listview here
    }
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
2

Personally I would delegate the loading of the data to a method e.g. Task LoadDataAsync(...) ...however if you assign the result of the async method to a field then the warning should go away. If you are calling Wait() then it is questionable whether you should be calling an async method in the first place.

See http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html for an asynchronous initialization pattern that may be of interest to you.

Ananke
  • 1,250
  • 9
  • 11
  • Oh man! Thanks for posting Cleary's Factory Pattern. I have been chasing my tail on why I can't refactor async into ViewModel. Now I can. Sweet!! – Adam Cox May 15 '17 at 07:06