Alessandro Del Sole's Blog

/* A programming space about Microsoft® .NET® */
posts - 159, comments - 0, trackbacks - 0

My Links

News

Your host

This is me! This space is about Microsoft® .NET® and Microsoft® Visual Basic development. Enjoy! :-)

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.

Microsoft MVP

My MVP Profile

I'm a VB!

Watch my interview in Seattle

My new book on VB 2015!

Pre-order VB 2015 Unleashed Pre-order my new book "Visual Basic 2015 Unleashed". Click for more info!

My new book on LightSwitch!

Visual Studio LightSwitch Unleashed My book "Visual Studio LightSwitch Unleashed" is available. Click the cover!

Your visits

Follow me on Twitter!

CodePlex download Download my open-source projects from CodePlex!

Article Categories

Archives

Post Categories

.NET Framework

Blogroll

Help Authoring

Microsoft & MSDN

Setup & Deployment

Visual Basic 2005/2008/2010

WPF: Introducing the Model-View-ViewModel pattern for Visual Basic 2010 developers - part 1

This is the first post of a new introductory series about the famous Model-View-ViewModel pattern, from the perspective of a Visual Basic 2010 developer. The reasons of this series are mainly the following:

  1. yes, there are tons of articles, posts, discussions about M-V-VM but most of them are for advanced users
  2. most of the available materials refer to Visual C# and there is not much VB code

Before going on, I suggest you to read the very famous article by Josh Smith on MSDN Magazine, which is probably the most complete article on this topic. Next, M-V-VM can be applied to both WPF and Silverlight, with some differences between the 2 technologies, but in this blog post series I will refer to WPF 4. I will also do some personal considerations during the explanation.

What is M-V-VM?

If you are existing WPF or Silverlight developers, probably you heard about the Model-View-ViewModel pattern. Such a pattern has the purpose of offering a high degree of abstraction between layers (such as data and presentation), so that inside the presentation layer the developer can write only UI-related code but not code for managing data. This is possible because of the powerful data-binding engine in WPF which allows to an intermediate layer (known as ViewModel), which is between data (Model) and the user interface (View), to execute required operatins through binding and commanding techniques.

M-V-VM is a pattern, meaning that it's a set of guide lines that will help you reach an objective. This also means that it is not the rule and that you do not need it always. In fact, there are some scenarios where M-V-VM is not the best choice.

Benefits

M-V-VM is particularly useful for the following reasons:

  1. full separation between data and the UI
  2. full separation between the roles of developer and designer (which is also one of the primary reasons for XAML to be created)
  3. testing: as I will show you in the last part of the series, executing unit tests against a ViewModel makes sense instead of executing tests inside the UI context
  4. Model and ViewModel don't have the need of changing if the UI changes
  5. The ViewModel keeps the same logic indipentently from the kind of Model (e.g. custom business objects, Entity Data Models, etc.) 
  6. better “Blendability”, which is the possibility of working on a project with Expression Blend

Technically speaking, M-V-VM is a complex pattern. For example, in a M-V-VM context a simple mouse click on a button for showing up a new dialog is not simple as we use to do. Outside the above numbered list, you need a deep analysis of your requirements and needs before you use M-V-VM. There is a number of 3rd party tools that make easier creating applications based on the M-V-VM but they're esclusive to Visual C#. This is not a problem, because by writing some more line of code we will better learn some concepts and how to reuse some components.

As an exception, I suggest you to download and install the XAML PowerToys by Karl Shifflet which offer an integrated instrumentation for generating ViewModel classes starting from .NET objects.

What about me and M-V-VM

I'm not a Model-View-ViewModel guru and it's important for me to clarify this. I would like to use this blog to share the experience I did (and that I'm currently doing) in studying the pattern. Also, I would be happy if M-V-VM experts could leave their feedback. What I can say is that I noticed that there's no just one fashion to apply M-V-VM. There are several techniques, several choices, different implementations and ways of writing objects. With that said, in this blog post and in next ones I will follow an intermediate approach so that I can be adapted to multiple scenarios. Obviously it is also a good idea if you use a search engine for deep diving such a pattern on your own.

About the post series

This is just the first post of the new series. In this post we will create a very basic application that loads data from an Xml document and shows them inside a DataGrid. Next blog posts will be on the following topics:

  1. implementing the “commanding pattern” for adding commands and buttons
  2. implementing navigation features between data (e.g. Next, Previous etc)
  3. implementing data validation via the IDataErrorInfo interface 
  4. all of the above, against a data model based on the ADO.NET Entity Framework instead of custom objects 
  5. using M-V-VM in master-details relationships against Entity Framework

Since we are beginning, we need a very simple app. First, let's create a new WPF project with Visual Basic 2010. Once done this, it's time to talk about data.

The Model

The Model basically represents our data. It can be of different kinds, for example a business object, an Entity Data Model or a LINQ to SQL model, a POCO class. Let's imagine we have a Customer class that represents one customer, defined as follows:

Public Class Customer

    Public Property CompanyName As String

    Public Property CustomerID As Integer

    Public Property Address As String

    Public Property Representative As String

 

End Class

Now let's imagine that such a class is required to represnt data from an (very simplified) XML document like this:

<?xml version="1.0" encoding="utf-8" ?>

<Customers>

  <Customer CompanyName="Del Sole" CustomerID="1" Address="Cremona" Representative="Alessandro Del Sole" />

  <Customer CompanyName="RM Consulenza" CustomerID="2" Address="Varese" Representative="Renato Marzaro" />

  <Customer CompanyName="Catucci Snc" CustomerID="3" Address="Milano" Representative="Antonio Catucci" />

</Customers>

Finally, let's implement a collection named Customers that stores all the loaded Customer objects. Such a class inherits from ObservableCollection(Of Customer) and exposes a shared method that loads data:

Imports System.Collections.ObjectModel

 

'Implements INotifyPropertyChanged

Public Class Customers

    Inherits ObservableCollection(Of Customer)

 

    Public Shared Function LoadCustomers() As Customers

 

        Dim customerCollection As New Customers

 

        Dim doc = XDocument.Load("Data\Customers.xml")

        Dim query = From cust In doc...<Customer>

                  Select New Customer With {.Address = cust.@Address, .CompanyName = cust.@CompanyName, .CustomerID = CInt(cust.@CustomerID), .Representative = cust.@Representative}

 

        For Each cust In query

            customerCollection.Add(cust)

        Next

        Return customerCollection

    End Function

End Class

We use the ObservableCollection because it implements the INotifyPropertyChanged interface and thus it can send notifications every time its content changes. 

The ViewModel

In most tutorials I read, after the Model they discuss the View. In my opinion this is not the right approach, so I will now talk about the ViewModel. Its job is executing tasks against the model and sending notifications about the executed tasks. The ViewModel sends notifications but it does not know who will receive them. Because the ViewModel sends notifications, the class that defines it must implement the INotifyPropertyChanged interface. Since in one project we could have several ViewModels, a good idea is creating a hierarchy of reusable classes. 

For example, we could have one ViewModel working on the orders of our company and another ViewModel working on the customers' data. Both will have some common features, so we can implement a base class that can be later inherited from other ViewModels. With that said let's create a new class named, as a convention, ViewModelBase:

Imports System.ComponentModel

 

Public Class ViewModelBase

    Implements INotifyPropertyChanged

 

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

 

    Protected Sub OnPropertyChanged(ByVal strPropertyName As String)

 

        If Me.PropertyChangedEvent IsNot Nothing Then

            RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(strPropertyName))

        End If

 

    End Sub

End Class

Here the class implementation is very basic. In later posts we will see some improvements for property names validation. At this point we need a ViewModel that executes tasks against the Model and that sends notifications to the bound View. Such a class can be named CustomerViewModel and inherits from ViewModelBase. This is the code:

Public Class CustomerViewModel

    Inherits ViewModelBase

 

    Private _objCustomer As Customer

    Private _customers As Customers

    Dim _selectedCustomer As Customer

 

    Public Property Selection() As Customer

        Get

            Return _selectedCustomer

        End Get

        Set(ByVal value As Customer)

            If value Is _selectedCustomer Then

                Return

            End If

 

            _selectedCustomer = value

            MyBase.OnPropertyChanged("Selection")

        End Set

    End Property

 

    Public Property Customers As Customers

        Get

            Return _customers

        End Get

        Set(ByVal value As Customers)

            Me._customers = value

            OnPropertyChanged("Customers")

        End Set

    End Property

 

    Public Property Customer() As Customer

        Get

            Return _objCustomer

        End Get

        Set(ByVal Value As Customer)

            _objCustomer = Value

            MyBase.OnPropertyChanged("Customer")

        End Set

    End Property

 

    Public Property Address() As String

        Get

            Return _objCustomer.Address

        End Get

        Set(ByVal Value As String)

            _objCustomer.Address = Value

            MyBase.OnPropertyChanged("Address")

        End Set

    End Property

 

    Public Property CompanyName() As String

        Get

            Return _objCustomer.CompanyName

        End Get

        Set(ByVal Value As String)

            _objCustomer.CompanyName = Value

            MyBase.OnPropertyChanged("CompanyName")

        End Set

    End Property

 

    Public Property CustomerID() As Int32

        Get

            Return _objCustomer.CustomerID

        End Get

        Set(ByVal Value As Int32)

            _objCustomer.CustomerID = Value

            MyBase.OnPropertyChanged("CustomerID")

        End Set

    End Property

 

    Public Property Representative() As String

        Get

            Return _objCustomer.Representative

        End Get

        Set(ByVal Value As String)

            _objCustomer.Representative = Value

            MyBase.OnPropertyChanged("Representative")

        End Set

    End Property

 

    Public Sub New()

        Me._customers = Customers.LoadCustomers

    End Sub

 

    Public Sub New(ByVal customerCollection As Customers)

        Me._customers = customerCollection

    End Sub

End Class

 

 

Let's make some considerations:

  1. The class exposes a Selection property thar represents the current customer and that is useful with View data-binding
  2. The class exposes a Customers property that sends to the View the content of the customers collection
  3. The class exposes the same number of properties as in the Model, plus explicitly sending change notifications by invoking OnPropertyChanged
  4. The class' constructor is responsible for loading data and for populating properties so that these can be data-bound

So what you can understand is that the ViewModel is responsible for loading and exposing data. In next posts we will also see how it can edit and save data. In other words, the UI does no work; instead, the ViewModel does all the work. The ViewModel does not know who will receive its notifications and so it is fully free from the UI. Now it's time to give a destination to what the ViewModel exposes: a View.

The View

When talking about M-V-VM, we refer to the View as the presentation layer and generally it is represented by a Window object. As you know, it exposes a DataContext property. Such a property allows all controls in the UI to populate picking up data right starting from the DataContext. And since data are exposed by the ViewModel, this will be the value of the DataContext.

If we switch to the XAML code editor of our main Window, we can decide to show our data inside a DataGrid (which is appropriate for learning purposes). The following XAML code demonstrates this:

<Window x:Class="MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="MainWindow" Height="350" Width="525">

    <Grid>

        <DataGrid AutoGenerateColumns="True" ItemsSource="{Binding Path=Customers}" SelectedItem="{Binding Path=Selection, Mode=TwoWay}"

                  Name="DataGrid1" >

        </DataGrid>

    </Grid>

</Window>

 

The ItemsSource property is poulated with the content of the Customers property exposed by the Window's DataContext and the same is true for the SelectedItem property which is poulated with the value of the Selection property from the DataContext. But as I said before, the value of the DataContext is nothing but our ViewModel. So, the Window's constructor (but you can do it also on the XAML side) will instantiate the ViewModel and assign it to the DataContext as follows:

 

    Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim custViewModel As New CustomerViewModel()

        Me.DataContext = custViewModel

    End Sub

As you can see, this is the only code for the Window. All the actual job is performed inside the ViewModel, reaching the objective of the full separation between layers (and roles). Now you can run the application and see how data are loaded inside the DataGrid. The UI is "simply" data-bound to the ViewModel, which performs the work.

Source code download and the end of the first part of the story

In this first part we have begun understanding some basic concepts. The sample application is really and really simple, but starting from next post I will show you some more interesting techniques such as commands implementation. The source code for this blog post is available at this address of the MSDN Code Gallery. 

Alessandro

Print | posted on mercoledì 16 giugno 2010 14:14 | Filed Under [ Visual Studio 2010 Visual Basic Windows Presentation Foundation ]

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 7 and 3 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET