How to display list of items – MVVM way.
What is that MVVM anyway?
The preferred way of connecting data with view in WPF applications seems to be MVVM pattern. MVVM stands for ModelViewViewModel. The whole idea behind it is to create a kind of a bridge between your data and logic at one side and view at the other. By using such bridge/buffer we avoid hardwiring our logic with view. It allows us to write application data and logic the way it should be written without taking shortcuts and making compromises just to be able to connect such code with a view. If written properly ViewModel can be unit tested which helps a lot in a world of GUI applications which are usually hard to test.
A little bit of practice.
Let’s start with a view model. What is a view model? For now let’s just think about view model as an object that provides view with whatever it requires in the form that is convenient for a view. Since view works with a few simple elements like properties containing data it can bind to and commands it can invoke these are two basic elements we will expose in out view model instance.
1: class MainWindowViewModel2: {3: public MainWindowViewModel()4: {5: People =6: new List<Person>()7: {8: new Person("Arek", 31),9: new Person("Magda", 26)10: };11: }12:13: public IList<Person> People { get; set; }14: }
Above we have our view model for main window. It provides view with a list of elements that we will bind to ListView’s control ItemsSource property.
For the sake of completeness of our view model example I have to say a few things about bindings here. Binding, according to MSDN, looks like this:
How our example works? Our binding target is ListView, binding source is MainWindowViewModel. Dependency property ItemsSource is bound in XAML to People property in view model. Our binding is in OneWay mode which means that data updates go only from People property to ItemsSource. Actually then don’t. They would if we implemented INotifyPropertyChanged interface in MainWindowViewModel. After that modification on view model looks like that:
(TODO: insert view model with updated implementation)
Now that we have our data we can move to a view implementation.
1: <Window2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"4: xmlns:local="clr-namespace:SimpleList">5:6: <Window.Resources>7: <local:MainWindowViewModel x:Key="viewModel" />8: </Window.Resources>9:10: <ListView11: DataContext="{StaticResource viewModel}"12: ItemsSource="{Binding Path=People}" />13: </Window>
As you can see we create an instance of our view model in Windows.Resources section and than use it for setting DataContext of ListView control. First effect of our struggles looks like this.
It’s not exactly what we had in mind so what’s wrong? By default list view displays for each item text returned by it’s ToString() method.
One way to improve it would be like this.
1: <ListView2: DataContext="{StaticResource viewModel}"3: ItemsSource="{Binding Path=People}">4: <ListView.View>5: <GridView>6: <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>7: <GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}"/>8: </GridView>9: </ListView.View>10: </ListView>
And the result:
Better, or maybe like this:
1: <ListView2: DataContext="{StaticResource viewModel}"3: ItemsSource="{Binding Path=People}">4: <ListView.ItemTemplate>5: <DataTemplate>6: <StackPanel Orientation="Horizontal">7: <TextBlock Text="Name:" Margin="10,0,5,0"/>8: <TextBlock FontWeight="Bold" Text="{Binding Name}"/>9: <TextBlock Text="Age:" Margin="10,0,5,0"/>10: <TextBlock FontWeight="Bold" Text="{Binding Age}"/>11: </StackPanel>12: </DataTemplate>13: </ListView.ItemTemplate>14: </ListView>
As you can see there is a lot of choices. Actually taking into consideration styles, templates, and ExpressionBlend we’ve got countless choices of how to show our data within a control.




