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

31 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

  9. Sachin says:

    really nice explanation.

  10. Rodolfo Duarte says:

    Great article, Reed!

    I’m writing some projects to atuou wpf And it works a lot!

  11. joeyend says:

    Hi Reed,

    Thanks for this great series. Too bad I only found it recently, my first WPF application could have been way better.

    Cheers!

  12. Elizabeth says:

    Excellent series, Reed. Using the three different approaches to contrast WinForms and WPF and to show the advantages of WPF/MVVM is extremely helpful. Thank you for your hard work and clear explanations.

  13. Tomas says:

    Thank you for these superb articles. I am VB developer and I was frightened with WPF. There are so many options how to achieve the same thing. I didn’t know where to start. Now I have really understood WPF with MVVM pattern.

  14. Jim says:

    Awesome help – went from not getting any of the WPF magic to totally loving it.
    Thanks!

  15. Gaurav says:

    This is awesome, after reading this article I suddenly realized that working with MVVM is more fun then using WPF directly.
    I have one question though – where should we initiate call to storyboards, code behind or View-Model or is there a way to do that in XAML?

    • Reed says:

      I see storyboards are a pure-View issue, which means there really is no reason not to use code behind for them. Attached properties or behaviors can often be used to trigger this if you want a xaml only solution, though.

  16. very clear document. I like and understood wpf,mvvm very much. Thanks :)

  17. Tom van Stiphout says:

    Excellent work Reed. Your series is the best introduction I have seen so far for developers coming from Windows Forms or other Controls-with-Events and CodeBehind environments. We have to go through the paradigm shift and you make it very clear.

    If you ever wanted to do another series, perhaps it could be comparing different alternatives and discussing pros and cons. For example you use DataTemplate to specify the VM in the V. Others says this is not optimal because it requires a default constructor and you cannot pass in arguments. Others discuss the relative virtues of V constructing its VM (like you’re doing) versus the reverse.
    Another topic in this series could be using a tool like MVVM Light and how it would benefit.

  18. J Bradshaw says:

    Good article. One thing still confused me however. Should I use an MVVM Framework for developing medium to complex WPF applications, rather than rolling my own? If so why?

    • Reed says:

      I think it’s valuable to “roll your own”, at least a bit, so that you understand the basics. That being said, the existing frameworks typically have more functionality, and are well tested, so I’d use them in production apps, whether large or small.

Trackbacks

Check out what others are saying about this post...
  1. […] of the sample apps, that raises my question : In Reed Copsey’s blog post on MVVM […]



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!