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:

WinFormFeedReaderMain There’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

… Continued in Part 3, Our Application in WPF …

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

Comments

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

Trackbacks

Check out what others are saying about this post...
  1. [...] we’re going to demonstrate this.  We’re going to write the same application we wrote using Windows Forms in Part 2, this time, using [...]

  2. [...] example, in both our Windows Forms and WPF (version 1) applications, we had a UserControl defined for displaying information about our [...]



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!