Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM view model and async data initialisation

I have a view model with a constructor that requires a service. I'm using GalaSoft's MvvmLight which uses a service locator to wire up the view to the view model.

SimpleIOC handles providing the service to the viewmodels constructor fine, but I somehow need to populate my viewmodel with data from a data source . My Viewmodel looks a like this:-

    public class MainPageViewModel : ViewModelBase
{
    private readonly GroupService _groupService;
    private readonly GroupFactory _groupFactory;
    private readonly ObservableCollection<GroupVM> _groupVms = new ObservableCollection<GroupVM>();


    public MainPageViewModel(Domain.Services.GroupService groupService, VMFactories.GroupFactory groupFactory)
    {
        _groupService = groupService;
        _groupFactory = groupFactory;
    }

    public async Task Init()
    {
        var groups = await _groupService.LoadGroups();
        foreach (var group in groups)
        {
            GroupVms.Add(_groupFactory.Create(group));
        }
    }

    public ObservableCollection<GroupVM> GroupVms { get { return _groupVms; } }
}

Somehow the init method needs to be called an awaited, but I don't know how best to do this? I can think of three options:-

  1. I just call Init on the constructor, but not await it (I know thats really bad practice)
  2. I call Init on ViewModelLocator object, but since I can't return a task I again can't await the init
  3. On the view's load I cast the DataContext to some sort of IAsyncViewmodel and await the init method.

I have used option 3 in a previous windows 8 store project but it just feels wrong. Any advice would be really appreciated!

Thanks

Ross

like image 465
Ross Dargan Avatar asked Dec 16 '12 16:12

Ross Dargan


1 Answers

I am curious why you consider not awaiting an async call a bad practice. In my opinion, it is not bad as long as you know what that means, that the call will be executed in the background and might return any time.

Typically what I do is that I call the async method in the constructor for design time data creation purpose and I don't await it. I just take care of raising the PropertyChanged and CollectionChanged events where needed for the bindings to be updated, and that does the trick.

Cheers Laurent

like image 124
LBugnion Avatar answered Oct 12 '22 08:10

LBugnion