Ranting and raving about anything I feel like complaining about.

My Silverlight MVVM Article is Live!

Url: http://msdn.microsoft.com/en-us/magazine/dd4588...

Silverlight Logo

If you are trying to learn what kind of architectures work well in Silverlight applications, take a look at my new MSDN Magazine article. It introduces the Model-View-ViewModel architecture pattern and how it works in Silverlight. You can read the article here:

http://msdn.microsoft.com/en-us/magazine/dd458800.aspx

 
 

Comments

Gravatar Thanks for the article! A short comment though: I usually like to track selected item state in my ViewModels, therefore I expose the appropriate property (e.g. string Genre), bind ListBox / ComboBox's SelectedItem to that property and handle its changed behavior (e.g. call LoadGames() method) in property's setter. With the ViewModel now being aware of the current selected item value, any other method can use it as its parameter with the View no longer required.
Gravatar That's a great idea Andrej!
Gravatar I am not surprised that Blend is choking on it, but it should see it. I didn't see that behavior.
Gravatar I finally got it to see it, then got a message about memory corruption.

Took me awhile to figure it out, but the problem was that it didn't like my viewmodel constructor?

Odd

Thanks Shawn
Gravatar Typically ViewModel constructors should be empty to make it easier to instantiate in XAML. Not a hard and fast rule, but that's what I typically do.
Gravatar Sorry, I didn't get enough detail: My code is nearly identical to your sample:

public GamesViewModel() :
this(new GameCatalog())
{
}

public GamesViewModel(IGameCatalog catalog)
{
theCatalog = catalog;
theCatalog.GameLoadingComplete +=
new EventHandler<GameLoadingEventArgs>(games_GameLoadingComplete);
theCatalog.GameLoadingError +=
new EventHandler<GameCatalogErrorEventArgs>(games_GameLoadingError);
}

With that code, Expression will not view for me. I get a memory corrupt error until I remove the constructors. Which will make it difficult for me to use DI
Gravatar Side question for you:

In my sample I'm getting like 3000+ records back which blows up my listbox.

I want to only show 50 at a time.

In my view model, I setup a 'FilteredSet' list and I bind to that in the view.

However, I get no results back when I do this?

1. I use the exact layout you have
2. my list of 'Games' is very large
3. I need to filter that list

however if I 'var filters = serviceClients.OrderBy(c => c.ServiceDescription).Take(50);' it's no longer my observable collection ?

Basically, how would you filter this list down - assume you have 5000 games returned
Gravatar Hello Shawn,

Thank you very much for the article : it saves my days. I have been looking for Silverlight MVC patterns samples for a long time.

Unfortunately, my application have a lot of business classes and a lot of operations : tackling with numerous events handle is tricky sometimes.

That's why I'm using a delegate approach instead of events for operations, and I uses events to handle errors the same way as the article do.

For example, my ViewModel contains a fonction like this:

ViewModel:
public void LoadList(int projectID, Action postAction)

So I can can pass a delegate to postAction to display and hide a "Loading..." control on the screen :

...
ShowPopup("Loading...");
LoadList(selectedProject, delegate
{
HidePopup();
});

My ViewModel call a LoadList function in my Model the same way:

Model:
public void LoadList(int projectID, Action<IEnumerable<SubProject>> postAction)

so the ViewModel calls it, passing it a delegate that process the data by populating a collection with the results.

...
LoadList(projectID, sp =>
{
foreach(var oneSp in sp)
SubProjectCollection.Add(sp);
});


It works perfectly. Thanks to this, I have fewer events in my application and my code is more small.

but I wonder whether this delegate approach is recommended or not :/. I would bet it is, because the "BeginXXX" functions of the MS generated Data Service proxy are working this way. However I prefer to be sure. What is your opinion about it ?
Gravatar Shawn,

Loved the article in MSDN Magazine - it was much clearer than some others I had read on the subject. I have one area that I am still confused on - maybe you could point me in the correct direction.

If, in my view, I have a tab control. Which tabs are the control are actually controlled by the Model (the user can define which tabs they want, and have it stored between sessions).

The question - how can the viewmodel create tabitems (with custom content) based on the data from the model?

Since the viewmodel has the ObservableCollection<TabItem>, I am currently constructing the tab item, and the usercontrol the user wants, setting the tab items content to the user control.

private void CreateDefaultTabs()
{
// Add the tab - type hardcoded for brevity
this.ModeTabs.Add(this.CreateModeTab(ParsedLogViewMode.Protocol));

this.SelectedModeTab = this.ModeTabs[0];
}

private TabItem CreateModeTab(ParsedLogViewMode mode)
{
TabItem item;
object control = null;
ParsedLogModeViewModel model;

item = new TabItem();

switch (mode)
{
case ParsedLogViewMode.Protocol:
control = new ProtocolMode2UserControl();
break;
}

item.Content = control;
model = this.CreateModeViewModel(mode);
item.DataContext = model;
item.Header = model.Title;

return item;
}

This just doesn't feel right, as I can't really unit test this viewmodel, but there are no examples of how to handle this situation.

Any help would be appreciated.
Gravatar Chad,

It would seem that exposing a set of TabItem's would mean your model is doing UI work. You should be doing only data in your VM.
Gravatar Chad,

So if your tabs are data-driven, I would expose the view names not the TabItems from your model so you can test it. That's a case where doing the work to instantiate the other views might be ok from the view (or use a ViewFactory).

Add a Comment

*
*
*