Sponsored Links


Resources

.NET Research Library
Get .NET related white papers, case studies and webcasts

Windows Presentation Foundation and your architecture - Where does it fit?Windows Presentation Foundation and your architecture - Where does it fit?Windows Presentation Foundation and your architecture - Where does it fit? Discuss DiscussDiscuss Printer friendly Printer friendlyPrinter friendly
Windows Presentation Foundation and your architecture - Where does it fit?

November 2, 2006

Windows Presentation Foundation (WPF) is a new client user interface technology that ships as part of the .NET 3.0 Framework. Architects have long faced the challenge of selecting an appropriate presentation tier technology for their applications. In recent times, if you are developing for the Windows platform, it was at least a fairly short list. You either built a web application, a smart client, a mobile device, or some combination of those depending on your target audience. Which one you picked gave you a fairly short list of practical options in the .NET space - ASP.NET, Windows Forms, and Compact Framework respectively.

Now a new option is just over the horizon and you will need to start considering it as well. WPF fits mostly in the smart client space, but there are some overlaps with the web space as well. For the time being there is no WPF for mobile devices, but WPF Everywhere, an upcoming derivative technology, will bring some capability for devices in the near future. This article briefly discusses the key concepts of WPF, how it fits into your presentation tier architecture, and how it will change the way you currently develop your client applications. It will also discuss the interoperability capabilities of WPF with Windows Forms, and will show an example of using that capability to migrate incrementally to WPF instead of making a wholesale change.

WPF Overview

The first question that may occur to you when approaching WPF is to ask why we need a new presentation technology. We have Windows Forms for smart clients; we have ASP.NET for the web. Why not just enhance those technologies to add new capabilities? The problem with trying to build in new functionality using existing technologies is that often to take something to a new level you need a completely new foundation on which to build those capabilities. You can't build a skyscraper on a slab designed for a two story building, you have to tear it all down and start over. When it comes to designing presentation tier solutions, the web is great at some things, and Windows Forms is great at others. But as architects and developers, we want the best of both worlds. This is what WPF is striving to provide for us.

WPF breaks the mold of traditional Windows desktop applications by introducing a presentation technology that is highly focused on maximizing the sensory experience for the user, primarily the visual experience. The web has evolved quite a bit and it is actually easier to present rich, visually compelling content within the browser using a combination of images and styles and text and even audio and video than it is to do the same in a Windows application. However, providing a rich interactive experience with the displayed content is much harder on the web than in Windows applications due to the disconnected request-reply model of the web. This is getting better with the introduction of AJAX technologies, but it is just a fact that if you want to maximize the user's interactive experience, you need an application that is harnessing the full capabilities of the desktop operating system. WPF makes it easy to present rich graphics with rich interaction within a Windows application and via the web by leveraging the capabilities of the client machine. Figure 1 shows an example application developed by InterKnowlogy that allows interactive manipulation (selection and rotation) of 3D models.

Figure 1: InterKnowlogy 3D Collaborator

One of the core concepts of building a WPF application is that everything you compose your application of is just an element. Controls, shapes, 3D models, images, sound, video, and styles are all just elements. Some of the things WPF allows you to easily present include:

  • Styled content (colors, fonts, images, shapes) applied uniformly throughout the application elements
  • 2D and 3D shapes, images, and models
  • Traditional UI controls
  • Animation of any element

Another key feature of WPF is that it raises the level of abstraction when developing Windows applications. First there is a blurring of the line between UI controls, graphics objects, styles, and other objects within the application so they can all be treated as elements. You can define resources from individual elements or collections of elements, and use those throughout the application. You can define data sources that flow through the application without any direct coupling between the bound controls and the data that they are presenting. You can even define control templates that replace the presentation rendering of a control from how it was originally designed to render itself.

WPF also allows you to define the static structure of your application through markup using the new eXtensible Application Markup Language (XAML). This approach is similar to the way ASP.NET uses markup to separate the layout from the dynamic behaviors of the application. With WPF, you can express all, part, or none of your code in XAML. Like ASP.NET, XAML allows you to include script blocks in the markup file that contain C# or VB code, so you could write entire applications in XAML files. However, the default way of using XAML in Visual Studio will be to use XAML to define the structure of your user interface elements, and then use programmatic code in a separate C# or Visual Basic code-behind file to hook up the dynamic aspects. However, you are not constrained to that and you could write your entire application in pure code or pure XAML, depending on what the application is designed to do and how you want to manage the code artifacts.

Adopting WPF

WPF ships with the .NET 3.0 Framework and is supported on Windows XP SP2, Windows Server 2003, and Windows Vista. This is a critical consideration for adopting WPF. If you cannot get the .NET 3.0 Framework installed on your user's machines, you can't use WPF for you client applications.

Another key consideration has to do with how productive you will be in developing your presentation tier application if you adopt WPF right away. Even though the runtime WPF libraries are part of the .NET Framework 3.0 and will be released in November 2006, the design time tools for WPF will not be released until the next version of Visual Studio releases (code-named "Orcas"). There is a Community Technical Preview (CTP) version of the Orcas designer for WPF available now, but it is fairly immature when compared to the Windows Forms or ASP.NET designers. There is also a beta version of the Expressions Interactive Designer, a new design tool for developing WPF applications, but it too has a ways to go before it can be considered production coding ready and it is targeted more for professional designers instead of developers, so the experience will not be what you are used to in Visual Studio.

As a result of the state of the union of WPF design tools, you need to carefully consider whether you want to adopt WPF immediately upon the release of .NET 3.0, or whether you want to wait for the design tools to mature further. If you are trying to develop standard business applications (with lots of traditional controls such as buttons, textboxes, combo boxes, and data grids), then you will likely experience a measurable productivity hit in developing those applications with WPF. Partly this decrease in productivity will be due to the learning curve of adopting a new technology, but even discounting that, you will have some impacts to your development schedule driven by the immaturity of the design time tools. You will have to develop most of your UI by banging out XAML, C#, or VB code instead of being able to use a lot of drag and drop manipulation of controls in the designer. There are some capabilities in the WPF designer for drag and drop definition of controls at this point, and they will continue to mature over time. But at the present time, there is a significant gap in capability between the WPF designer and the Windows Forms designer when it comes to getting the layout of your windows defined and configuring all their control properties and data binding. There are also some shortcomings in the available control set, with the notable absence of a data bound grid control, that will make some common business application use cases much harder to implement in WPF than they are in Windows Forms at the current time.

On the other hand, if you want to adopt WPF to take advantage of some of the rich graphical capabilities of WPF such as 3D models, animation, and rich styling of your application, you will be able to achieve those things much more quickly and cleanly using WPF than you can using the available capabilities in Windows Forms. So it really depends on what you are trying to accomplish. The trade off of a slow down in coding buttons, textboxes, and forms may be well worth the ability to take the appearance and graphical capabilities of your application to the next level. Visually compelling applications could make the difference between success and failure of a presentation tier application, especially if the target audience are consumers.

One way to mitigate the potential loss of productivity for mainstream business applications will be to use a mix a Windows Forms and WPF. There are good interoperability capabilities between the two technologies as discussed in a later section in this article. So you can take advantage of interoperability to use Windows Forms and WPF in a single application where each technology makes the most sense. You can also use this capability to gradually migrate an existing application to WPF.

WPF Application Types

There are two types of WPF applications that you will have to choose from: traditional Windows desktop applications, and XAML Browser Applications. WPF Windows applications run on the user's desktop in their own process and can harness the full capabilities of the .NET Framework, WPF, and other resources on the client machine. XAML Browser Applications are WPF applications that run within the browser.

The concept that XAML Browser Applications run within the browser can be a little misleading. WPF is not a replacement for other web technologies. The compelling aspect of web browser client technologies is their ability to run across multiple browsers and multiple platforms. In other words, your users can be running on a much wider range of configurations than they can for Windows desktop applications. A XAML Browser Application has the same restriction as a full blown desktop WPF application: the .NET 3.0 Framework must be installed on the client machine. That means the client has to be Windows XP SP2 or later, which is a much more restrictive set than just saying they need a compatible browser.

There is an additional restriction to be aware of with XAML Browser Applications: they are only granted the security permissions of the Code Access Security zone from which they are run (based on the address you access them with in the browser). This means pretty much every XAML Browser Application will be run in the Local Intranet or Internet zones, which have severely restricted permissions. As a result, you cannot do much with a XAML Browser Application other than present rich graphics or make web calls back to the site of origin. Your XAML Browser Application will not be able to access the client file system, access a database, or make web calls to any other site than the one from which it came.

You may be wondering why you would use a XAML Browser Application given those restrictions. The main reason in my mind would be to present a consistent user experience if the way the user will be getting to your functionality is through an existing web site or portal. By using WPF, you can still present them with a richer and more interactive experience than you can with other web technologies, but to the user it will appear as if they have just transitioned to another page on the site and the fact that the "page" is using WPF will be transparent if they have .NET 3.0 installed on their machine.

WPF/e

WPF Everywhere (WPF/e) is a derivative technology that will extend the reach of WPF to allow you to build applications based on WPF that both run in the browser and can be run by a much wider range of clients including other platforms. WPF/e will not release with WPF in .NET 3.0, but will release sometime later, hopefully in 2007. WPF/e will use an ActiveX control or some other form of auto-installed hosting component within the browser. The component will render and run WPF content and controls within the browser without relying on the hosting browser's object model or specific scripting capabilities. An easy comparison here is to think of WPF/e as a similar technology to the way Macromedia Flash or Apple QuickTime run in the browser and present content that is richer than what the browser itself is capable of. In the case of WPF/e, the content that will be rendered will be WPF applications. The functionality that will be supported in WPF/e will be a subset of the full capabilities of the WPF API and is not yet final. But I would expect that the capabilities will be very similar to what I discussed earlier for XAML Browser Applications - you can do very rich graphics and audio and make calls back to your site of origin (possibly using AJAX technology in the hosting page), but not much else with respect to accessing other resources. However, with a good distributed architecture that exposes services from the hosting site could let you implement a lot of functionality using WPF/e. Keep your eyes out for more information coming out about WPF/e in the future.

Developing WPF Applications

When developing WPF applications, depending on what your application needs to do, you will be able to choose from a code-only, XAML-only, or mix of XAML and code approach. The latter will be the most common because that is where you will derive the best benefits from the design tools, maintainability, flexibility, and making your code as expressive as possible. Ultimately, everything you do in WPF is just coding against types in the WPF .NET class libraries, so the full range of functionality is available to you from code. Using XAML markup just lets you put things that can be expressed more declaratively in a form that is easier for both design tools and human designers to manipulate and define.

A WPF application is composed of a hierarchy of elements. The basic programming model at a top level is not all that different from Windows Forms. You create an instance of an Application class, create a top level window from the Window class (or a derived class), and set the application running. Like a Visual Basic Windows Forms application, the entry point (Main method) will be automatically generated for you if you do not explicitly create one of your own.

For example, the following two XAML files shown in Figure 2 declaratively create an Application class instance and a Window class instance. The window has a Grid as its first child element. The Grid control in WPF is like an HTML table or the TableLayoutPanel in Windows Forms 2.0 - it just gives you a rectangular grid container into which you can place other elements for layout purposes. Inside of the grid, the XAML defines two rows and two columns, and then places two TextBlock controls (think Label in Windows Forms) and two TextBox controls into the grid cells using attached properties.

// App.xaml
<Application x:Class="SimpleWPFApp.App"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml"/> 

// Window1.xaml
<Window x:Class="SimpleWPFApp.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title=" SimpleWPFApp" Height="100" Width="270">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0">Name:</TextBlock>
    <TextBlock Grid.Row="1" Grid.Column="0">Phone:</TextBlock>
    <TextBox Grid.Row="0" Grid.Column="1" Width="150"/>
    <TextBox Grid.Row="1" Grid.Column="1" Width="150"/>
  </Grid>
</Window>

Figure 2: Simple XAML Application

The resulting (fairly uninteresting) application is shown in Figure 3. Note that the window is displaying with Windows Vista border and title bar styles because that is what I am running it on. If run on a Windows XP or Server 2003 machine, it would have standard title bar and border styling for those operating systems.

Figure 3: Running XAML Application

The same application could be expressed in code-only as shown in Figure 4.

class Program
{
    [STAThread]
    static void Main()
    {
        Application app = new Application();

        Window win = new Window();
        win.Width = 270;
        win.Height = 100;
        win.Title = "SimpleWPFAppCodeOnly";

        Grid grid = new Grid();
        win.Content = grid;

        RowDefinition row1 = new RowDefinition();
        row1.Height = new GridLength(0, GridUnitType.Auto);
        RowDefinition row2 = new RowDefinition();
        row2.Height = new GridLength(0, GridUnitType.Auto);
        grid.RowDefinitions.Add(row1);
        grid.RowDefinitions.Add(row2);

        ColumnDefinition col1 = new ColumnDefinition();
        col1.Width = new GridLength(0, GridUnitType.Auto);
        ColumnDefinition col2 = new ColumnDefinition();
        col2.Width = new GridLength(0, GridUnitType.Auto);
        grid.ColumnDefinitions.Add(col1);
        grid.ColumnDefinitions.Add(col2);

        TextBlock label1 = new TextBlock();
        label1.Text = "Name:";
        grid.Children.Add(label1);
        TextBlock label2 = new TextBlock();
        label2.Text = "Phone";
        grid.Children.Add(label2);
        TextBox tb1 = new TextBox();
        tb1.Width = 150;
        grid.Children.Add(tb1);
        TextBox tb2 = new TextBox();
        tb2.Width = 150;
        grid.Children.Add(tb2);

        Grid.SetColumn(label1, 0);
        Grid.SetColumn(label2, 0);
        Grid.SetRow(label1, 0);
        Grid.SetRow(label2, 1);
        Grid.SetColumn(tb1, 1);
        Grid.SetColumn(tb2, 1);
        Grid.SetRow(tb1, 0);
        Grid.SetRow(tb2, 1);

        app.Run(win);
    }
}

Figure 4: Code-Only Version of SimpleWPFApp

As you can see from the code-only version, despite the fact that XML is often more verbose than code, in the case of many WPF elements, the XAML is actually slightly more compact simply because many properties can be set on a single element through XML attributes inline rather than requiring a separate line of code to set the property. Also, you don't have to explicitly add an element as a child of another element because in the XAML that relationship is implicit in the nesting of the markup tags.

You can also see from the code that the composition that results from the XAML is not all that different from what you do in Windows Forms or ASP.NET. The Window is the top level element, you add the Grid as a child element, you add the TextBlock and TextBox controls as child elements under the grid, and so on.

When you start to hook up event handlers to control events, you usually will do that through C# or VB code. The XAML code gets compiled into a partial class to which you can add any additional code through another partial class file. Visual Studio follows a similar approach to ASP.NET on this, where it creates a Window1.xaml file for the markup, and a Window1.xaml.cs file for the "code-behind" in the partial class.

Another thing you might be staring at trying to understand are the XAML attributes or lines of code where you specify what column and row the contained controls are. Doing this uses a new concept in WPF called Attached Properties. In the XAML, it looks like there are properties named Grid.Row and Grid.Column defined on the control classes themselves. Clearly defining properties on controls for every possible context they could be used in would turn the object model into a horrible mess. However, the code-only version makes it more clear what is really going on. The attached properties are just calling static methods on the Grid class to set a grid-level property related to the contained control. If you have been exposed to Windows Forms Extender Provider controls, the concept is similar here.

Building up more complex WPF application follows a similar pattern to what you have seen here. You just define more elements in a hierarchy that compose the windows of your application. Those elements may be any combination of container controls like the Grid, individual controls like the TextBox, styles, geometries, animation timelines and storyboards, 3D models, videos, and so on.

Interoperating with Windows Forms

As mentioned earlier, you do not have to build WPF applications from scratch and abandon Windows Forms. You can migrate applications from Windows Forms to WPF, or you can incorporate Windows Forms features into new WPF applications if there are existing Windows Forms controls that you want to leverage in a WPF application.

One common example that may make you want to interoperate at first is the need to present a data bound grid of information. There is no DataGridView control equivalent in WPF at the current time. You have to dynamically create something from a combination of the more primitive controls that are available. This is a daunting task when you consider how much functionality is built into the DataGridView. You may also face the same problem with respect to 3 rd party control libraries in which you have a significant investment.

Interoperability between WPF and Windows Forms works very easily and does not require a lot of code. The fact that both technologies are based on managed objects makes it a lot easier. Basically what you have to do on either side is create a host control for the other technology and put the other technology controls into that host. For hosting WPF controls within a Windows Forms application, the host control is called the ElementHost. For hosting Windows Forms controls in a WPF application, it is WindowsFormsHost.

As an example, say you had a Windows Forms application that presented numerical data and you wanted to incorporate a graphical view of that data. You could write a WPF control that performs the drawing operations using WPF primitives for graphics. But you could host that control in your Windows Forms application providing a seamless experience for incrementally starting to take advantage of WPF.

As an example, you could define a custom WPF user control as shown in Figure 5. This control is designed to use WPF drawing objects to draw lines on a drawing surface. You can see that the way it "draws" the lines is simply by adding Line elements to the Children element collection of the Canvas control contained in the UserControl.

<!-- WPFLineControl.xaml-->
<UserControl x:Class="WPFLineControlLib.WPFLineControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
      <Canvas Name="DrawingSurface" />
    </Grid>
</UserControl>

// WPFLineControl.xaml
public partial class WPFLineControl : 
System.Windows.Controls.UserControl
{
  private BindingList<Line> m_Lines = 
  new BindingList<Line>();

  public BindingList<Line> Lines
  {
     get { return m_Lines; }
     set { m_Lines = value;}
  }

  public WPFLineControl()
  {
     InitializeComponent();
     Lines.ListChanged += OnLinesListChanged;
     RefreshDrawing();
  }

  private void OnLinesListChanged(object sender, 
  ListChangedEventArgs e)
  {
     RefreshDrawing();
  }

  public void RefreshDrawing()
  {
     DrawingSurface.Children.Clear();
     foreach (Line line in Lines)
     {
        DrawingSurface.Children.Add(line);
     }
  }
}

Figure 5: WPFLineControl Custom Control

You could then easily host this control in a Windows Forms application, and even dynamically populate the WPFLineControl's Lines property through Windows Forms data binding to a DataGridView that displays the Lines collection. The Form class code is shown in Figure 6.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        // Create the hosting container for WPF controls
        ElementHost host = new ElementHost();
        host.Dock = DockStyle.Fill;
        m_ContainerPanel.Controls.Add(host);

        // Create the WPF control itself and add to host
        WPFLineControl ctrl = 
		new WPFLineControl();
        host.Child = ctrl;
        // Data bind the windows forms controls to a property 
        // exposed from the WPF control
        m_LinesBindingSource.DataSource = ctrl.Lines;
        AddLines();
    }
}

Figure 6: Windows Form Class Hosting WPF Control

The form uses Windows Forms 2.0 data binding (see my book Data Binding with Windows Forms 2.0 for more details) and had a DataGridView control added to the form from the Data Sources window. The grid was data bound to the Line type from the WPF libraries, which is just a managed object. The grid presents the X1, Y1, X2, Y2, Stroke, and StrokeThickness properties of the Line class so that they can be set from the Windows Forms application. When rows are added into the grid, they are added to the Lines collection maintained by the WPFLineControl because the DataGridView is data bound to a BindingSource component named m_LinesBindingSource, and the binding source is bound to the Lines property on the WPF control.

Note that all that is required here is to create an instance of the ElementHost control, add it as a child Panel control that is in the form, docked to fill that panel, and then add the WPF control as the Child property of the host. The running application is shown in Figure 7.

Figure 7: Windows Forms Application Hosting WPFLineControl

It is important to note that this sample is seamlessly working with WPF types as data bound objects in a Windows Forms program. This works out because those objects are just .NET objects like any other. The only place that any magic needs to happen is in the rendering of visual WPF objects like the control, and the host controls take care of all that magic for us.

As an example, the Line Color column shown in the Grid is bound to the Stroke property of the Line type. The Line type is a WPF object, and the Stroke property is of type System.Windows.Media.Color (the WPF Color class as opposed to the System.Drawing one used by Windows Forms). The bound column in the DataGridView allows you enter the color name as a string (i.e. Blue, Red, etc.) and the Color class automatically converts it to an instance of the Color class. The Color class has a ToString method that presents the color as hex, which is why you see hex in the figure. No code was needed to support this because the automatic formatting of Windows Forms data binding works cleanly with the WPF objects.

Summary

This article gave you a quick introduction to WPF from the perspective of an architect trying to understand where and when it might fit into their presentation tier applications. You saw that WPF allows you to substantially raise the bar on the graphical presentation capabilities of your applications. WPF overlaps more with smart client applications than web applications, but you can run WPF applications in the browser as XAML Browser Applications if you can accept the restrictions that model imposes. For broader reach in the browser, you will eventually be able to write WPF Everywhere applications that can run on multiple platforms and browsers.

The process of developing WPF applications requires you to get familiar with XAML since that is primarily how you will express the static layout aspects of your windows. You then hook up the dynamic aspects in code. You can also interoperate seamlessly between Windows Forms and WPF to get the best of both worlds and migrate to WPF incrementally as your requirements and the capabilities of the tools evolve. The samples in this article demonstrated the basics of how you do these things. The full sample code is also available as a download.

Authors

Brian Noyes is chief architect of IDesign (www.idesign.net), a Microsoft Regional Director, and Solution Architect MVP. He is a highly rated speaker appearing at numerous international conferences each year and writes for a variety of publications. His latest book, Smart Client Deployment with ClickOnce, will be out in December 2006, and his last book, Data Binding with Windows Forms 2.0, continues in the top-selling .NET books. You can contact Brian at brian.noyes@idesign.net.

News | Blogs | Discussions | Tech talks | White Papers | Downloads | Articles | Media kit | About
All Content Copyright ©2007 TheServerSide Privacy Policy
Site Map