Model-View-ViewModel pattern example
I've been promising an example of the Model-View-ViewModel pattern for some time. With the Feb CTP of WinFX out and the Feb CTP of Expression Interactive Designer close, I feel like I can post something that will work for awhile. I had more ambitious plans for a complex, real-world example, but realized that 1) I didn't have much time to write such a beast and 2) It was hard to create a complex example that still clearly explained the principles.
So, I came up with the idea of doing a toy contact database. The core model classes looks like this:
Contact{ Contact( name, gender, favoriteColor); ToString(); FavoriteColor { ; } Gender { ; } Name { ; }} |
ContactDatabase{ ContactDatabaseChanged; ContactDatabase(); AddContact( newContact); OnContactDatabaseChanged( changeType, index, contact); RemoveContact( index); <> Contacts { ; }} |
Notice the classes have no special WPF dependencies. Imagine this is a pre-existing model, perhaps an interchange schema or a web-service with no UI or specific UI technology in mind. What I will be demonstrating is how to wrap this Model in a ViewModel an then build a UI on that ViewModel, all without changing the Model and especially without mixing UI code into it.
But to start, I want to show how much you can do with WPF data binding to just bind directly to the model...without any additional code. It turns out, quite alot. Here's a scrap of XAML I created using Expression:
<!-- The code will set the data context for this item -->
<Grid x:Name="MasterDetailContainer"
Margin="28,25,28,11" RenderTransformOrigin="0.5,0.5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.45*"/>
<ColumnDefinition Width="0.55*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- The parent's data context is going to be of type ContactDatabase
we bind the ListBox items to the ContactDatabase.Contacts property -->
<ListBox x:Name="ContactsListBox"
Margin="12,12,11,94" RenderTransformOrigin="0.5,0.5"
ItemsSource="{Binding Path=Contacts}"
IsSynchronizedWithCurrentItem="True"/>
<ContentControl x:Name="CurrentContactDetail"
Margin="14,16,17,219" Grid.Column="1" RenderTransformOrigin="0.5,0.5"
Content="{Binding Items.CurrentItem, ElementName=ContactsListBox, Mode=OneWay}"/>
<Button x:Name="AddButton"
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="18,0,0,131"
Width="86" Height="58" Grid.Column="1" RenderTransformOrigin="0.5,0.5"
Content="Add"
IsEnabled="false"/>
<Button x:Name="RemoveButton"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="135,0,93,131"
Width="86" Height="58" Grid.Column="1" RenderTransformOrigin="1,0.48"
Content="Remove"
IsEnabled="false"/>
</Grid>
The full project code at this point is attached. Take a look at it. In the next installment I will add a simple ViewModel.
Comments
Anonymous
February 26, 2006
John Gossmann has posted the first part of his long-awaited example of a Model-View-ModelView architecture,...Anonymous
March 01, 2006
I fail to see the relevance of this, post the ViewModel already!!Anonymous
January 20, 2008
PingBack from http://blog.quantumbitdesigns.com/2008/01/20/wpf-application-design-and-architecture/Anonymous
July 22, 2008
PingBack from http://blog.quantumbitdesigns.com/2008/07/22/wpf-application-design-and-architecture/Anonymous
January 13, 2009
Jag talar ofta med kunder och partners som vill använda vedertagna designmönster för att separera ansvaret