duminică, 22 iulie 2012

MVVM


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

This series introduces the Model-View-ViewModel Pattern from the point of view of a Windows Forms developer. The goal is not to introduce WPF, but to demonstrate some of the new features within Windows Presentation Foundation, and show how they should force every WPF developer to re-think how they design their applications.
The Model-View-ViewModel pattern is introduced after a discussion of three of the main features in WPF which enable it’s usage. In order to illustrate this, three versions a single application were written:
  • A Windows Forms application
  • A WPF Version of the application, using the same style
  • A WPF Version of the application, built using MVVM
This allows a detailed understanding of the reasons behind MVVM, as well as the technology that enables the pattern.

Series Outline

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

I frequently talk to people trying to decide, for a new project, between Windows Forms and Windows Presentation Foundation.  After spending time with WPF, I feel there is no reason to choose Windows Forms for new development.  WPF, when used correctly, is far superior, both in terms of user experience, but also developer productivity.
I feel that the confusion around choosing WPF really stems from a lack of understanding about WPF.  Even people on my own team have been overwhelmed trying to understand how the different pieces of WPF fit together, and how to apply the new concepts introduced with WPF effectively.  In order to address this, I’m going to break this down into a few simple pieces, and show the migration in terms of thought required to transition from being a good Windows Forms developer to an effective WPF developer.
Windows Presentation Foundation is huge.  Do not doubt it.  It is huge, both in terms of scope, but also in terms of the radically different approach it takes to developing user interfaces than other technologies.  Don’t let the scope frighten you, however – it is very well thought out, and very usable, once you understand some of the basic concepts.
In addition to the huge scope of WPF, new design patterns have evolved to take advantage of the new features introduced by this framework.  The most commonly referenced one, in terms of WPF, seems to be MVVM, or Model-View-ViewModel.  The Model-View-ViewModel pattern was inspired by some of the features in WPF, and seems perfectly fit for WPF, so many developers advocate it (with good reason) for use with WPF.
Again, don’t let this frighten or discourage you… MVVM isn’t about making WPF more difficult, it’s about making WPF usable in a quick, efficient manner.  Learning MVVM actually makes understanding WPF easier, not more difficult.
The issue here is that WPF is large, and the framework doesn’t force you into a single way of working.  There are lots of ways to work with WPF, including doing nearly the exact thing you’re used to with Windows Forms!  This is part of the power and flexibility of WPF, but also a trap to watch for and to avoid.  MVVM helps guide and force you to take advantage of WPF’s new features effectively, insulating you from common pitfalls and mistakes.
For this series, I’m going to start by showing a simple Windows Forms application – an RSS Feed Reader, and demonstrate converting it to WPF.  I’ll start with a strait conversion – and demonstrate how you can make WPF look and work exactly the same as you can with Windows Forms.  I’ll then explain, in details, some of the new ways of thinking that are pervasive within WPF, and show how this should change your way of thinking about user interfaces.
In order to do this, we’ll work with four separate projects – which include three completely different versions of the same application.  The goal here isn’t to use WPF to make the application “pretty” or “flashy”, rather, it’s to show how you can use WPF to make an application more developer friendly, including making it cleaner, more logical, easier to maintain, and more testable.

Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 1, The Model

Before we can make a user interface for a program, we need to know what the program is going to do.  Hopefully, we have some logic we’re going to be exposing to our users.  Underneath all of the beautiful user interfaces we build there is something that we’re trying to accomplish, some data we’re editing or information we’re conveying.  Before we can discuss how to make an effective user experience, we need to define the core information with which we are working.
When we discuss software architecturally, the core elements of our program are the “Model”.  The terminology comes from architectural design patterns, and goes back pretty far.  The “Model” is the one thing in most user interface patterns that hasn’t changed, and is the same terminology used all the way back with Smalltalk in the 70’s when Trygve Reenskaug first described the Model-View-Controller pattern.
When we’re talking about the Model, we’re talking about the domain-specific data and logic – the “guts” inside the program itself.  In an ideal world, the program should be able to, at least theoretically and architecturally, work without the user interface being present at all, provided it has the appropriate information passed to it.  The core business logic, in an ideal world, doesn’t need or want to know anything about how it’s being used – that’s outside of its concern.
Your business logic should know about your business, and nothing else.  This is key to maintaining an effectiveseparation of concerns within the design of our program.  This is also very useful for maintaining a program over time.  Keeping the model separate makes it much easier to extend an application into other realms without duplication of code or breaking a deployed application.  For example, if your business logic is completely isolated, you could potentially switch, without changing your business logic, from using a desktop, client-side application to using a command line, script based version of your application.  In some situations, you can even take the same logic and host it, accessing it remotely via a web page.
In most cases, its easiest to think of the Model as the data.  If you are making an application to edit customer information, the customer information (data) is the Model.  The model can also encapsulate logic, however.  If you have a service that needs to be called as part of your business logic when data is updated, the service itself can be thought of as part of the model.  When you talk about your program, when you discuss what functions the program performs, such as it “works on” this (data) or “performs this task” (logic), you are talking about the model.  Any time you discuss how the user interacts with the program, however, you are talking outside of the concern of the Model.
I want to mention, as a side note, one other thing here, that I often see as a point of confusion.  If you have an application with a full, multi-tier data access layer, all of the data access and logic layers are part of (or under) the Model.  For our purposes, we treat data and logic tiers as an internal, private implementation detail of the Model.  Here, the business logic layer acts as the Model’s public API, and we use that as our Model.  Presentation is separate from the Model, but the things the user "works on" (the data and domain specific logic to manipulate the data) are part of the Model.
For our series, we’re going to work with a simple program that is just an RSS feed reader.  When we’re talking about the feed reader applications, all three versions of our application we will develop use the same Model.  The public API of the Model is nothing but 2 classes: a Feed and a FeedItem.  The Feed class has some properties (Title, Description, etc), as well as a collection of FeedItem instances.  The FeedItem class contains properties for information about each item in the feed, including a Title, a Link to the original item, and a Description of the feed item.  The Feed class also has some logic – it has a static method that allows it to create a Feed given a Uri.
There is one important thing to remember about our Feed and FeedItem classes – they just describe data, and provide a means to load it.  They do not describe, in any way, how to edit or display the data.  Because the Model is all about data, and not about presentation or manipulation of that data by the user, we can use the same assembly, unchanged, in all three versions of our application.

Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 2, Our Application in Windows Forms

In order to fully understand how and why to migrate from Windows Forms to WPF, and from WPF to WPF using MVVM, we need to understand Windows Forms.
When Microsoft first developed and released .NET, they provided a very clean, simple API for creating Windows applications based upon existing technologies: Windows Forms.  The Windows Forms programming model is an event based programming model.  This matches very well with prior Microsoft technologies, such as ATL and MFC, since the core of Windows Forms wraps around controls defined in the Windows API.
In Windows Forms, you start with a “Form”, which corresponds to a Window in the desktop.  The form contains multiple controls, each done via a wrapper around the Controls in the Windows API.  Each control provides its own window handle (HWND, via Control.Handle), which is basically a separate Window.  When the application starts, you create a windows message pump by calling Application.Run, which maps the standard windows messages to their appropriate controls, which in turn raise events in the code for the Form.
In addition, a full designer was built which takes care of the initialization of the form, so the developer can graphically layout their controls on a form, and the appropriate C# code will be generated (inside the InitializeComponent method) on the fly.  It will add event handlers for the developer, and map them to methods in the Form’s .cs file automatically, making the creation of quick GUIs very easy.
Microsoft also provided a means of compartmentalizing a form, breaking it into more managable, smaller pieces of functionality called a UserControl.  A UserControl is basically the “guts” of a form that you can drop into another form, allowing both reuse in multiple forms, but also separation of logic into pieces to prevent a form from getting too large, in terms of code.
This is a very similar, comfortable model for developers who have used MFC, VB6, or even Delphi.  The implementation details are slightly different, but the basic conceptual model was unchanged – design a form, hook up events, handle the events, always working with the message pump in code.  This made adoption of the Windows Forms model very fast – it was familiar, and easy to transition from other technologies to Windows Forms.
For our series, we’re going to start here.  Taking our Model, the Feed and FeedItem classes described previously, we’re going to wire up a simple RSS Feed Reader application using Windows Forms. 
This is a very simple application.  For our purposes, the application must:
  • Load the feed using the Model
  • Display the basic information about the Feed
  • Display the list of FeedItems in the Feed
  • Let the user choose a specific FeedItem
  • Allow the user to open a FeedItem’s original source in their browser
  • Display the FeedItem in a wrapped browser
Here is a screenshot of our completed Windows Forms application:
WinFormFeedReaderMainThere’s nothing fancy in this application, and the code should look very familiar to anyone who’s used Windows Forms.  So, let’s look at how this works internally…
The “Feed Information” and “Select a Feed Item” section are broken into a separate UserControl for demonstration purposes.  The user interface was completely generated inside of a designer, and the code was written for us. 
When the user clicks on “Load RSS Feed”, a small event handler is run:
private void ButtonUpdateFeed_Click(object sender, EventArgs e)
{
    this.feedControl.Feed = Feed.Read(new Uri(this.textBox1.Text));
}
This sets the “Feed” property within our UserControl to a Feed (our Model).  The UserControl has a “Feed” property, which specifies some code to run when the Feed is updated:
public Feed Feed
{
    get
    {
        return this.feed;
    }

    set
    {
        this.feed = value;
        this.ResetFeed();
    }
}
This, in turn, calls the ResetFeed() method, which first calls ClearFeed() to cleanup the current UI, and then sets values inside each control:
private void ResetFeed()
{
    this.ClearFeed();

    if (this.Feed == null)
    {
        return;
    }

    this.textBoxTitle.Text = this.Feed.Title;
    this.textBoxLink.Text = this.Feed.Link.AbsoluteUri;
    this.textBoxDescription.Text = this.Feed.Description;

    foreach (var item in this.Feed.Items)
    {
        this.listBoxFeeds.Items.Add(item.Title);
    }
}

private void ClearFeed()
{
    this.listBoxFeeds.Items.Clear();
    this.textBoxTitle.Text = string.Empty;
    this.textBoxLink.Text = string.Empty;
    this.textBoxDescription.Text = string.Empty;
    this.textBoxItemTitle.Text = string.Empty;
    this.textBoxItemLink.Text = string.Empty;
    this.textBoxItemDescription.Text = string.Empty;
}
Our user control gets filled in with all of the feed information by us.  When the user chooses a feed in the ListBox control, we handle it via another event handler:
private void ListBoxFeeds_SelectedIndexChanged(object sender, EventArgs e)
{
    FeedItem item = this.Feed.Items[this.listBoxFeeds.SelectedIndex];
    this.textBoxItemTitle.Text = item.Title;
    this.textBoxItemLink.Text = item.Link.AbsoluteUri;
    this.textBoxItemDescription.Text = item.Description;

    if (this.UriChanged != null)
    {
        this.UriChanged(this, new UriChangedEventArgs(new Uri(this.textBoxItemLink.Text)));
    }
}
When our selected feed item changes, we update the feed item’s controls, and also raise an event on our UserControl.  Our main form subscribes to this event, and uses it to update the WebBrowser control sitting underneath our UserControl in the Form.
Finally, we have a button labeled “Open”, which has an event handler attached to it to open the Feed in our browser:
private void ButtonOpenLink_Click(object sender, EventArgs e)
{
    if (this.Feed != null)
    {
        FeedItem item = this.Feed.Items[this.listBoxFeeds.SelectedIndex];
        if (item != null)
        {
            System.Diagnostics.Process.Start(item.Link.AbsoluteUri);
        }
    }
}
This should look familiar to most Windows Forms programmers.  There are other ways to write this type of code, but this is very common, and seems quite indicative of how many Windows Forms programs are written.  This is by no means meant to be a perfect example of a great Windows Forms application, but rather a typical, common way this application could have been written.
There are some important things to realize here. 
  • All of our logic is handled in events, triggered by the user interacting with the user interface in our Window.
  • Although the Windows Forms designer provides a nice interface, if you actually examine the code, the entire user interface is defined imperitively, whether by us or by the designer.
  • The code, and therefore the logic, is really dependent on the type of control being used.  For example, if we changed from a ListBox to some other type of control, we’d most likely need to change the code to compensate

Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 3, Our Application in WPF

One common misconception I see when people start off with WPF is that they feel that it’s unapproachable, too complicated, and too unwieldy.  There some fundamental shifts that every developer must deal with when the first switch to WPF, but they are actually fairly minor.  You can program against the Windows Presentation Foundation API using the same basic techniques that you used in Windows Forms.
The first thing you’ll notice when working with WPF is the change in how the designer works.  The same concepts are there – you can drag controls onto a Window or a UserControl, and move them around, perform layout, etc.  There are some differences in how things work, especially in regards to layout, but for the most part, a developer can still open a window, drag in controls, and place them using the same basic technique as the Windows Forms designer.
However, when this is done, the designer does something very different.  In Windows Forms, the designer wrote our code for us; it created a partial class, and in the .designer.cs file, we got all of the code required to programmatically create our user interface.  This fit well with Windows Form’s imperative programming style.  The WPF designer, on the other hand, builds its user interface by creating .xaml files instead, using the Extensible Application Markup Language.  Microsoft describes XAML as “A Declarative Language with Flow Control Support”; the key word here is “declarative.”  WPF uses a declarative programming model, at least for the creation of the user interface.  Instead of specifying the steps required to build the user interface, the compiler uses a markup file (based on XML) that describes what should be displayed, not how to display it.
This is the single, fundamental change in thinking required to use WPF.  Even then, this is handled completely by the designer, so technically, you can build an entire user interface and never even look at this, just as you could build a Windows Forms user interface and never look at the designer file.
WPF also provides similar, often identical, events on controls for each control type.  For example, Button provides a Click event, to which you can subscribe.  The TextBox control provides a Text property you can set. This lets you wire up your event handlers in a manner that is nearly identical to Windows Forms.
For this part of our Series, we’re going to demonstrate this.  We’re going to write the same application we wrote usingWindows Forms in Part 2, this time, using WPF.
First thing to notice – the application looks very similar:
WPFFeedReaderMainThe main differences are due to changes in the default styling of WPF’s controls vs. those of Windows Forms.  Functionally, the application is identical.  It uses the same Model classes, completely unchanged.  I performs the same functions, with the same basic behavior.  We even structured it the same way, using a UserControl for the center section of the Window.
When we look at the code, we find something even more surprising – the code is nearly identical to our Windows Forms application!
For example, our “Load RSS Feed” button in our main Window class has a click event handler attached to it, and just like our Windows Forms application, it does nothing but load the Feed using the Model, and set a property in the UserControl.  The only difference here is in the declaration of our method: instead of passing EventArgs e, we now pass RoutedEventArgs e.  Otherwise, the code is identical:
private void ButtonUpdateFeed_Click(object sender, RoutedEventArgs e)
{
    this.feedControl.Feed = Feed.Read(new Uri(this.textBoxFeedUrl.Text));
}
Just like before, this sets the “Feed” property within our UserControl, but this time, the code in our UserControl is exactly the same as our Windows Forms code!  We were able to copy the code, with absolutely no changes, from Windows Forms to WPF.  Here is a small subset of that code, just to demonstrate that it hasn’t changed:
// ... previous code from Windows Forms application
    this.textBoxTitle.Text = this.Feed.Title;
    this.textBoxLink.Text = this.Feed.Link.AbsoluteUri;
    this.textBoxDescription.Text = this.Feed.Description;

    foreach (var item in this.Feed.Items)
    {
        this.listBoxFeeds.Items.Add(item.Title);
    }
// ... continue with code from Windows Forms application
In fact, when we look at our UserControl’s code behind file (the file that ends in .xaml.cs), the only differences we have between our WPF code and our Windows Forms code, through the entire Window and UserControl, are subtle differences in the method declaration, and setting “.Source” instead of “.Url” in our Main window, since WPF has different delegate declarations for its events and some subtle differences in control APIs.  Otherwise, the code we wrote is identical, to the letter.
Windows Presentation Foundation, though new, does not force us as developers to change our programming style.  We can do things the way we’ve always done them in Windows Forms, and continue forward with newer technology.  We can even mix and match Windows Forms and WPF via ElementHost and WindowsFormsHost, which let us host WPF inside Windows Forms and Windows Forms inside WPF.
Here are the important points to realize from this part of the series:
  • Although WPF is a completely new API, you can use the same event-driven programming style that you used in Windows Forms.
  • Most of the “new” features in WPF are optional.  WPF can make a real application using the same techniques as Windows Forms, only now, some of the interface is defined declaratively instead of being entirely imperative.
Hopefully, this mitigates some of the concern and fear of moving from Windows Forms to WPF.  There really is no reason to avoid using Windows Presentation Foundation, even if I haven’t described (yet) the compelling reasons to migrate, and the numerous advantages of WPF.

Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 4, Data Binding

Now that I’ve demonstrated how WPF can be written in the same manner, using the same methods as prior windowing frameworks, it’s time to explain why this is a bad idea.  To do this effectively, I’m going to discuss a few things that WPF introduces, and explain how they should change the way all of us approach building user interfaces.  One thing I do want to mention – this series is not meant to be a full tutorial on WPF, rather an explanation of how to use features in WPF effectively.
The first new concept in WPF I’ll introduce is the new, more powerful, more flexible model for Data Binding.
Windows Presentation Foundation provides an entirely new form of Data Binding than previous data binding technologies.  Data Binding existed in Windows Forms, but was limited to being bound to pretty specific data sources.  Many developers have used data bound controls prior to WPF, but the way data binding works in WPF has changed.  The data binding support in WPF adds the potential to use completely different programming models than we used previously.
So lets start with explaining data binding, in general terms.  Data binding is a general purpose technique that lets you take two (or potentially more than two) separate elements, and “bind” them together so that their values stay synchronized.  Typically, a control in the user interface (like a text box or a label) is bound to a property on some object containing your business logic.
The advantages of this should be obvious pretty quickly, provided this works correctly.  However, previous attempts at data binding have all fallen short when it came time to use them in practical, real-world problems.  I believe this comes down to the inability of most data binding frameworks to handle everything required.  For data binding to truly be effective, a binding framework should provide the following.
  • An easy way to bind user interface elements to data sources
  • A clean way to specify a data source for an entire collection of objects
  • A consistent way to specify bindings, no matter what is being bound
  • Allow flexibility in what triggers updates
  • An effective means of validation of values
  • The means to do conversion of the data through the binding itself
Most frameworks for data binding have provided some, but not all, of the features available above.  I’m going to address the above bullet points, and show how WPF provides for clean data binding.  We’ll start with the first three points:
  • An easy way to bind user interface elements to data sources
  • A clean way to specify a data source for an entire collection of objects
  • A consistent way to specify bindings, no matter what is being bound
Nearly all user interface items in WPF derive from FrameworkElement.  Whenever you create a Window or a UserControl in WPF, you have the option of specifying any object as the Framework Element’s DataContext.  The DataContext property specifies “the data context for an element when it participates in data binding”.  Whenever an object has a DataContext specified, you can use WPF’s data binding to bind directly to properties defined on that object.
There is a very important line in the documentation for DataContext:
This dependency property inherits property values. If there are child
elements without other values for DataContext established through local values
or styles, then the property system will set the value to be the DataContext
value of the nearest parent element with this value assigned.
What this means is that you don’t have to specify the DataContext for every element in your Window or UserControl.  You can specify the DataContext for a UserControl, and, by default, every control inside of the UserControl will automatically use that same DataContext for data binding!  This is incredibly powerful.
For example, in both our Windows Forms and WPF (version 1) applications, we had a UserControl defined for displaying information about our Feed object.  Whenever we’d update our Feed object, we would write a bunch of code triggered by setting our property to update our UI, such as:
// .. Called when Feed changes to update the user interface
    this.textBoxTitle.Text = this.Feed.Title;
    this.textBoxLink.Text = this.Feed.Link.AbsoluteUri;
    this.textBoxDescription.Text = this.Feed.Description;
By using data binding, we can completely eliminate this code.  Instead of doing this, we could, for example, just set the DataContext of our UserControl to the Feed object itself.  Once we’ve done that, we can just specify, in our XAML (which can be done in the designer), which property in our DataContext which we want to bind to our individual TextBox controls:
<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.AbsoluteUri, Mode=OneWay}" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=Feed.Description, Mode=OneWay}"/>
Now, all of a sudden, we have full, up to date user interface controls, and we can completely eliminate two entire methods (ResetFeed and ClearFeed) from our code!  Less code means less to maintain, less to test, and less to worry about.  Our TextBox instances don’t have a DataContext specified, so they automatically inherit the DataContext of the UserControl (since that is the first parent element with a DataContext provided).  They then bind directly to the property of the object in the DataContext.
This solves our first three bullet points – we can bind to any object (*see note below) using declarative syntax (in XAML), and we can specify the object one time, at a high level such as a Window or UserControl, viaFrameworkElement.DataContext.
Let’s move on to the next two points:
  • Allow flexibility in what triggers updates
  • An effective means of validation of values
Windows Presentation Foundation provides the means to handle this, as well.  Again, with no changes to our code, we can declaratively add support for both of the above bullet points.
First, what triggers an update to the binding can be specified, in XAML, by providing an UpdateSourceTrigger.  This lets us say, explicitly, that we want the property to update every time we type a letter into a TextBox (by setting the trigger to “PropertyChanged”), or only when the control loses focus (“LostFocus”).  In addition, UpdateSourceTrigger lets us explicitly handle property updates, even though this is not as commonly used.
Validation can be handled, and again specified declaratively by using XAML, in multiple ways.  I do not want to cover Validation here in detail, but it is discussed in detail on MSDN.  One or more ValidationRules can be attached to a Binding, allowing for great flexibility in data validation.
Let’s look at our final point:
  • The means to do conversion of the data through the binding itself
Using WPF, we have the ability to bind objects of any type to a control, even if the type wouldn’t normally (directly) be editable or displayable within a control.  WPF allows you to specify a converter to use to convert from the source type to the editing type, as well as handling the conversion back.  This is done via IValueConverter.  By specifying your own value converter, you can bind, via both OneWay or TwoWay binding, any control to any type of object.  For example, above, we bound our TextBox to “Feed.Link.AbsoluteUri”, which is a string.  However, if the AbsoluteUri property didn’t exist, we could write a converter to convert from a Uri to a string, and use that in our data binding.  This would allow us to bind directly to “Feed.Link”, as follows:
<TextBox Grid.Row="1" Grid.Column="1">
    <TextBox.Text>
        <Binding Path="Feed.Link" Mode="OneWay">
            <Binding.Converter>
                <RssMVVM:StringToUriConverter />
            </Binding.Converter>
        </Binding>
    </TextBox.Text>
</TextBox>
This is critical to the flexibility of WPF’s data binding – we’re now directly binding a string (the TextBox.Text property) to a custom class (Uri).  We can now data bind to any type of object, which allows us to do very complex operations.  For example, we can now display different images for Enum values (by having a converter that converts from the Enum value to an image).
To summarize, the data binding in Windows Presentation Foundation provides us with a simple, clean, powerful, and flexible means of displaying our properties inside our user interfaces, as well as automatically updating our properties when the user edits values within controls in our user interfaces.  In addition, it does it in a way that’s completely declarative, with no code required.
* Although you can bind to any object, there are certain types of objects that work better.  In particular, any object that implements INotifyPropertyChanged or derives from DependencyObject will allow for TwoWay binding to work properly.  Collections should implement INotifyCollectionChanged or IBindingList in order to allow for proper TwoWay binding, as well.  This isn’t a requirement, but it is worth mentioning, since it has a large impact on usability.

Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 5, Commands

In the last article, I explained how Windows Presentation Foundation improves upon data handling via it’s excellent support for data binding.  However, data is only part of the equation.  In order to be a more effective framework, WPF also provides us a way to more effectively handle our application specific logic.
It does this by providing a unified model for separating the originator of an action from the effect produced by the action, via the Commanding infrastructure.
Commands in WPF are a very powerful abstraction.  MSDN clearly states the goals of the commanding infrastructure:
What makes commands different from a simple event handler
attached to a button or a timer is that commands separate the
semantics and the originator of an action from its logic.
This allows for multiple and disparate sources to invoke the
same command logic, and it allows the command logic to be
customized for different targets.
This follows a simple, but pervasive goal in WPF – separation of logic from presentation.  In the case of commands, the goal is to decouple an “action” from the object on which its working, as well as from the user interface element that triggers the action.
Also MSDN’s Commanding discussion focuses on the RoutedCommand implementations, for our purposes, we’ll use theICommand interface directly.  ICommand is a simple interface, and it provides two functions:
  1. Provide a means (CanExecute method) to determine whether an action can be run in the current context, as well as a way to track when this changes (CanExecuteChanged event).
  2. Provide a method (Execute) to perform a given action
By providing this in a simple interface, we can make our own class which wraps this functionality into any series of delegates.  In our case, we made an ICommand class called ActionCommand, which lets us do some nice things.
For example, in the DataContext we use for our specific feed information UserControl, we start off by defining an ICommand as a property:
/// <summary>
/// Gets the open feed command.
/// </summary>
/// <value>The open feed command.</value>
public ICommand OpenFeedCommand
{
    get;
    private set;
}
We then initialize this directly using:
this.OpenFeedCommand = new ActionCommand(this.OpenFeed, () => true);
Basically, this provides us a Property, directly on our DataContext, that lets us call an OpenFeed method.  Also, since we can now directly expose the SelectedFeedItem due to Data Binding (as discussed in part 4), we simplify our logic as well.
Now, in our code, we can replace our event handler:
private void ButtonOpenLink_Click(object sender, RoutedEventArgs e)
{
    if (this.Feed != null)
    {
        FeedItem item = this.Feed.Items[this.listBoxFeeds.SelectedIndex];
        if (item != null)
        {
            System.Diagnostics.Process.Start(item.Link.AbsoluteUri);
        }
    }
}
With a dramatically simplified OpenFeed method:
private void OpenFeed()
{
    if (this.SelectedFeedItem != null)
    {
        System.Diagnostics.Process.Start(this.SelectedFeedItem.Link.AbsoluteUri);
    }
}
Our XAML will change, so instead of using the event handler, we switch to specifying the Command for our button directly, using WPF’s DataBinding:
<Button
   Grid.Row="1" Grid.Column="1" Height="23"
   HorizontalAlignment="Right" Margin="0,0,0,0"
   VerticalAlignment="Top" Width="60"
   Command="{Binding OpenFeedCommand}">
Open
</Button>
Note the differences here in approach – we’re accomplishing the same goal (hooking our code into the button being clicked by the user), but in a very different way.
In Windows Forms, and even in WPF when we use the event approach, we’re directly handling the button’s click event, and our logic gets mixed with the fact that we’re using a button in the interface.  If we were to change from a button to a menu, or a hyperlink, or some other control, we’d have to change our code to handle the different type of event, and move our logic across.  The code is always aware of what control is triggering some action.
Now, by using an ICommand, we’re doing something different.  What we are accomplishing here is making two statements in our code:
  1. Our user should be able to call a command to Open a feed (OpenFeedCommand)
  2. The OpenFeedCommand performs this function (launches the browser with the feed’s URI).
Nothing in the code knows how this command will get invoked – it can be from a button’s click (as it is here), but it could just as easily be triggered by any ICommandSource, including a HyperlinkMenuItem, or even a KeyGesture.
The important point here is that the code does not know, or care, what triggered it.  We could rework the user interface to use completely different controls without changing one line of C# code, because we decoupled the action from what triggered the action by using a Command.

Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 6, Templating

In order to rethink how we architect and write client applications, there is one last important concept Windows Presentation Foundation introduces, beyond the excellent Data Binding and Commanding support I’ve already discussed.  WPF adds an entire suite of features specifically related to Styling and Templating.  This is often discussed in relation to improving the overall look, feel, and usability of applications written using WPF – the key to the new user experience (UX) WPF allows.  However, the templating engine introduced with WPF has other side effects, which change the way we should design our software, not just change the way we stylize our software.
Windows Presentation Foundation, in its design, strives to keep a clear separation of presentation and logic.  This is apparent throughout its architecture, but perhaps most notable in one of the core building blocks of every WPF application: the Control class
Controls, in WPF, have two completely separate parts.  There is the logical portion, and then there is a ControlTemplatethat defines how the control is represented visually; how the control looks.  The difference in thinking, even in this core element, is apparent from the documentation.
Here is how the Control class in Windows Forms is described in MSDN:
Defines the base class for controls, which are components with visual representation.
Compare that to the Control class in WPF:
Represents the base class for user interface (UI) elements that use a ControlTemplate to define their appearance.
Note the difference here.  Even the most basic definition of a “Control”, the core component used to build applications, has changed in Windows Presentation Foundation.  In Windows Forms, when you defined a control, you defined everything about the control directly.  Take a button – a button not only had to deal with the fact that it has behavior (its something visual on which you click, which in turn triggers behavior) – it also directly handled its own rendering.  Typically, if you wanted to make a Button that looked dramatically different from the standard button, you’d make a custom control (ie: a separate class), where you’d handle, not only the button’s behavior, but also all of the code required to paint the customized button.  In WPF, making custom controls is much less common – instead of making a separate class for the new button, you could just make a custom Style, a ControlTemplate which completely changes the way the button is rendered.  However, the behavior of the button is the same, since it’s still uses the standard “Button” class.
This is the key to making WPF applications highly designable – it’s very easy to allow a designer to go in and completely customize the look and feel of every part of your application without introducing custom controls.  Many people tout this as WPF’s advantage over Windows Forms, as well as nearly every other preceding UI technology.
In our case, however, we’re interested in how to architect our application from a code standpoint, not how to make it pretty.  The styling and templating engine in WPF provides another very critical component: the DataTemplate.
Data templates are most often used by WPF controls whose purpose is to display a collection of items.  These typically are the classes that derive from ItemsControl, such as ListBox and TreeView.  For our purposes, lets look at ListBox.
In Windows Forms, when you had a ListBox, by default it just displayed a list of items as text.  Changing this requiredcreating an owner drawn list box, which was a challenge, even for a simple change in style.  This requires handling your own GDI+ drawing using the Graphics class, and pushed everything into code that is difficult to write and maintain.
In WPF, this is handled by a DataTemplate.  By default, you can bind a collection of any objects to a ListBox, and the ListBox will list the results of calling Object.ToString() on each element of the collection.  Custom drawing is handled very easily by using a DataTemplate.  In the Styling and Templating example, the DataTemplate creates a Border with a nested Image, bound to the Source property of each element.  This causes the ListBox to display a list of Images.
In our RSS Feed Reader, we use the same technique to display a list of FeedItems.  Our ListBox is bound directly to a list of our RssModel.FeedItem class, and without a DataTemplate, we see:
ListBox with No Template
However, in our UserControl, we added a very simple DataTemplate:
<DataTemplate DataType="{x:Type model:FeedItem}">
    <TextBlock Text="{Binding Path=Title}" />
</DataTemplate>
This causes our display to change.  Now, instead of just listing the class name (the default behavior of ToString() on our RssModel.FeedItem class), we display a TextBlock containing the FeedItem’s Title property:
ListWithTemplate
This is much nicer, and very simple to implement. 
DataTemplates, however, go far beyond just displaying Text – we could have displayed borders, images, text, or any other complex item we wished, merely by specifying a template in our UserControl.  The idea behind a DataTemplate is that you specify, in XAML, how any object should be represented visually.  This lets us tell the user interface todirectly render a custom class, without the code needing to know or worry about the class being rendered properly.
In our case, we used that to customize the display of a list of FeedItems.  The MSDN sample displayed a list of Photo classes using pictures surrounded by a border.  This flexibility is the key to rethinking our architecture, and in our final installment, I’ll delve into how and why this should change the way you think about designing client applications.

Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 7, MVVM

I mentioned in the introduction that a new architectural pattern has emerged for Windows Presentation Foundation:Model-View-ViewModel.  As I mentioned, MVVM can make developing applications in WPF efficient, quick, and highly maintainable.  Now that I’ve covered some of the basic technological advances in WPF, mainly Data Binding,Commands, and Templating, it’s time to bring everything together, and demonstrate how this improves our jobs as developers.
As I mentioned in the section on templating, WPF’s design strives to maintain a clear separation between presentation and logic.  We’ve seen some of the advantages in terms of control creation – unlike Windows Forms, we can completely change the way a control looks merely by creating a new template, using XAML in a completely declarative form.  No code is required.  We get more flexibility with less work.  By separating presentation and logic, WPF creates opportunities for much greater degrees of flexibility in our applications.
As a developer, I see this as a very “good thing”.  The Model-View-ViewModel pattern has one goal – to extend this same flexibility into our applications by creating and maintaining a clean separation of concerns through our entire application.
In order to understand MVVM, I will start off by defining our distinct concerns, the individual “parts” of our application. 
I already defined our arguably most important concern: the Model.  Again, the Model is the domain-specific data and logic used within your application.  It’s the goal – the “data” you’re working to expose to your users.  This may be customer records in a database, or product information on a website, or anything else.  In our case, it’s two classes, the Feed and the FeedItem class.  In Model-View-ViewModel, our goal is to keep the model unaware of the specific application or technology that’s using it.  The Model knows about itself, and nothing else.
The second concern I’ll discuss is the View.  The View is the entire user interface of your application – it’s everything the user’s interact with directly: every control, every button, every check box, every window.  As I mentioned in part 3, WPF changes how the View is normally defined.  Instead of developing the user interface via code, we use XAML to create an XML-based, declarative description of the interface.
Let’s review our goal of maintaining a full separation of presentation and logic, this time just in terms of the View.  When we create our user interface, we want to define what the user will see (presentation) without worrying about how the program works (logic).  XAML is perfect for this, as it lets us design the user interface with zero code involved.  This gives us an easy way to think about our View in terms of our goal: The user interface should be declared entirely in XAML, with zero code behind.
Succeeding in this goal has many advantages.  It makes the View very flexible – a designer can take our View and stylize it or change it in any way desired, without changing or effecting a single line of code.  Also, if there is no logic in the View itself, it eliminates the risk of “stale” or unused code creeping into the View, which often happens in Windows Forms.
Now that we have the View and the Model defined, we need a way to hook the two things together.  Something has to coordinate our actions between the Model and the View, so that the user’s interaction has an effect on the Model.  This is handled by our third concern: the ViewModel.
The ViewModel serves the purpose of adapting the Model to be directly usable by the View.  In order to do this, we take advantage of WPF’s incredible Data Binding support.  In MVVM, the ViewModel sits between the View and the Model, and basically acts similar to an Adapter – it translates the properties and methods of the Model to a form that can be directly used via Data Binding.
The ViewModel also provides us a place to manage application state and logic.  By taking advantage of WPF’s Commanding Infrastructure, we can define ICommand instances in the ViewModel that the View can directly access via Data Binding.  This provides us a clean way to keep the logic out of the View – again, the View works completely via Data Binding to the ViewModel.  This provides a means by which we can hook into logic from the View without having the logic be tied to the specific view that is using it.
Here is a diagram illustrating our three areas of concern:
MVVMThere are some important aspects of this diagram I will discuss, for each of our Concerns, some critical points
  • The Model
    • The Model is unaware of anything except itself
    • The Model could be used by any form of program, and is not tied to a specific framework or technology
  • The View
    • The View is defined entirely in XAML
    • The View only needs to know what to bind to, by name.  It does not need to know anything about what will happen when properties change or commands are executed.
    • The View’s state is completely based upon data binding
  • The ViewModel
    • The ViewModel knows nothing about the View
    • The ViewModel directly interacts with the Model, in order to expose it for data binding
    • The ViewModel manages the Application-specific information
The advantages here are profound:
Our Model, since it is self contained, can be used in any way we wish.  If, later, we decided we needed a web-based API to the same model, we could use the Model unchanged.  If the successor to WPF comes along, and we need to update our application to use it, the Model remains unchanged.
Our View, since it has no logic, is completely designable.  The View can be modified by a designer with little or no programming experience, with no fear of breaking the logic.  The only knowledge that the designer needs to know is what properties and commands are available, and their names – everything else is handled directly by the framework to make it work.  This leads to a tremendous amount of flexibility in the View – the entire look and feel of an application can be changed at any time.
Our ViewModel gets a nice advantage from this architecture, as well.  Since it is not tied to a specific View, it is very easily testable.  The logic of our application is all exposed through self-contained ICommand implementations, which are easy to test.  The data is exposed via properties; again, easy to test.
There is still one issue left to resolve, though.  At this point, we know how to architect a single window or form correctly – the Model is used by the ViewModel, and the View “hooks” into the ViewModel with data binding.  This works great for a single user control – but we still need to create and wire up the controls in the first place.
At first glance, it seems like we’d need to know about the View and the ViewModel in order to do this.  For the ViewModel to be used as a binding source, it needs to be set as the DataContext of the correct View.  We need a way, given a ViewModel, to construct a View and set its DataContext.  In order to do this, we break one of our rules – the ViewModel, in order to construct the View, needs to know about the Views.
WPF, again, provides us with the final tool required for MVVM: Templating.  The same mechanism that our ListBox used when we discussed templating can be used for our ViewModel.  Instead of trying to construct our View, we can setup a simple DataTemplate that specifies that our View is used to render our ViewModel.  This will look similar to:
<DataTemplate DataType="{x:Type local:OurViewModel}">
    <local:OurView />
</DataTemplate>
This DataTemplate tells WPF that, any time we say to directly render an instance of OurViewModel, it should construct an instance of OurView, place it at that location, and set the DataContext of the OurView instance to the instance of OurViewModel.  Basically, WPF will do all of the work for us, just be specifying a DataTemplate.
Since DataTemplates are definable in XAML, and will propagate downwards through the Visual Tree in WPF, this lets our View automatically set itself up.  All that needs to happen is to provide a ContentPresenter in our View which binds, using standard DataBinding, to a ViewModel, and WPF will do all of the plumbing for us!
WPF adds three profound features: Data BindingCommands, and Templates.  By using these three feature sets appropriately, we can redesign the architecture of our applications by using the Model-View-ViewModel pattern. This maintains a clear separation of concerns, allows for easy changes and redesign of the View, provides good testability, and keeps our domain specific classes completely isolated.

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 BindingCommands, 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.







Niciun comentariu:

Trimiteți un comentariu