Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Conclusion

Windows Presentation Foundation provides us with new opportunities to build applications that are very flexible to design, easy to maintain, and clear to understand.  By taking advantage of Data Binding, Commands, and Templating, we can rethink the way we build our applications, and design them using the Model-View-ViewModel Pattern.

Now that I’ve walked through how we do this, I will revisit our original RSS Feed Reader application, and show samples of how this changes the design and code in this simple application.

First, lets look at our Model.

Our Model classes, as expected, remained completely unchanged through all three versions of our software.  The same Model was usable by the Windows Forms application, our WPF application, and our WPF with MVVM version of our application.  This works because our Model described nothing but it’s own, domain specific information.  It took no dependencies on a presentation technology, and made no assumptions of how it would be used.

Next, lets begin by looking at our View.

In Part 7, I mentioned that we should keep a goal in mind for the View: The user interface should be declared entirely in XAML, with zero code behind.  Unfortunately, it’s impossible to have absolutely zero code, but we’ve managed to move our entire declaration of both our Window and our UserControl into XAML, so all that is left in the code is the constructor which calls InitializeComponent:

namespace RssMVVM.Views
{
    public partial class MainView
    {
        public MainView()
        {
            InitializeComponent();
        }
    }
}

In this example, we’ve succeeded in accomplishing our goal – we have no code in the code behind other than the automatically generated code that is required to initialize our UserControl or WIndow.

Our XAML changed, as well.  Instead of having nearly every element named in order to make them accessible via code, we now use data binding to bind directly to their values.  For example, in our original WPF version of our UserControl, the first set of TextBox elements was written like this:

<TextBox Grid.Row="0" Grid.Column="1" x:Name="textBoxTitle" />
<TextBox Grid.Row="1" Grid.Column="1" x:Name="textBoxLink" />
<TextBox Grid.Row="2" Grid.Column="1" x:Name="textBoxDescription" />

Now, in our MVVM version, we change this to:

<TextBox Grid.Row="0" Grid.Column="1"
  Text="{Binding Path=Feed.Title, Mode=OneWay}" />
<TextBox Grid.Row="1" Grid.Column="1"
  Text="{Binding Path=Feed.Link, Mode=OneWay, Converter={StaticResource StringToUriConverter}}" />
<TextBox Grid.Row="2" Grid.Column="1"
  Text="{Binding Path=Feed.Description, Mode=OneWay}"/>

At first glance, this may seem like extra work.  However, the second eliminates all of the code required to set and manage changes in the first (two entire methods).  The MVVM version also has a subtle, yet profound advantage over the first: the XAML code is exactly describing what will exist inside that text box.  This provides a level of self-documentation in your XAML, which fits in perfectly with it’s declarative nature.  In the original version, the only clue we would have to the TextBox’s purpose is the name we specified.

I will mention – I had to “cheat” here, to some extent.  There is one issue that was not easily resolved in porting this application to MVVM: the WebBrowser control.  Unfortunately, the WebBrowser control wraps a COM component, and is not a native WPF control.  I suspect that this led to an unfortunately design decision: WebBrowser.Source is not a standard WPF DependencyProperty, and as a result, can not be used with Data Binding like standard control elements.

There are at least two options for handling this situation.  We could have easily handled this by using code in the code behind file.  This would be a minor deviation from our goal, but as the goal of no code in code behind is a guideline, not a hard fixed rule, it would be a valid option.  However, there is another feature in WPF we can use in many situations such as this: Attached Properties.  In my case, I prefer to use attached properties, since this creates a tool that is easily reusable on any WebBrowser control.  By using an attached property, we can create a BindableSource property that allows us to use Data Binding with a WebBrowser, just by changing the XAML to:

<WebBrowser Grid.Row="2" RssMVVM:WebBrowserUtility.BindableSource="{Binding Uri}" />

The final change I introduced was the addition of a DataTemplate in the application’s XAML:

<Application.Resources>
    <DataTemplate DataType="{x:Type ViewModels:FeedViewModel}">
        <Views:FeedControl />
    </DataTemplate>
</Application.Resources>

This simple addition allows WPF’s templating to automatically construct and manage our View for the UserControl, saving us all of the code required to construct and place the control.

We made our clean View possible by introducing two ViewModel classes: MainViewModel and FeedViewModel.  Looking at our ViewModel classes, we see their simplicity.  Most of the code involved in our ViewModel class is nothing but a wrapper around our Model in order to allow it to properly implement INotifyPropertyChanged, and to handle the creation of our ICommand implementations.

The nice thing here, is we can see all of our logic, everything that the View is going to use, in one location.  There is nothing tied to a specific View here, so it is easy to generate unit tests for our ViewModel classes.  All of our logic is wrapped into a commands, and the rest of our ViewModel classes do nothing but wrap properties to properly handle INotifyPropertyChanged.

I purposely did not make custom styles for the WPF versions of this application.  That would be very easy to do, and potentially could make the WPF versions of this application much better looking and more usable.  Though it would be a fun and easy exercise, the main goal of this series is to demonstrate how the code itself can be changed in order to make maintaining and redesigning the application simple – not how to make a beautiful designed user interface.

The Visual Studio Solution used in this article, with full source code, is available on MSDN Code Gallery.  I encourage you to download and compare all three versions of the RSS Feed Reader application in detail.  The progression of this application, and the advantages it brings, will be much more noticeable when looking at the full source code.

Windows Presentation Foundation has a lot to offer every application developer.  By taking advantage of its unique features, we can build our applications in a way that is maintainable, testable, designable, and simple to implement.  The Model-View-ViewModel design pattern provides a clean pattern we can use improve our efficiency as developers.

About Reed
Reed Copsey, Jr. - http://www.reedcopsey.com - http://twitter.com/ReedCopsey

Comments

15 Responses to “Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Conclusion”
  1. Thanks for posting this series of articles, Reed. I understand WPF and the MVVM pattern much better now. It helps to see how things have changed and evolved since the WinForms days!

  2. Adam says:

    Great series.. thanks for taking the time to write it. This will definitely help me as I transition from WinForms to Silverlight (and hopefully some WPF).

  3. Sher says:

    This is the best ‘transitional’ discussion I’ve read. Excellent. The recasting of our solutions to the MVVM model does not seem nearly s daunting.

    Thank you!

  4. Peter says:

    Great article!

    Finally understand some MVVM basics and more important, differences between WinForms and WPF.

  5. Why do you prepend “this.” to some of the controls? Isn’t that redundant?

    BTW, thanks for this series; I can’t say that I can dive right in and create a MVVM WPF app, but it’s helped me along that path.

    • Reed says:

      B. Clay,

      It is redundant in that it is not necessary. I tend to write my code to follow StyleCop guidelines (http://stylecop.codeplex.com/), which require this.

      While it’s not technically necessary, it does provide a readability/maintainability advantage if all of your code is this way, as it makes it very, very clear when looking at a code where the variable is scoped. It also allows you to freely reuse variable names as parameters without as much worry, as private variables will not clash if they’re explicitly scoped with “this.”, which adds some freedom to naming.

  6. Shai says:

    Can you explain how the following portion of code communicate ViewModel?
    Can you put implemantion of ViewMode where the following cod segment is pointing?

    WebBrowserUtility.BindableSource=”{Binding Uri}”

  7. Jamshid says:

    how to get ActionCommand in our program

    • Reed says:

      Jamshid: The code for this program is on the MSDN Code Gallery (link above in post). You are welcome to copy the ActionCommand from this project and use it in your own.

  8. Chris says:

    Hi, I would like to thank you for writing this series of articles. Your writing has really helped me understand WPF and MVVM in a very quick and concise manner. The sample solutions combined with easy to digest blog posts is just fantastic.

    Thanks again,
    Chris

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!