Reputation: 6021
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:-
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
Upvotes: 8
Views: 4007
Reputation: 6662
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
Upvotes: 8
Reputation: 456322
I'm not as familiar with MvvmLight as I once was, but I've tried to deal with async
constructors in a variety of ways.
Option (1) has error handling complexities. Option (3) forces InitAsync
to be accessible.
I prefer an async
factory approach (e.g., option (2), where the DataContext
would stay null
until the VM initialization completes), but it sounds like ViewModelLocator
won't work for that. So (for now) you have to choose between an async
factory that does not use IoC and one of the other options (1 or 3) that are not ideal.
Personally, I would toss out IoC for VM/View binding (I never use IoC for that anyway; my views depend on my VMs) and use an async
factory method. However, the other options are perfectly viable if you want to stay with IoC. For VMs I think option (1) would be slightly better than option (3) if you always had a top-level try
/catch
in your InitAsync
methods.
Upvotes: 1