views:

80

answers:

2

I'm having a bit of trouble deciding on the best way to get the data from the web service to the UI.

Given the asynchronous nature of WebClient how would you build this?

  • Model uses WebClient to talk to webservice
  • ViewModel asks model for data
  • View is databound to ViewModel

On the Async complete event I need to get that data back out of the model to the ViewModel, these are the things I've thought about.

  1. I could fire an event in the Model that the ViewModel subscribes to.
  2. I could perhaps do something with passing around callbacks?
  3. Or should I be doing a second level of INotifyPropertyChanged events between the ViewModel and the Model?
  4. Or am I very confused and completely misunderstanding MVVM?
+2  A: 

It depends on how purist you want to be about MVVM.

You could treat the API itself as your Model, in which case the ViewModel has the WebClient and on Async completed you'd set your properties (and they would in turn fire PropertyChanged from within their setters).

Or you can have a local Model that has the WebClient code in it (as it sounds like you have). In this case, my personal approach would to have a "ModelUpdated" event that fires from the Async complete event. (Your option 1).

Your ViewModel can listen for this event, and either fire a PropertyChanged(null) to have the View ask for ALL properties, or fire multiple PropertyChanged events. Remember you're not restricted to firing PropertyChanged from within your setters. There's nothing stopping you from having a method like

private void FireMultipleProperties(){
NotifyPropertyChanged("Property1");
NotifyPropertyChanged("Property2");
NotifyPropertyChanged("Property3");
}

So you could call that method when the Model finishes populating, and your UI will call update each property when they are fired. You'd only need to do this if you have a ton of properties and don't want to fire them all at once with PropertyChanged(null).

Ben Gracewood
Thanks Ben. I think I want to keep the local models as they'll be used across a number of ViewModels.I didn't know about the PropertyChanged(null), that's pretty cool.
Will
A: 

I think you need to introduce a new layer into your architecture; a service layer. Usually, I pass in my relevant services to my ViewModel and the ViewModel does the handling of the async calls and showing busy states and all that fun stuff.

For instance, if you have a Product Model, and ProductListViewModel with a collection of products and maybe a search command, then you would introduce a ProductSearchService (Or ProductLoadService that loads all products). I would then pass that ProductSearchService into your ProductListViewModel constructor (dependency injection) and let your ViewModel control the retrieval of the Products (your model objects) by calling the relevant service methods and loading the response.

  • ProductListService Returns Product (Model) List
  • ProductListViewModel uses ProductListService to get Products
  • ProductListView binds to ProductList ObservableCollection in ProductListViewModel.

This pattern essentially resembles Model-View-Controller, where the ViewModel takes more of the Controller responsibilities.

Since you mention REST based web services, I have an example blog post of using MVC 2 JSON results as a service layer for a Win Phone 7 app: Data Driven Win Phone 7 Apps with MVC 2 JSON services

Jacob