I’m still playing with MVVM at work and I got a new occasion to setup a dialog using the MVVM methodology.
I really love the process of creating User Interface using MVVM, the process is so much natural ! Basically, I needed to create a “setup” dialog in the application I’m currently working on. I wanted to achieve something like this:

Of course, I wanted to create this dialog using the power of WPF. My primary objective when I create a new dialog is to keep the code-behind empty. Using MVVM it took me about 10 minutes to create the basic structure of the dialog withouth writting a single line of code in the xaml.cs files.
Here is the process I followed to create this dialog. This is the “thinking with MVVM” part because I’m explaining the reasoning I had
You can download the source code for this example here.
Setup the main dialog
When I need quick prototypes, I often don’t use Blend and type the XAML directly into Visual Studio editor. That was the very first part I did to write this XAML:
1
2
3
4
5
6
7
8
9
10
11
12
| <Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" Margin="5"/>
<Border Grid.Column="1" Margin="5" BorderBrush="#FF7F9DB9" BorderThickness="1">
<!-- Content goes here -->
</Border>
</Grid> |
Pretty easy isn’t it. Please note the “Content goes here” comment. I knew I wanted to put the settings dialogs here, but I didn’t know how… I named this file ConfigurationDialog.xaml.
Create sub-configuration dialogs
For this example, I created 2 sub-configuration dialogs just for the demo. I just put a TextBlock into a Grid to demonstrate the principles. Of course, we should add real configuration controls such as CheckBox, TextBox, etc. Those 2 new files are GeneralSettingsView and AdvancedSettingsView and are UserControls.
Create a ViewModel class for each View
I used to use an abstract base class for all my ViewModel classes where I implement the INofityPropertyChanged interface. I also use a trick from Josh Smith to throw an exception if the property name doesn’t exist when the PropertyChanged event is raised.
That gives us 3 new files: ConfigurationDialogViewModel, GeneralSettingsViewModel and AdvancedSettingsViewModel. Because I wanted configuration dialogs to have a common Name property (to identify them in the UI), I created a base class SettingsViewModelBase.
Setup the ViewModel of the main View
I needed the main View to expose the other configuration views available. I used an ObservableCollection for that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| public class ConfigurationDialogViewModel : ViewModelBase
{
private readonly ObservableCollection<SettingsViewModelBase> settings;
public ObservableCollection<SettingsViewModelBase> Settings
{
get { return this.settings; }
}
public ConfigurationDialogViewModel()
{
this.settings = new ObservableCollection<SettingsViewModelBase>();
this.settings.Add(new GeneralSettingsViewModel());
this.settings.Add(new AdvancedSettingsViewModel());
}
} |
Setup the main View to consume datas from its ViewModel
I did some changes in the XAML to databind the ListBox’s ItemsSource property to the ViewModel. Because I always set the DataContext property of a view to its associated ViewModel, there is no ambiguity:
1
| ItemsSource="{Binding Settings}". |
The ListBox control has no idea how a SettingsViewModelBase object (that is in the associated ObservableCollection) should be displayed. We need a simple DataTemplate to specify this information:
1
2
3
4
5
| <ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" Padding="10"/>
</DataTemplate>
</ListBox.ItemTemplate> |
And finish using my favourite part !
We just setup a ListBox to consume a collection of SettingsViewModelBase class to build a menu, fine. By using a very simple DataTemplate, we said: “I want to render the SettingsViewModelBase object in the ListBox using a TextBlock”.
We can take this reasoning one step further. We have a View associated to each SettingsViewModelBase. ListBox was fine to have a collection of controls. How could we display only one control ?
We can use a ContentControl of course ! Because we want do display the dialog that is currently selected in the menu, we can use a simple DataBinding (here, the ListBox has been named ListBoxMenu):
1
| <ContentControl Content="{Binding ElementName=ListBoxMenu, Path=SelectedItem}"/> |
One more time, we got a rendering problem. The ContentControl doens’t know how to render a SettingsViewModelBase object. Well, it’s not a big deal, just specify it:
1
2
3
4
5
6
7
8
| <Window.Resources>
<DataTemplate DataType="{x:Type ViewModel:GeneralSettingsViewModel}">
<View:GeneralSettingsView/>
</DataTemplate
<DataTemplate DataType="{x:Type ViewModel:AdvancedSettingsViewModel}">
<View:AdvancedSettingsView/>
</DataTemplate>
</Window.Resources> |
What I’m saying here is that GeneralSettingsViewModel should be rendered using a GeneralSettingsView. That’s exactly what we need ! Because the Views are created using a DataTemplate, we do not need to setup the DataContext, it will be automatically registered to the templated object, the ViewModel.
Conclusion
The example I describe here is very simple. The goal was to show the process of creating a dialog thinking in the “MVVM” way. It was very natural to use the concepts I explain here. The code-behinds are completely empty and ViewModel classes are testable ! Because the View are XAML only, I can give them to a designer that will tweak them to make them have a nice look.
You can download the source code for this example here.
Recent Comments