I am looking for a best practice to the following setup.
A View is data bound to ViewModel (through WPF). ViewModel updates View via INotifyPropertyChanged. Model updates ViewModel via events. The Model knows about stuff from the outside-world, like how to get stuff from the internet via WebClient, and how to retrieve data from a database.
Getting and sending stuff to the outside-world should be done asynchronously in order for the UI (and by extension, the user) not to suffer from waiting on the outside-world.
What would be the best practice way to go about this?
1. The ViewModel should be responsible for calling model methods asynchronously.
This would have the advantage of being able to write stuff like
GetWebPage(string url) {
var result = await Model.GetWebPageAsync(url);
Url = result.Url;
}
in the ViewModel where Url
is a ViewModel property with INotifyPropertyChanged to update the View.
Or even
GetWebPage(string url) {
var result = await Model.GetWebPageAsync(url);
_view.Url = result.Url;
}
where we can avoid the INotifyPropertyChanged all together. Which of these ways do you prefer?
However, it might be more sensible to have the Model itself do the asynchronous work. We might want to be able to use the Model without the View and ViewModel, while still having it work asynchronously. Another argument is that, who knows better that the Model what stuff is best handled asynchronously.
2. The Model handles all the asynchronous stuff by itself. The ViewModel code becomes more like
GetWebPage(string url) {
Model.GetWebPage(url);
}
and in the Model
GetWebPage(string url) {
var result = await Model.GetWebPageAsync(url);
if (UrlChanged != null);
UrlChanged(this, new UrlChangedEventArgs(url));
}
that the ViewModel can subscribe to, and update the View accordingly.
Which of the ways do you think is the best practice?
The third way: view model makes asynchronous call, but it uses client-side service to retrieve web page, model itself is anemic (it knows nothing about outer world):
GetWebPage(string url)
{
var dataService = anyServiceLocator.GetService<IDataService>();
var result = await dataService.GetWebPageAsync(url, Model);
Url = result.Url;
}
This allows to change real data downloading algorithm, e.g. for testing purposes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With