Best Practises in creating View Models

Dec 10, 2010 at 12:31 PM

Hello,

I am new to  Windows Phone 7 and Silverlight development and I would like some input on best practises regarding loading the View Models with data.

My plan is to use CM for creating my application. How would I best fill my viewmodels with data.

For example:

Say that I have a MainViewModel that is bound to the MainView. In there I have for example a listbox that contains bound items. I can add and delete items from that list in the application.

Where should I load the data? Are there any differences between mainmodel and other screens that I open?

The ViewModel is created automatically by the CM framework.

Should I load the data in the constructor? (querying my repositories for data that is). Should I override anothe method? Should I use a framework feature that I don't know about?

When using the MVC web framework, I would perhaps call a repository or something similar in the controller and get a viewmodel that I would use to populate my HTML tags with.

What are the best practises in a MVVM scenario?

Thanks for the input.

/Joel

Dec 10, 2010 at 1:38 PM

Yes you can load your data in VM's constructor.

But it's usually better to differ loading to latest possible moment. You can choose to override OnInitialize(), OnActivate() methods on Screen class. Or you can load your data as a response on user's request (button clicked).

And if you're loading data from web or wcf don't forget there is async communication in play. 

There is a complete sample application, it can help you start digging into CM & WP7.

Valeriu

 

Dec 10, 2010 at 2:27 PM

I've got a somewhat related question, hope you don't mind a little thread hijacking :)

For my use cases, the user expects to get a View filled with data when he navigates to it, so I'm doing my data loading in OnActivate. Data is loaded from a custom webservice, which can be a bit slow at times - so I'd like a bit of animation or other visual indication that the View isn't ready to use yet.

If I had been replying to a user action, the command handler could have a IEnumerable<IResult> return type and use the yield trick, but what are my options when loading data in OnActivate? It should be noted that this is from a WPF app, but I expect the solution in terms of CM framework to be the same irrespective of the target platform?

Thanks in advance for any pointers :)

Dec 10, 2010 at 2:40 PM

In your OnActivate() you can use:

Coroutine.Execute(MethodReturningCoroutine().GetEnumerator()) 

In sample application cited above I've used another method, wrapped using of WebClient class in a RequestProcessor. Whenever you make a web call it will show a progress view before the call and hide it when receiving results... You can do the same in your IResult implementation.

Dec 10, 2010 at 3:13 PM

Fantastic, had to be something obviously simple - thanks! :)

Are there any downsides, gotchas or whatever to doing this in OnActivate? I assume the method won't return until the coroutine is entirely finished - does this have an effect on, say, message processing for the calling ViewModel's IHandle<whatever> implementations?

Dec 10, 2010 at 3:41 PM
Edited Dec 10, 2010 at 3:41 PM

I'm not quite sure here, but it should return the flow to main thread right after executing first IResult. If it's an async web call, the responce will come later in time and then you're firing Completed event to signal IResult's completition.

And it worth's trying, to avoid surprises...

If I'm wrong here, please someone correct me...

Dec 10, 2010 at 5:29 PM
Edited Dec 10, 2010 at 5:41 PM

Thanks for your answers!

I have acctually looked at your Sample Application. Nice work! It's always great to see a complete app to get a feeling of how to structure your own app.

And thats kind of also where my question came from. I  tend to think that you shouldn't put to much logic into your constructors. It's not the nicest place to get exceptions etc. in. And I usually want to avoid having a lot of calls to private methods etc. in there.

But in the MVVM case it seems that you don't have to much of a choice. I tried to load my data in OnActive but the method won't get called in my app?

The OnActivate method gets called when I from my 2:nd screen press the Back button to get to my first screen. But when I start the application or when I use:

 _navigationService.Navigate(new Uri("/SomePage.xaml", UriKind.Relative));

It is not called.

My ViewModel for SomePage.xaml inherits frm Screen and implements ILaunchChooser<PhotoResult>

Am I missing something here perhaps?

EDIT: Humm I might have missed the ScreenConductor thing. I'll try some tests with this and see if it helps! :)

Thanks again for taking time to answer my questions.

 

Dec 10, 2010 at 10:22 PM

A quick note, if you are performing the data loading in an async task, you might want to keep the user from interacting with the screens until the data is loaded.

 

One of the ways that I've found is to use the BusyIndicator in the WPF Extended Toolkit.  http://wpftoolkit.codeplex.com/

 

James

Dec 11, 2010 at 10:19 AM

Thanks for the tip.

Although I'm currently focusing on WP7 development, but I can probably find something similar for WP7!

 

/Joel

Dec 15, 2010 at 3:42 PM

For WP7 busy indication, check out this link: http://www.jeff.wilcox.name/2010/08/progressbarperftips2/