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.
Note: Since the Code Gallery was removed, I have now attached the source code to this article. Â This is unchanged from the version posted with the original article.
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!
Dean,
Glad I can help 🙂
-Reed
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).
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!
I’m really glad it helps, Sher!
Great article!
Finally understand some MVVM basics and more important, differences between WinForms and WPF.
Glad to hear that it helped, Peter!
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.
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.
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}”
This is done via an attached property. For details on attached properties, I’d recommend reading the MSDN article here: http://msdn.microsoft.com/en-us/library/ms749011.aspx
-Reed
how to get ActionCommand in our program
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.
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
Glad to hear it helped, Chris!
really nice explanation.
Great article, Reed!
I’m writing some projects to atuou wpf And it works a lot!
Hi Reed,
Thanks for this great series. Too bad I only found it recently, my first WPF application could have been way better.
Cheers!
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.
Thank you for the positive feedback, Elizabeth!
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.
Awesome help – went from not getting any of the WPF magic to totally loving it.
Thanks!
Glad that it helped! Thank you for the feedback.
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?
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.
very clear document. I like and understood wpf,mvvm very much. Thanks 🙂
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.
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?
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.
Thank you for the series and I want to ask is the sample code still available ?
Thanks, for this tutorial, my friend!
I was completely lost looking at weird XAMLs and trying to change things around to make it work.
I was always more of a code behind developer and the change from windows forms to MVVM was breaking my head!
Thanks again and keep up with the good work!
Thanks for this excellent series. finally, after many internet search, I can start with wpf , mvvm.
really thanks soooooooo much.
Thanks a lot for this tutorial. I download the source code and load it into VS 2013 Professional version, the project RssWpfMVVM has a runtime error, and the xaml file also complain the line has an error, and the intelligence saying that: the request was aborted: and the connection was closed unexpected. Project and solution can compile, but this MVVM project can’t run. Is there anything missing is my DEV. Environment.
Thanks for your guidance in advance.
Min
Thanks sir, Respect.
This is still a very valuable series in 2018. Very thorough explanation on the difference between WPF with MVVM and Winform. I enjoy the reading and read it multiple times to digest the details. Great sample code to explain the key technology of WPF MVVM on Data Binding, Commands and Templating. I read this article before start the journey of learning WPF. I had an impression that the learning curve is steep even for an experienced developer and kind of lost on why and how to start it. After reading your series, I am eager to start the study and encouraged to use it in my work. Very insightful series. Thank you for the wonderful teaching.
This is a wonderful tutorial for an MVVM beginner. I’m trying to run the example code in Visual Studio Express 2015. The RssWindowsForms and RssWindowsPresentation projects run beautifully. The RssWpfMVVM project, however issues a ‘ContextSwitchDeadlock’ error. 🙁