A Guided Tour of Windows Presentation Foundation

 

Tim Sneath
Microsoft Corporation

September 2005

Applies to:
   WinFX Runtime Components September CTP (PDC 2005 Build)

Summary: Get an overview of Windows Presentation Foundation (formerly code-named "Avalon") and a context for this new graphics subsystem. Survey the architecture and major components available within this release for developers. (37 printed pages)

Download the WinFX Runtime Components September CTP (September PDC 2005 Build).

Download the associated sample code, WPF_PDC_Samples.msi.

Contents

Introduction
Windows Presentation Foundation
Layout: Placing Elements on the Screen
XAML
Graphics and Text Services
Text
Styling and Data Binding
Data Binding
Document Services
Application Model
Writing High Performing Applications
Interoperability and Migration
Conclusion
Useful Resources

Introduction

In the last decade, we've seen a bifurcation of models for application development, with both traditional "smart client" installed applications and Web-based applications vying for supremacy in the development arena. Both of these models require a developer to sacrifice features that are taken for granted in the opposing world. Web applications offer reach, ease of deployment and simplicity in return for the loss of state, a more complex development model and a less integrated platform experience, despite the recent rediscovery of technologies like AJAX. On the other hand, the Windows world offers the promise of applications that can work offline and can fully take advantage of client hardware, but forfeit the ease of deployment and myriad of markup tools support that is available for Web applications. There's a clear role for a client application model that offers standalone and browser-based applications, ease of deployment, great tools support, and deep platform integration.

The graphical subsystem that forms the heart of the Windows user experience (the USER32 and GDI libraries) is actually now approaching its twentieth birthday, having debuted in the first version of Windows. Of course, USER32 and GDI have undergone substantial evolution and development over that time, with the introduction of many new services and capabilities in all areas. New presentation technologies such as Direct3D have also come along that take full advantage of the explosion of graphics capability in recent video cards. But most mainstream applications today don't deliver the experience made possible by these graphics cards.

Windows Presentation Foundation

Windows Presentation Foundation (formerly known as "Avalon") is the new strategic graphics subsystem in Windows that provides a unified approach to user interface, 2D and 3D graphics, documents and media. Built on the .NET Framework foundation and utilizing Direct3D for vector-based rendering, it provides a powerful solution for building immersive applications of all kinds. Furthermore, Windows Presentation Foundation enables designers to be an integral part of the development process by providing declarative programming models for "toolability" and flexibility.

Table 1. Windows Presentation Foundation Services

Base Services XAML, Property System, Input and Eventing, Accessibility
Media Services 2D, 3D, Audio, Video, Text, Imaging, Animation, Effects, Composition Engine
Document Services XPS Documents, Open Packaging Conventions
User Interface Services Application Services, Deployment, Controls, Layout, Data Binding

The design principles behind Windows Presentation Foundation can be categorized as follows:

  • Integration: Windows Presentation Foundation offers a unified API that spans the services identified in Table 1. Developers today are faced with a myriad choice of disparate technologies and APIs, depending on whether they are targeting 2D graphics (GDI or GDI+), user interface (USER32 or Windows Forms), media (DirectShow), or 3D (Direct3D or OpenGL). Windows Presentation Foundation provides a single model that is orthogonal across all these services and allows seamless integration of content within a single application. You can use the same constructs for animation, data binding and styling, regardless of whether you are targeting 2D, 3D or text content.
  • Vector graphics. As described in the introduction, Windows Presentation Foundation takes full advantage of the powerful Graphical Processing Units that are part of modern PC systems. At its heart, the composition engine is vector-based, allowing for scaling of all output to match the resolution of a specific machine. The rendering architecture uses Direct3D for all output: on video cards that implement DirectX 7 or later in hardware, Windows Presentation Foundation renders output using the GPU wherever possible. In situations where hardware rendering cannot be used, software rendering is available as a fallback. Lastly, a floating-point logical pixel system and 32-bit ARGB color support provide a rich high-fidelity experience that anticipates future technology needs, such as high-DPI displays.
  • Declarative programming. Windows Presentation Foundation introduces XAML (eXtensible Application Markup Language), an XML-based language for instantiating and populating nested object hierarchies. While XAML isn't exclusively tied to Windows Presentation Foundation, it is inherently suitable for tasks such as UI definition and construction. The design of XAML allows applications to parse and manipulate UI logic at run-time for dynamic workflow scenarios. Importantly, the XAML / code-behind model embodied in Windows Presentation Foundation allows designers and developers to work collaboratively on client application design and development, using tools such as Expression "Sparkle" as well as third-party specialist tools including ZAM 3D and Mobiform Aurora.
  • Easy deployment. With support for both standalone applications and Web-browser applications, Windows Presentation Foundation offers the best of both deployment models. Web-browser applications run from within Internet Explorer, either occupying the entire window or within an inline frame. They offer the ease of deployment for which Web applications are famed, as well as operating within a partial trust sandbox that protects the client machine against malicious applications. Yet they can still take advantage of the local client hardware and use 3D and media services for the richest Web experience available today. On the other hand, standalone applications are locally installed via ClickOnce or MSI technologies and offer full access to the underlying platform.
  • Document lifecycle. Windows Presentation Foundation introduces a new set of document and print technologies. Applications that need to persist data to a local store can use the Open Packaging Conventions, a ZIP-based packaging convention shared with Office 12 that supports core properties and custom metadata, digital signatures and rights management functionality. For applications that want to share documents for collaboration across multiple machines, even without the application installed, the XML Paper Specification allows visuals to be fixed in a printable, portable format.

The architectural diagram shown in Figure 1 identifies the major components of Windows Presentation Foundation. (Note that the sizes of boxes should not be taken as representative of the relative size or importance of each component.)

Aa480221.wpf101_01(en-us,MSDN.10).gif

Figure 1. Windows Presentation Foundation Architecture

At the top level, the Presentation Framework provides a managed API that offers full access to the underlying functionality. The vast majority of Windows Presentation Foundation developers will work exclusively with this layer. The framework includes a large number of standard controls (such as Button, Label, Menu), layout panels, 2D and 3D graphics and text primitives, support for imaging effects, media, animation and document services, and support for interoperability with GDI, DirectX and Windows Forms / GDI+.

The real workhorse of Windows Presentation Foundation is the visual system. Most elements in Windows Presentation Foundation derive from a base Visual class. The visual system composites all the data and produces the output onto the screen. This is where we integrate video and audio, 2D, 3D and animation together, as well as deliver certain text layout services. Lower in the architectural model sits the composition engine, which has the responsibility of rendering a visual tree to the screen, taking account of everything from transparent layers to window region invalidation.

All rendering in Windows Presentation Foundation takes place through Direct3D (indeed the Windows Vista hardware logo program will require a DirectX 9-level GPU). By moving more graphics processing to the GPU, we release the CPU for other work, increasing performance while simultaneously improving graphics quality. These benefits aren't limited to the 3D world, however—2D graphics also take advantage of the same services; GDI is not used within Windows Presentation Foundation except for integration with legacy elements. For machines with Windows Vista, the new display driver model offers superior output with higher performance characteristics for media-intensive applications.

Layout: Placing Elements on the Screen

One of the foundational services of any user interface subsystem is layout – positioning elements within a window. Windows Presentation Foundation layout system is designed to provide support for a flexible, extensible model that is optimized for content and works well with data, styling and controls.

Traditional application platforms such as Win32 barely have a notion of layout: controls are positioned on an (x,y) co-ordinate system on a canvas, and the developer is required to manually provide support for determining the origin and dimensions of any element, taking account of window resizing and display DPI settings. On the other hand, Windows Presentation Foundation provides multiple implementations of layout that size to content and manage the positioning of controls and items within a window.

In Windows Presentation Foundation, almost any element can be used as a host for other elements. For example, a Button can contain an image as follows:

<Window xmlns="https://schemas.microsoft.com/winfx/avalon/2005" >
   <Button Width="260" Height="200" >
      <Image Source="C:\WINDOWS\Web\Wallpaper\follow.jpg" />
   </Button>
</Window>

Aa480221.wpf101_02(en-us,MSDN.10).gif

In addition, Windows Presentation Foundation provides five layout panels that control and constrain the size and positioning of child elements: Canvas, DockPanel, StackPanel, Grid, and WrapPanel.

Note   The SDK contains a great tool for experimenting with XAML called XamlPad. XamlPad provides basic error reporting and a WYSIWYG preview window for the code you're editing.

Layout Panels

Canvas allows you to do (x,y) positioning, similar to what is provided with GDI and GDI+ today. You can also use attached properties to control the location of an item. For example:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <Canvas Background="silver" Margin="20" LayoutTransform="scale 2">
      <Button Canvas.Top="30" Canvas.Left="50">Hello world!</Button>
   </Canvas>
</Border>

Here, Canvas.Top and Canvas.Left are properties from the Canvas class that are applied to the Button to control its location. The LayoutTransform property (part of the FrameworkElement class from which all higher-level classes are derived) scales the output by a 3.0x magnitude.

Aa480221.wpf101_03(en-us,MSDN.10).gif

DockPanel allows you to dock items without worrying about their exact (x,y) positioning:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <DockPanel Background="silver" Margin="20" LayoutTransform="scale 2">
      <Menu DockPanel.Dock="Top">
         <MenuItem Header="File" />
         <MenuItem Header="Edit" />
      </Menu>
      <TreeView>
         <TreeViewItem Header="root1">
            <TreeViewItem Header="child" />
         </TreeViewItem>
         <TreeViewItem Header="root2">
      </TreeView>
      <ListBox>
         <ListBoxItem>listBoxItem1</ListBoxItem>
         <ListBoxItem>listBoxItem2</ListBoxItem>
      </ListBox>
   </DockPanel>
</Border>

Aa480221.wpf101_04(en-us,MSDN.10).gif

StackPanel provides a stacking model that places content from left to right or top to bottom.

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <StackPanel Orientation="Horizontal" Background="silver" Margin="20" LayoutTransform="scale 2">
      <Button Height="30" Margin="5">OK</Button>
      <Button Height="30">Cancel</Button>
   </StackPanel>
</Border>

Aa480221.wpf101_05(en-us,MSDN.10).gif

Grid provides a model that allows row/grid positioning:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <Grid Background="silver" Margin="20" LayoutTransform="scale 3">
   <Button Width="200" Height="60" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="20" >Hello</Button>
   </Grid>
</Border>

In a grid, you can set column and row definitions, which allow you to set width and height. You can set these to absolute values (x pixels wide), or use an asterisked notation to allocate the remaining space after absolute sizing has been taken care of. You can also set a coefficient to determine how the space is allocated. For instance:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <Grid LayoutTransform="scale 3" ShowGridLines="true">
      <ColumnDefinition Width="30" />
      <ColumnDefinition Width="2*" />
      <ColumnDefinition Width="*" />

      <RowDefinition />
      
      <Button Grid.Column="1" Margin="10">Hello world!</Button>
   </Grid>
</Border>

You can specify a shared size for multiple objects with a SharedSizeGroup property. For example, you could use this to specify that two buttons have the same width even if they would normally have different size scopes. For instance:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
<Grid LayoutTransform="scale 2" ShowGridLines="true" IsSharedSizeScope="true" Height="80">
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Buttons" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Buttons" />

<RowDefinition />
<Button Grid.Column="1" Margin="10">OK</Button>
<Button Grid.Column="2" Margin="10">A very long cancel button</Button>
</Grid>
</Border>

WrapPanel models the right hand pane of an Explorer window, allowing you to handle items that flow over to a new row when the current row is full. For example:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005" LayoutTransform="scale 2">
   <WrapPanel Background="Silver" Margin="10">
<Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button 
/> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> 
<Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button 
/> <Button /> <Button /> <Button /> <Button />
   </WrapPanel>
</Border>

Panels are responsible for the layout of their children. They define the size and shape of content, alignments and margins. The child of a panel could be an element such as TextBox or Button, or it could in turn be another panel. For example, a DockPanel can contain a StackPanel.

Items size to their contained content—this is an important concept, because it ensures that localization of an application doesn't require recalibration of the application layout (because, for instance, different languages have different text lengths for the same sentence—"Auf Wiedersehen" compared to "Goodbye" for example). You can apply alignments with the HorizontalAlignment/VerticalAlignment property, and specify margins using a Margin property.

The ScrollViewer provides a scrolling view on a child's content; if the content overflows the available space, a scrollbar will appear and allow the user to move around the content area. For example:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
        LayoutTransform="scale 2">
   <ScrollViewer>
      <TextBlock FontSize="20" TextWrapping="Wrap" FontFamily="Global User Interface">

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce posuere volutpat erat. 
Praesent imperdiet nibh nec pede. Mauris quis orci. Maecenas luctus, risus tempus 
dapibus mollis, magna metus convallis nunc, eget pulvinar eros ipsum consectetuer dui. 

      </TextBlock>
   </ScrollViewer>
</Border>

Aa480221.wpf101_06(en-us,MSDN.10).gif

ViewBox has the opposite effect of constraining the size of the content to fit the parent panel. This provides a kind of auto-zoom effect.

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <Viewbox>
      <TextBlock FontFamily="Global User Interface">
         Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
      </TextBlock>
   </Viewbox>
</Border>

Aa480221.wpf101_07(en-us,MSDN.10).gif

Aa480221.wpf101_08(en-us,MSDN.10).gif

The layout protocol is a recursive process that is a form of negotiation to ensure that all elements get a "fair" amount of space based on their request. Firstly, a measure process takes place where a parent asks the child how big it wants to be, and the child responds with a DesiredSize. Then the arrange process takes place where the parent tells the child how big it's going to be, in the form of an ActualSize property. When calculating, the special value Double.PositiveInfinity means "size to content". You handle this by overriding the MeasureOverride and ArrangeOverride elements for your panel.

XAML

Before going on to look in more detail at the graphical capabilities, let's take a moment to discuss the use of XAML in Windows Presentation Foundation. You've seen that all the samples so far use XAML. However, it's important to be aware that XAML is just convenient shorthand for writing UI code, not a mandatory component of Windows Presentation Foundation. Everything that can be done in XAML can be done using a .NET language such as C# or Visual Basic.

For example, the first example in the layout section above:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <Canvas Background="silver" Margin="20" LayoutTransform="scale 2">
      <Button Canvas.Top="30" Canvas.Left="50">Hello world!</Button>
   </Canvas>
</Border>

could be rewritten in Visual Basic as:

Dim myBorder As New Border, myCanvas As New Canvas, myButton As New Button

With myCanvas
   .Background = Brushes.Silver
   .Margin = New Thickness(20)
   .LayoutTransform = New ScaleTransform(2.0, 2.0)
End With

With myButton
   .Content = "Hello World"
End With

myCanvas.Children.Add(myButton)
Canvas.SetTop(myButton, 30.0)
Canvas.SetLeft(myButton, 50.0)

myBorder.Child = myCanvas 
or in C# as:
Border b = new Border();
Canvas c = new Canvas(); 
Button btn = new Button();

c.Background = Brushes.Silver;
c.Margin = new Thickness(20);
c.LayoutTransform = new ScaleTransform(2.0, 2.0);
btn.Content = "Hello World";
            
c.Children.Add(btn);
Canvas.SetTop(btn, 30.0D);
Canvas.SetLeft(btn, 50.0D);

b.Child = c;

this.Content = b;

You can probably see just from this short example that XAML provides a consistent, neatly hierarchical model for object construction, with no need for the hidden regions of code that are required for Windows Forms today.

But surely XAML isn't a wholesale replacement for other .NET Framework languages? Clearly XML markup can't substitute for the sophisticated constructs and flow control logic, and the XAML design intends it to be used in conjunction with more traditional programming languages. At compilation-time, XAML is compiled into a binary representation within a partial class (a new feature in .NET Framework 2.0 that allows you to spread one class definition over multiple files). You implement the other half of that class using a language of your choice. For example, in Visual Basic:

Partial Public Class Window1
    Inherits Window
...
End Class
and in C#:
public partial class Window1 : Window { ... }

You can naturally access any named element in XAML from your own code as if it had been declared there, since your code is part of the same class.

The use of XAML supports good architectural principles, such as the separation of model and view. Developers and designers can work collaboratively using specialized tools (e.g.,a 3D design tool, a designer tool, a development tool, a high-end typography tool) and so long as they all emit XAML, they can be combined together to build a sophisticated UI.

Graphics and Text Services

As highlighted in the introduction, the current Windows graphics platform (GDI) has a heritage spanning nearly two decades. Over the last few years huge innovation in the 3D space, but GDI developers have seen little benefit from this. Graphics hardware advances today are mainly focused on the 3D pipeline, and Windows Presentation Foundation is designed as a full strategic replacement for older 2D-based technologies, using the graphics capabilities of modern PCs to their fullest. All the different elements of graphics go through the same pipeline: 2D, 3D, text, imaging and video.

Windows Presentation Foundation provides mainstream graphics services for applications and content. It provides an application model that takes advantage of the 3D hardware support prevalent in modern graphics cards. Windows Presentation Foundation places a greater emphasis on vector-based content; it offers resolution independence, with virtual pixels that are mapped to logical pixels and support high DPI screens; the native co-ordinate system is based on a double data type. A side effect of the new rendering model is that image transformations can be applied without additional work (for example, it's possible to apply a blur effect or a scaling factor to any content). Windows Presentation Foundation is also an integrated component of the broader graphics ecosystem: for example, it takes advantage of the new Windows Vista display driver model, it shares capabilities with the print model, and it has high fidelity remoting via Terminal Services.

Aa480221.wpf101_09(en-us,MSDN.10).gif

Figure 3. The North Face In-Store Explorer Prototype

Figure 3 shows a highly immersive application experience that was demonstrated at the PDC 2005 conference. Everything that you see here is powered by 3D. The text takes advantage of sub-pixel ClearType. Composition is taking place to create the video controls: different content types are being put together to create an interactive experience.

There are several tiers to Windows Presentation Foundation development. For managed code, most developers will work at the framework level, using objects from namespaces such as System.Windows.Shapes, System.Windows.Media, or alternatively at the lower visual layer level to replace your existing graphics back-end (accessing drawing primitives without taking advantage of services such as layout and data binding). Unmanaged code can also be used to access or extend services such as imaging codecs and effects.

2D Graphics

Shapes are the most basic 2D graphical element a developer can work with: they include brushes, pens, geometries, transforms etc. All the properties are dependency properties, which means that they can be animated, data bound etc.

For example:
<StackPanel xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
<Slider Name="WidthSlider" Maximum="200" Minimum="10" />
<Rectangle Fill="LinearGradient 0,0 1,1 #FF3366FF #FFFFFFFF" Height="100" 
Width="{Binding ElementName=WidthSlider, Path=Value}" />
</StackPanel> 
Aa480221.wpf101_10(en-us,MSDN.10).gif Aa480221.wpf101_11(en-us,MSDN.10).gif

(We'll cover data binding more fully later in this article.)

Even a simple task like this would be significantly more code in Win32, because of the need to manage repainting. Note also that shapes like Rectangle derive from FrameworkElement, which means that they participate in the layout system. The impact is that in the code below, as the rectangle increases in size, so the ellipse shrinks to fill the remaining available space.

<DockPanel xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
   <Slider Name="WidthSlider" DockPanel.Dock="Top" Maximum="200" Minimum="10" />
   <Rectangle Fill="Red" Width="{Binding ElementName=WidthSlider, Path=Value}" />
   <Ellipse Fill="Blue" />
</DockPanel>

Brushes are used to fill geometries. They come in many different forms: solid, gradient and tile brushes being perhaps the most commonly used. If you spend most of your time in XAML, it's possible to use solid brushes without even realizing it. For example, the rectangle and the ellipse in the prior example both use a green solid brush: it's just that XAML provides a shorthand "mini-language" that converts a named string into a brush of that color.

Gradient brushes can be used for a subtle fade, or for more dramatic effects. For example, try this optical illusion out:

<Grid xmlns="https://schemas.microsoft.com/winfx/avalon/2005">

<!-- Strange optical effect. Stare at this for a while and then change 
     the first gradient stop from Black to LightBlue. For a while, it
     will seem as if the gradient has disappeared altogether. -->

   <Rectangle>
      <Rectangle.Fill>
         <LinearGradientBrush StartPoint="0.0, 0.0" EndPoint="0.01, 0.03" 
                              SpreadMethod="Reflect">
            <LinearGradientBrush.GradientStops>
               <GradientStop Color="Black" Offset="0.3" />
               <GradientStop Color="Silver" Offset="0.8" />
            </LinearGradientBrush.GradientStops>
         </LinearGradientBrush>
      </Rectangle.Fill>
   </Rectangle>
</Grid>

An ImageBrush is a tile brush that allows you to use any image supported by a codec (e.g., PNG, JPEG, or GIF) as a brush. Like any tile brush, the contents of an ImageBrush can be tiled or scaled, and a transform may be used to skew, rotate, scale or translate the image.

One of the most powerful brushes is the VisualBrush, a TileBrush in which any Visual object is the contents. A VisualBrush allows live "secondary" representations of an object (for example, a tooltip that shows a live thumbnail of a window that's already open) or it may be used to create complex graphical effects by embedding any visual content within the brush itself and transforming it in some way.

<StackPanel xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
  LayoutTransform="scale 2">
      <StackPanel Name="reflectedPanel" Orientation="Horizontal">
         <TextBox Width="300" FontSize="48">Reflections...</TextBox>
         <Button Content="OK" Margin="2" />
      </StackPanel>
      <StackPanel Height="{Binding Path=(StackPanel.ActualHeight),
                                         ElementName=reflectedPanel}">
         <StackPanel.Background>
            <VisualBrush Stretch="None" Opacity="0.75"
              AlignmentX="Left" AlignmentY="Top"
              Visual="{Binding ElementName=reflectedPanel}">
               <VisualBrush.RelativeTransform>
                  <TransformGroup>
                     <MatrixTransform Matrix="1,0,0,-1,0,0" />
                     <TranslateTransform Y="1" />
                  </TransformGroup>
               </VisualBrush.RelativeTransform>
            </VisualBrush>
         </StackPanel.Background>

         <StackPanel.OpacityMask>
            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
               <LinearGradientBrush.GradientStops>
                  <GradientStop Color="#FF000000" Offset="0.0" />
                  <GradientStop Color="#00000000" Offset="0.8" />
               </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
         </StackPanel.OpacityMask>
      </StackPanel>
   </StackPanel> 

Aa480221.wpf101_12(en-us,MSDN.10).gif

The SDK provides further samples of the usage of VisualBrush.

If you want to have some artwork that you use throughout your application, you can use a drawing, which represents vector-rendering instructions. These can be declared once and reused many times—a good example of how these are useful is for vector graphics or icons. Drawings are lightweight objects that operate at the visual layer; for example, they don't participate in the layout system, and are thus ideal where performance is the most critical consideration.

One further useful class in Windows Presentation Foundation allows you to combine drawings together with brushes in the form of the DrawingBrush class. This is a tile brush that can be applied to 2D or 3D surfaces, allowing you to take a static vector resource and use it elsewhere (for example to take a vector fill in the background of the UI).

3D Graphics

There's a growing trend in the graphics industry towards 3D, yet this is a challenging area for most developers today. When 3D was designed into Windows Presentation Foundation, it was a clear objective to ensure that there was a tight integration between the 2D and 3D worlds to reduce the complexity of this shift. 3D can be used in 2D scenes, and vice versa; text and media can also be placed in a 3D scene. Many programming concepts carry forward from 2D to 3D, such as scene-based programming and a consistent class hierarchy, in addition to unique 3D features such as cameras, models, lights and materials.

One of the central objects is Viewport3D, a 2D element that hosts 3D content. This describes models, lighting and camera. Model3D is the analogous 3D object to Drawing in 2D; this describes a specific 3D geometry. Materials describe texture and lighting characteristics. Any content can be a brush in a material, including text, video, shapes, drawings etc.

Authoring models by hand is painful; one option is to use a tool such as Electric Rain's ZAM3D. 3D can also be used subtly in user interfaces for data visualization (e.g., 3D charting, transitions between 2D content and super-positioning of multiple 2D data sets).

Aa480221.wpf101_13(en-us,MSDN.10).gif

Figure 4. Channel 9 Guy Rendered with ZAM3D

The 3D APIs in Windows Presentation Foundation shouldn't be viewed as an overarching replacement for DirectX, however. Use Direct3D for immersive 3D gaming, large-scale 3D applications (e.g., CAD) and general-purpose GPU scenarios. Think of Windows Presentation Foundation as the "automatic" equivalent of Direct3D's "manual" / "stick-shift" mode.

Imaging

Windows Presentation Foundation provides support for most common image formats via a library of codecs. To embed an image in your application, it's as simple as using the following XAML:

<Image Width="200" Source="sampleImages\apple.jpg" />

Note that images are fundamentally rectangular, although they can be clipped with a geometry:

<Border xmlns="https://schemas.microsoft.com/winfx/avalon/2005" Margin="20">
<Image 
  Source="C:\WINDOWS\Web\Wallpaper\follow.jpg" 
  Width="200" Height="150" HorizontalAlignment="Left">
  <Image.Clip>
    <EllipseGeometry
      RadiusX="100"
      RadiusY="75"
      Center="100,75"/>
  </Image.Clip>
</Image>
</Border>

You can use an ImageBrush to apply images as a texture. For example:

  <Ellipse Stroke="Purple" StrokeThickness="5.0">
    <Ellipse.Fill>
      <ImageBrush 
         ImageSource="table-bowl.jpg" 
         TileMode="Tile" 
         Viewport="0,0,.3,.3" />
    </Ellipse.Fill>
  </Ellipse>

ImageSource is the base class for vector or bitmap images (DrawingImage or BitmapSource, respectively).

Windows Presentation Foundation has rich and extensible support for metadata, with in-place updates (so that if you change EXIF data in a JPEG, it doesn't have to read and write the entire file). There are also straightforward query capabilities, so you can do for example:

BitmapMetadata m = ((BitmapMetaData)myImage.Metadata); // get metadata from a JPEG
string focalLength = m.GetQuery("System.Photo.FocalLength"); 
string exposure = m.GetQuery("System.Photo.ExposureTime");

Or even (from a TIFF file) acquire non-keyed metadata:

string value123 = m.GetQuery("/ifd/{uint=123}"); // from a TIFF

Media

At the framework element level, there's an object called MediaElement that supports video and audio. You can control this object (play, pause, seek etc.) using timelines and clocks. Windows Presentation Foundation supports WMV, MPEG and some AVIs; in future builds, media will be able to be synchronized with animations.

Effects

Bitmap image effects take a BitmapSource and return a BitmapSource. Typical usage applies the bitmap effect to any Visual object in the visual tree. In the PDC build there are just two image effects supported: blur and drop shadow; more are in the works between now and RTM. Importantly, the image effect model is extensible by others—you can create your own image effects for others to apply.

Here's an example of how you use them:

<StackPanel.BitmapEffect>
   <BlurBitmapEffect Radius="8" />
</StackPanel.BitmapEffect>

Animation

You can animate any dependency property on any Windows Presentation Foundation object. Animations can occur at the object level, but for co-ordination, it's more common that you'll use an animation at the storyboard level. Animations are time-based, rather than frame-based—this gives temporal resolution independence (it doesn't matter how many frames per second get rendered: the speed of an animation is independent of the system performance).

Storyboards operate on triggers, not properties. Triggers are event-driven (for example, Button.Click), and they can drive one or more actions, such as ColorAnimation or DoubleAnimation, which may in turn target properties of multiple elements. Here's an example of animation taking place:

<Page
    xmlns="https://schemas.microsoft.com/winfx/avalon/2005"
    xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">

  <Ellipse Width="200" Height="200">
    <Ellipse.Triggers>
      <EventTrigger RoutedEvent="Rectangle.Loaded">
        <BeginStoryboard>
          <Storyboard>
            <ColorAnimation
                From="Blue"
                To="Red"
                Duration="00:00:01"
                RepeatBehavior="Forever"
                AutoReverse="true"
                Storyboard.TargetName="gradientStop"
                Storyboard.TargetProperty="Color" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
    </Ellipse.Triggers>
    <Ellipse.Fill>
      <!-- Animated Linear Gradient -->
      <LinearGradientBrush x:Name="brush" EndPoint="1,1">
        <LinearGradientBrush.GradientStops>
          <GradientStopCollection>
            <GradientStop Color="Blue" Offset="0" />
            <GradientStop x:Name="gradientStop" Offset="0.5" />
            <GradientStop Color="Red" Offset="1" />
          </GradientStopCollection>
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Ellipse.Fill>
  </Ellipse>
</Page>

In this simple example, the circle appears to change color in a sweep from top-left to bottom-right and then back again, as the middle GradientStop animates from blue to red and then reverses.

Animation is a complex topic, with much more to offer than this overview white paper can cover. Check the SDK documentation for many more samples and details of how to use storyboards from code.

Text

Windows Presentation Foundation introduces the next generation of text rendering using ClearType, with many new advances to further improve the readability of text on a computer display.

Three new enhancements in particular have been added to ClearType in Windows Presentation Foundation:

  • Sub-pixel positioning
  • Natural advance widths
  • Y-direction anti-aliasing

In many of the "black and white" TrueType fonts that were included with Windows 3.1 (e.g.,Times New Roman and Arial) hints were added to many glyphs to change the natural advance width to something that allowed for better symmetry of the characters. Often widths were changed by ±2 pixels. With the low resolution of black and white pixels, things like symmetry are much more important for reading than accuracy of the character width (WYSIWYG). Because of the extra resolution available along the "widths" axis, ClearType allows us to get both the symmetry for the glyphs and more accurate advance widths. Even with this extra accuracy, GDI is still limited to expressing glyph widths in integer pixels, so ultimately all widths round to the nearest pixel.

Because we wanted to enable ClearType for all fonts on the system in GDI, we needed the widths with ClearType on to be the same as with ClearType off (this is what we had previously done with font smoothing.) In order to get this behavior, we had to add a mode to GDI called compatible widths, which forces the advanced width to be the same as black and white. In order to do this we have to insert a little error into the glyphs. Unfortunately, this error noticeably distorts the glyph shape and at smaller glyph sizes makes incorrect gamma settings more problematic (the ClearType Tuner, available as a Windows XP PowerToy, can help here.)

This means that for GDI there are two width options available: compatible and non-compatible widths. By adding some error, compatible widths create widths exactly the same as black and white and font smoothing. Non-compatible widths are called "natural widths" and this mode became available in Windows XP SP1. It provides high-quality ClearType, but since it is in GDI, it is still limited to integer pixels.

Windows Presentation Foundation uses sub-pixel positioned ClearType, which allows the full precision of ClearType to be displayed on the screen. Using this option, glyphs can both start and end on arbitrary pixel positions. This, especially when combined with kerning, allows us to have very high quality word shapes on the display. High-quality spacing is an important part of making good-looking text on the screen. Sub-pixel positioning gives us a very slight loss of contrast, but excellent spacing offsets this. This high precision spacing allows us to position text in a device-independent manner.

Lastly, y-direction anti-aliasing smooths the edges of character glyphs on the vertical axis; while it can't take advantage of RGB sub-pixels in this axis, this capability still further increases the accuracy of text rendering.

All of the text rendering in Windows Presentation Foundation can be hardware-accelerated given a suitable card, using composites, filters, and blends to offload work that would otherwise be performed on the CPU. The enhanced text support in Windows Presentation Foundation is particularly noticeable for users of East Asian fonts, where historically ClearType has been missing and fonts haven't taken full advantage of the platform.

Windows XP with GDI rendering Aa480221.wpf101_14(en-us,MSDN.10).gif
Windows Presentation Foundation Aa480221.wpf101_15(en-us,MSDN.10).gif

Windows Presentation Foundation also supports many new OpenType font features, including fractions, discretionary and contextual ligatures, petite caps, and antique numerals. Here's a simple example of how the new features described above make a big difference. Enter the following line into XamlPad and experiment with how the text renders. (You'll need to use Windows Vista for this experiment because the typeface used is only available on latest versions of the operating system.)

<RichTextBox xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
             FontFamily="Segoe Script" FontSize="44" />

Aa480221.wpf101_16(en-us,MSDN.10).gif

Notice how individual glyphs like 'o' and 't' change completely depending on their context. This is based on additional hinting information in the font that tells a rendering engine which glyph to choose dependent on its neighboring characters. For script fonts in particular, it results in a much more natural "handwritten" look.

For a more dramatic example, take a look at the beautiful way the following typeface is represented, thanks to the support in Windows Presentation Foundation for the Adobe Compact Font Format (CFF). This is Bickham Script Pro:

Aa480221.wpf101_17(en-us,MSDN.10).gif

Again, notice how glyphs change (r, y, l, and g) or even merge (Th) depending on context. These sophisticated capabilities are provided automatically in Windows Presentation Foundation.

In Windows Presentation Foundation, you can display text runs using the TextBlock or TextFlow classes. TextBlock simply displays a single block of text; TextFlow is a useful class when used from XAML to display a few paragraphs of content. At the visual layer, DrawingContext.DrawText() is the equivalent of DrawText in the GDI world, and there are classes representing concepts such as TextRun and Glyph. Lastly, FormattedText is a particularly useful class within the text API. You can take a piece of text, use the BuildGeometry() method to extract the vector geometries, and use them wherever you'd use a regular vector.

As well as rendering support for individual text runs, Windows Presentation Foundation also includes some powerful controls to improve the reading experience. For example, the SinglePageViewer class provides a container for flow documents, which in turn can host rich content. This model is ideal for eBooks and other places where a large amount of textual content needs to be displayed.

<SinglePageViewer xmlns="https://schemas.microsoft.com/winfx/avalon/2005" >
<FlowDocument ColumnWidth="250" ColumnGap="20" ColumnRuleWidth="1" ColumnRuleBrush="Gray" IsColumnBalancingEnabled="False" 
              Background="AliceBlue" FontFamily="Palatino Linotype" FontSize="14" 
              Typography.DiscretionaryLigatures="True" Typography.NumeralStyle="OldStyle">

In many of the "black and white" TrueType fonts that were included with Windows 3.1 (e.g.,Times New Roman and Arial) hints were added to many glyphs to change the natural advance width to something that allowed for better symmetry of the characters. Often widths were changed by ±2 pixels. With the low resolution of black and white pixels, things like symmetry are much more important for reading than accuracy of the character width (WYSIWYG). Because of the extra resolution available along the "widths" axis, ClearType allows us to get both the symmetry for the glyphs and more accurate advance widths. Even with this extra accuracy, GDI is still limited to expressing glyph widths in integer pixels, so ultimately all widths round to the nearest pixel.

Because we wanted to enable ClearType for all fonts on the system in GDI, we needed the widths with ClearType on to be the same as with ClearType off (this is what we had previously done with font smoothing.) In order to get this behavior, we had to add a mode to GDI called compatible widths, which forces the advanced with to be the same as "black and white". In order to do this we have to insert a little error into the glyphs. Unfortunately, this error noticeably distorts the glyph shape and at smaller glyph sizes makes incorrect gamma settings more problematic (the tuner can help here).

<Paragraph><Floater Background="LightYellow" Padding="10" BorderThickness=".5" 
BorderBrush="Gray" Width="140">
    <Paragraph FontFamily="Calibri" FontWeight="Bold" FontSize="18">GDI Widths</Paragraph>
        <List>
      <ListItem><Paragraph>Compatible</Paragraph></ListItem>
      <ListItem><Paragraph>Natural</Paragraph></ListItem>
    </List>
</Floater>

This means that for GDI there are two width options available. Firstly, compatible widths, which by adding some error, creates widths exactly the same as black and white and font smoothing. Non-compatible widths is called "natural widths" and this mode became available in Windows XP SP1. It provides high quality ClearType, but since it is in GDI, it is still limited to integer pixels.

Windows Presentation Foundation uses sub-pixel positioned ClearType, which allows the full precision of ClearType to be displayed on the screen. Using this option, glyphs can both start and end on arbitrary pixel positions. This, especially when combined with kerning, allows us to have very high quality word shapes on the display. High quality spacing is an important part of making good looking text on the screen. Sub-pixel positioning gives us a very slight loss of contrast, but this is made up by the excellent spacing. This high precision spacing allows us to position text in a device independent manner.

</FlowDocument>
</SinglePageViewer>

Aa480221.wpf101_18(en-us,MSDN.10).gif

You can restyle the SinglePageViewer control to match the experience you want to offer (for example, different buttons).

Annotations

Annotation support is built into two document controls that are based on DocumentViewerBase and that support anchoring to flow and fixed content. These controls are SinglePageDocument and DocumentViewer, respectively. With just a few lines of code, developers can enable support for adding and delete annotations. By default annotations are stored to an XML stream using a published schema. With additional code a developer can implement a custom store, for example saving annotations to isolated store or even to a remote server using Web services (e.g., in order to allow annotation sharing).

Two types of annotations are supported in Windows Presentation Foundation: highlighting and notes. Highlighting works just like a highlighter pen for paper: you can select a range of content to be set with a different color. On the other hand, note annotations allow you to add ink or text content to a piece of content, for example, to add a comment. Like any other control, note annotations can be styled; for example, you can set a different background note color for each user/annotator.

Styling and Data Binding

Application styling is a broad term that incorporates resources, styles, templates, triggers and storyboards. Styles centrally define the appearance and interactive behaviors of elements in your application.

Windows Presentation Foundation gives you great power in determining the look and feel of your application, with an easy graduation of complexity compared to technologies like Windows Forms where there was a sudden cliff between basic customization and the owner draw model. The risks are that application authors try to use every technology just because you can and wind up creating distracting and annoying applications. Creating a well-designed application means that the design is appropriate for the application and the target user, it is aesthetically pleasing, it improves usability, and it is lasting—as enjoyable to use the application the hundredth time as the first.

Styles

Styles drive the look and feel of any piece of content. They can be named (and used by name) or targeted at a particular control type (Button), or even both. Styles can even be based on other styles. Here's a quick example that creates a button style:

<StackPanel xmlns="https://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005"
   Margin="15" LayoutTransform="scale 2" >
   <StackPanel.Resources>
      <Style x:Key="MyStyle" TargetType="{x:Type TextBox}">
         <Setter Property="Background" Value="Green" />
         <Setter Property="Foreground" Value="White" />
      </Style>
   </StackPanel.Resources>

   <TextBox Style="{StaticResource MyStyle}">TextBox 1</TextBox>
   <TextBox Style="{StaticResource MyStyle}">TextBox 2</TextBox>
   <TextBox>Unstyled</TextBox>
</StackPanel> 

Aa480221.wpf101_19(en-us,MSDN.10).gif

In this code, you'll notice that we declare a resource dictionary that contains a single named style that targets a TextBox control. Within the style, we set two properties—its foreground and background colors. To take advantage of it, it's just a matter of setting a textbox to use the style from the resource dictionary. Note that the third textbox does not reference the named style, and so receives the default style.

Templates

Templates extend styles by describing the visual structure of a control or data type; they're where a lot of the magic of Windows Presentation Foundation occurs. With templates, you can use composition to describe the object's visual tree. In the following example, we replace the default button style with a styled ellipse:

<StackPanel xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">
   <StackPanel.Resources>
      <Style x:Key="MyStyle" TargetType="{x:Type Button}">
         <Setter Property="Background" Value="SkyBlue" />
         <Setter Property="Foreground" Value="White" />
         <Setter Property="Cursor" Value="Hand" />
         <Setter Property="Template">
            <Setter.Value>
               <ControlTemplate TargetType="{x:Type Button}">
                  <Grid>
                     <Ellipse Name="rect" 
                        Fill="{TemplateBinding Property=Background}" />

                     <ContentPresenter Margin="20,0,20,0"
Name="content" TextElement.Foreground="{TemplateBinding Property=Foreground}" 
TextElement.FontSize="{TemplateBinding Property=FontSize}"
                                             VerticalAlignment="{TemplateBinding Property=VerticalContentAlignment}" 
                                          
   HorizontalAlignment="{TemplateBinding Property=HorizontalContentAlignment}" />
                  </Grid>
                  <ControlTemplate.Triggers>
                     <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="rect" 
Property="Fill" Value="LightBlue" />
                        <Setter TargetName="content" 
Property="TextElement.Foreground" Value="Black" />
                     </Trigger>
                  </ControlTemplate.Triggers>
               </ControlTemplate>
            </Setter.Value>
         </Setter>
      </Style>
   </StackPanel.Resources>
   <Button Height="200" Width="400" FontSize="24pt" Style="{StaticResource 
MyStyle}">Click here</Button>
</StackPanel>

Aa480221.wpf101_20(en-us,MSDN.10).gif

Here you'll see that we use a ContentPresenter within the ContentTemplate to contain the actual content of the object (in this case, the text of the button). We're also binding several of the properties within the ellipse to their parent template, to ensure that as a developer sets those values on the button, so the changes are made to the appropriate underlying elements.

Triggers and Storyboards

Triggers can be used with styles and templates to create rich and dynamic interactions between the user and the application. Triggers are fired when a specified condition becomes true (in the above sample, a trigger was fired when the mouse moved over the button). For another example, see this snippet that changes the background color of an element when it gains focus:

<Trigger Property="IsFocused" Value="true">
   <Setter Property="Background" Value="Purple" />
</Trigger>

You can use TargetName="ContentBorder" within a setter property to target a particular subelement of an object (e.g., an element within a ListBox).

Event triggers allow you to support storyboards, which enable animations. If you don't set both To and From properties, this will work without glitches even if this event overrides another set event.

<EventTrigger RoutedEvent="Mouse.MouseEnter">
   <EventTrigger.Actions>
      <BeginStoryboard>
         <Storyboard TargetProperty="MaxWidth">
            <DoubleAnimation Duration="0:0:1" To="150" />
         </Storyboard>
      </BeginStoryboard>
   </EventTrigger.Actions>
</EventTrigger>

Data Binding

Every application uses data in one form or another. Windows Presentation Foundation provides a rich set of data services to enable you bind to and manipulate data from your application.

In most systems, user interface and the data are separate, both in logical structure and in the developers who build it. Data binding is a bridge between these two entities. But data binding in many platforms today has issues: it operates as a black box, it doesn't fully support different data models (XML, relational, object), and it's hard to extend. The result is that many people wind up ignoring the platform data support and write their own data mechanism.

The data-binding model in Windows Presentation Foundation attempts to address these problems. Data has been a first-class citizen since the start of Windows Presentation Foundation; there is support for data in the property engine as well as declaratively from XAML. Windows Presentation Foundation supports three types of data binding: one-time (ignore server updates), one-way (read-only), and two-way (read-write).

Basic Data Binding

The first thing you need to do is to create a data provider. Data providers can be used to connect to XML, relational or object data sources; you can also create your own provider by deriving from the abstract DataSourceProvider class.

In this example, we create a provider with inline XML data:

<XmlDataProvider x:Key="nodePrototype" XPath="AuctionItem">
<AuctionItem Description="AuctionItem" StartPrice="3.50">
</XmlDataProvider>

Next we simply need to bind to it.

<TextBox>
   <TextBox.Text>
      <Binding XPath="@Description" Source="{StaticResource nodePrototype}" />
   </TextBox.Text>
</TextBox>

If you have multiple bindings within a parent container, you can set the DataContext to this source, which means that you don't have to keep setting the source for each binding. Lastly, a markup extension shortcut allows you to write Value="{Binding XPath=@StartPrice}" within the object itself.

Working with List Content

It's rarely sufficient to bind just to individual items. More commonly, you'll want to bind to a collection of objects and show them together. Windows Presentation Foundation provides an ItemsControl object that you can use to generate your own view of this information. For example, given this data source:

<AuctionItems>
   <Item Title="Slightly unwashed, tatty teddy bear" />
   <Item Title="Threadbare pair of socks" />
   <Item Title="A used tea towel" />
   <Item Title="Packet of cereal, mostly uneaten" />
   <Item Title="A dead stick insect" />
</AuctionItems>

You can bind to it with the following code:

<StackPanel xmlns="https://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">
   <StackPanel.Resources>
      <XmlDataProvider x:Key="myItems" Source="c:\mydata.xml" XPath="/AuctionItems" />
   </StackPanel.Resources>
<Border>
   <ItemsControl ItemsSource="{Binding Source={StaticResource myItems}, XPath=/AuctionItems/Item}"
      DisplayMemberPath="@Title" >
   </ItemsControl>
</Border>
</StackPanel>

ItemsControl listens to changes to the underlying data and updates the view directly. It iterates over each item and generates a ContentControl for each item. A ContentControl allows you to present an individual piece of data the way you want. In this case, we are just showing the default: a label with a value bound to the @Title XPath query.

Data Presentation

In Windows Presentation Foundation, we give developers the ability to choose how their data is presented in abstraction from the binding itself. Data templates provide a way to control the presentation of an item of data in a specific way. In a data template, you can define the data type, such that all instances of this data are displayed in that way.

In this case, we're going to use Windows Presentation Foundation to create an RSS browser using XAML:

<DockPanel xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005" Margin="10">
   <DockPanel.Resources>
      <XmlDataProvider x:Key="Blog" Source="https://blogs.msdn.com/tims/rss.aspx" />

      <DataTemplate x:Key="TitleTemplate">
         <TextBlock Text="{Binding XPath=title}"/>
      </DataTemplate>
   </DockPanel.Resources>

   <Label Content="{Binding Source={StaticResource Blog}, XPath=/rss/channel/title}" 
FontSize="24" FontWeight="Bold" DockPanel.Dock="Top" />      
   
   <Label Content="{Binding Source={StaticResource Blog}, XPath=/rss/channel/description}" FontSize="18" DockPanel.Dock="Top" />

   <DockPanel DataContext="{Binding Source={StaticResource Blog}, XPath=/rss/channel/item}" >
      <ListBox DockPanel.Dock="Left" ItemsSource="{Binding}" ItemTemplate="{StaticResource TitleTemplate}" IsSynchronizedWithCurrentItem="True" />
      <Frame Source="{Binding XPath=link}" Width="Auto" />
   </DockPanel>
</DockPanel>

Aa480221.wpf101_21(en-us,MSDN.10).gif

Here the data template is used to define how each item within the listbox is displayed. In this case, we simply use a TextBlock to show a data-bound item, but we could easily extend this to show graphics, media, hyperlinks or any other content type. The Frame control is used as a host for IE in order to show the details of any individual post.

Clearly there is more work to do to build a fully-featured RSS browser: we'd need to implement item caching, read/unread status, multiple feeds, better styling and much more. But to achieve just the basic feed reader shown here entirely using data binding is a great testament to the power of XAML.

Organizing Data Presentation

Developers want to be able to filter, group and sort data. Windows Presentation Foundation supports this with the use of a CollectionView object. You can have multiple views of the same collection simultaneously. You can use this over any data form, so long as it supports IEnumerable. You can also implement your own sorting, filtering and grouping algorithms by implementing ICollectionView.

In the resources section, add one of the following:

<CollectionViewSource x:Key="SortByName" Source={StaticResource Blog}"
<CollectionViewSource.Sort>
<scm:SortDescription PropertyName="@title" Direction="Ascending" />
</CollectionViewSource.Sort>
</CollectionViewSource>
 
<CollectionViewSource x:Key="GroupByDate" Source={StaticResource Blog}"
<CollectionViewSource.GroupBy>
<scm:PropertyGroupDescription PropertyName="@pubdate" StringComparison="OrdinalIgnoreCase" />
</CollectionViewSource.GroupBy>
</CollectionViewSource>

To use the sort, simply bind to the new key name rather than to the underlying data source.

For grouping, you need to specify a group style that should be used to show the group headers, as follows:

<ItemsControl ItemsContainerStyle="" ItemsSource="{Binding Source={StaticResource myItems}">
   <ItemsControl.GroupStyle>
      <GroupStyle HeaderTemplate="{StaticResource groupingHeaderTemplate}" />
   </ItemsControl.GroupStyle>
</ItemsControl>

Customizing Data Presentation

Finally, what if you don't want to show data as a list at all? What if you want to show your information as a graph, for instance? This is possible with Windows Presentation Foundation. The data binding support in Windows Presentation Foundation extends to all content controls. For example, Button, Window, ToolTip, and Label are all ContentControls. ListBox, ComboBox, TabControl all derive from ItemsControl.

Document Services

Along with Windows Presentation Foundation itself, the Windows Vista presentation technologies include two new specifications for handling the document and print lifecycle:

  • Open Packaging Conventions describes a series of file format packaging conventions and associated services that can be used by any application. The specification for Open Packaging Conventions is based on a ZIP file, over which there is a parts/relationships abstraction and then services that allow you to access the ZIP file.
  • The XML Paper Specification describes the markup and rendering rules for a fixed, paginated document that uses the Open Packaging Conventions. The XML Paper Specification also includes a specific fixed format implementation called XPS Document.

Open Packaging Conventions

There are three primary scenarios for the usage of Open Packaging Conventions:

  • Building custom file formats
  • Accessing XPS document and Office 12 content directly
  • Providing document solutions for XPS document, Office 12 or custom files.

You're encouraged to use Open Packaging Conventions for your own file format. If you do this, you can take advantage of the common services available.

The packaging model provides the foundation of a file format – it's described in the Open Packaging Convention Specification (currently at v0.75). Packages are usable by any application, and there are multiple implementations underway; amongst other things, Office 12 uses this specification for its new .docx, .xlsx and .pptx formats. You can access the contents of this file either using the packaging services (parts and relationships) or via any standard ZIP utility.

The file rels.relx is the master index for the files: here you can see links to other XML files containing metadata properties, the document itself, a thumbnail etc.

The Open Packaging Convention APIs reside in the System.IO.Packaging namespace (within the WindowsBase assembly). Here you can access classes such as Package, PackagePart, and PackagePartCollection. The APIs provide the ability to open and close packages, create and delete parts and relationships, get the name, content-type and stream for parts, read and write part streams, and get the ID, type and URI for relationships, as follows:

const string relType = "https://schemas.microsoft.com/xps/2005/06/fixedrepresentation";

Package p = Package.Open("c:\\package.container", FileMode.Open);            
PackageRelationshipCollection packRels = p.GetRelationshipsByType(relType);

foreach (PackageRelationship pr in packRels)
{
   Console.WriteLine(pr.RelationshipType);
   PackagePart part = p.GetPart(
      PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), pr.TargetUri));
   Console.WriteLine(part.ContentType + part.CompressionOption);
   // do something with part.GetStream() here.
}

There are three main services available for the header of packaged content. These may be used to share common notions of the document's authentication and content. They are as follows:

  • Core properties common metadata: there are a common set of properties, including:
    • Category
    • Content status
    • Content type
    • Creator
    • Date created
    • Date last modified
    • Description
    • Keywords
    • Last modified by
    • Title
  • Digital signatures provide a way of validating that the signed content hasn't been tampered with, supporting end-user needs for repudiation. This is available for all Open Packaging Convention formats. Certificates are compatible with XML Digital Signatures and follow the X.509 standard. The choice of which parts are signed is determined by the signing policy: for example, XPS Document Viewer policy is to sign all defined parts and relationships. Certificates can be in their own part or they can be embedded in the signature part in its own right. You can sign a document using the PackageDigitalSignatureManager class: the PackageDigitalSignature class represents the signature itself; you can also use this to verify the signature.
  • Rights management. The Open Packaging Conventions specification does not mandate a specific rights management solution. However, we do ship a default solution that can be used by any code targeting Windows Vista, which is Windows Rights Management Services. This API can be found in the System.Security.RightsManagement namespace, and can be used to apply rights management controls to data files that implement the package.

XML Paper Specification

The XPS Document format can be considered an example of a custom file format. A XPS document contains a number of parts, including:

  • FixedDocumentSequence (root)
  • FixedDocument (document markup)
  • FixedPage (page markup)
  • Font (embedded font)
  • Image (embedded image)
  • Thumbnail (page thumbnail images)
  • PrintTicket (printer settings)

Within an XPS Document, there are specific APIs that supersede the package APIs for document solutions. These include XpsDocument, IDocumentSequenceReader, and IFixedDocumentReader. These APIs allow you to manipulate your document: add or remove parts, retrieve or set core properties – they are friendlier than the base part APIs.

Lastly, XPS Documents may be extended through the use of markup compatibility. This is identical to XAML markup compatibility: you can set Ignorable, ProcessContent, AlternateContent, and MustUnderstand.

Application Model

Windows Presentation Foundation provides primitives to help you manage the logic flow within your application. When we look at existing application frameworks, many are somewhat restrictive. For example, MFC is great for building applications so long as your application fits the structure of MFC. If you go beyond the bounds, you can often find that MFC gets in your way. In some cases, infrastructure is missing for common user experience models (for example the navigation model popularized by Web browsers). Lastly, many platforms don't provide good metaphors for application-level management (for example, in Win32, you often wind up having to post messages to other windows; in the Web model, postback latency is a major issue without the use of ameliorating technologies such as AJAX).

Most applications need the following services:

  • Application-wide state (tracking variables across the lifetime of the app)
  • Interaction with the OS (for example, application shutdown)
  • Managing windows and resources
  • Storing files and user data
  • User interface model
  • Hosting and distribution

Conveniently, this list describes the areas of focus for the Windows Presentation Foundation application model.

General Application Services

Windows Presentation Foundation provides a series of opt-in services for data management, system interaction and UI model; there's infrastructure available, but it tries not to get in your face. Despite that, there are common services that most applications require (for example, resource management) that Windows Presentation Foundation can abstract away. Most importantly, it needs to be simple to build a basic app (does anyone remember the hundreds of lines of code necessary to build a standard Windows "hello world" app prior to application frameworks?)

The base class for any application is the <Application> element. This abstracts application lifetime (OnStartup, OnExit) and resource management, as well as providing a property bag for storing session data (somewhat akin to the one provided by ASP.NET). You can also subclass Application to provide extended functionality. Lastly, the Application class abstracts many WM_ messages from Win32 into managed events (for example, application activation or deactivation).

Application resources can be stored in four different places: embedded within the assembly, locally as files within the application directory, on the server from which the application was executed, or within another assembly. Use code such as the following to access resources:

Embedded in the assembly <Image Source="Mushroom.jpg" />
Locally in app directory <Image Source="Mushroom.jpg" />
On the application's server <Image Source="pack://siteoforigin:,,,/Images/Quiche.jpg" />
Within another assembly <Image Source="Food;Component/Egg.jpg" />

(Note that in the third fragment above, siteoforigin is a fixed keyword, rather than a placeholder for the server name.)

Another valuable service is application storage. Traditionally applications have often stored their data in the file system, and this remains an option with Windows Presentation Foundation. Applications also have the opportunity to store their data into an isolated storage area, which provides a quota-based model that is supported in partial trust scenarios. To do this, use the IsolatedDataFileStream object. Other choices include a .config file or the registry (for settings), or even cookies (for Web-based applications).

A third service provided by Windows Presentation Foundation supports multiple UX models: both the single document interface (SDI) and navigation-based interfaces. In a dialog-based SDI model, you use windows, dialogs and controls; features are often surfaced to users through menus. Navigation-based apps use Windows Presentation Foundation classes such as Page, Hyperlink and NavigationWindow to provide a model that more closely matches the Web metaphor. Note that Windows Presentation Foundation does not force an application to use just one model: it's pretty common to see applications that are fundamentally window-based, but use a page-based model for wizards or other "led" tasks. As an aside, Windows Presentation Framework doesn't natively support the MDI (multiple document interface) model; designers are encouraged to adopt a tabbed model (as per Visual Studio) or a multiple window model (as per Microsoft Word) instead.

While on the topic of navigation windows, one challenge within the application model is that hyperlinks on the Web really model the BASIC "GOTO" statement: they have no notion of the originating page built into them. With Windows Presentation Foundation, a solution to this problem is the PageFunction object, which more closely models the "GOSUB" statement. From XAML, you use the PageFunction object in place of a Page object; from the calling code, you can then create an instance of this page function, create an event handler for a return event and navigate to it. Once the user has finished with the called page, you simply call the OnReturn event, passing any parameters that you want to return.

Web-based Applications

Windows Presentation Foundation isn't just for window-based applications: we also support browser-based applications. Web browser applications (WBAs) run in a security sandbox—they are unable to call privileged services and thus require no security or installation prompts. They are not installed in the traditional sense—so they don't appear in the Start Menu or create files in the \Program Files directory. They are deployed via ClickOnce (part of the .NET Framework 2.0). Lastly, they are online-only applications, and are thus not suitable for "sometimes-connected" scenarios.

One advantage of having a single platform that offers both browser-hosted and standalone options is that the programming model for the two is the same. In comparison to Outlook, which exists as two completely separate code bases for rich client and Web (Outlook Web Access), this model offers clear advantages for applications that need to support a Web or thin client approach.

How do you create a WBA? You can either use the template included with Visual Studio 2005 or simply set three properties in your project file:

<HostInBrowser>True</HostInBrowser>
<Install>False</Install>
<TargetZone>Internet</TargetZone>

If you are converting an existing application, you must also remove code that is not suited for the sandbox—either with conditional checks (#if (WBA)...#else...#endif) or by using runtime checks of permission levels.

Writing High Performing Applications

Windows Presentation Foundation offers great power for writing rich applications, but at the same time, it's possible to introduce performance problems unless the application design takes account of the different characteristics of target machines.

Windows Presentation Foundation takes advantage of hardware rendering as appropriate. It uses Direct3D to provide accelerated rendering on DirectX 7 or above, with further optimization for graphics cards with DirectX 9 and Pixel Shader 2.0 hardware. For machines without these capabilities, Windows Presentation Foundation uses software rendering, a CPU-based, SSE and SSE2 optimized rasterizer. This is also used when Windows Presentation Foundation is unable to render something using the hardware pipeline, and guarantees that rendering output is available across all machine hardware configurations.

As a result, Windows Presentation Foundation has both hardware and software pipelines, both with difference performance characteristics. This could make application performance very difficult to predict, since there are two code paths. In practice, hardware is reliably faster; for a given application, it's simply a matter of setting a minimum requirement. Windows Presentation Foundation supports simple runtime hardware detection and allows you to dynamically tailor your application for the platform it's running on using resource dictionaries.

Use code like the following: 

// tier will be 0, 1 or 2 where 2 is full hardware and 0 is software
int wpfTier = System.Windows.Media.RenderCapability.Tier >> 16;
 
// in this example, simply switch between software and hardware rendering
if (wpfTier == 0)
Resources.MergedDictionaries.Add(softwareRenderingDictionary);
else
Resources.MergedDictionaries.Add(hardwareRenderingDictionary);

The high-order bit of Tier contains the tier number, and there's also a TierChanged event you can trap (for example, a fallback to a lower power management mode). 0x20000 is high-end hardware support; 0x10000 is basic hardware rendering; 0x00000 is software rendering. On a Tier 2 development machine, you can switch to a lower tier by using the Troubleshooting tab on the Display Properties control panel applet. 

Finding out the tier is easy, but authoring the appropriate content is harder. Use Tier 0 machines for static 2D content and simple 2D animations; Tier 1 machines can also do multiple animations, opacity and larger filled areas; Tier 2 is best for scenes with complex 3D content and radial gradients.

Debugging Performance Issues

Note that software rendering is used for certain operations even when the application is running on Tier 2 hardware. For example, setting TileMode=Tile will cause that element to be rendered through the software rasterizer.

Perforator is a new SDK tool that allows you to connect to a running Windows Presentation Foundation application to retrieve performance measurements. It also allows real time changes to Windows Presentation Foundation rendering to help diagnose performance issues. With Perforator, you connect to a running Windows Presentation Foundation process, and you can set it to tint all elements that have fallen back to software rendering to a specific color.  

Another tool is ETW. Tools such as tracelog, tracerpt and mofcomp can record and consume ETW events. The documentation exposes the events that we support.

Thirdly, you can run traditional profiling to understand the bottlenecks in an application. Enterprise Profiler Tool ships with Visual Studio 2005 and offers sampling and instrumentation modes.

Lastly, you can use CLRProfiler (an existing tool that has shipped for a while from the Microsoft Web site) to track managed heap allocation issues and the performance costs associated with them.

Performance Tips

Virtualization is a great way to improve performance of data-intensive applications. UI virtualization is available in Windows Presentation Foundation through the VirtualizingStackPanel control. This is up to 70 times faster than StackPanel for large numbers of items. You can do the same thing too—if you can avoid keeping all your objects in the tree all the time, you'll probably see a win.

Use resources in XAML and the resource dictionary in code to reuse common resources. This is especially important for controls that are reused many times. In addition, make sure that you freeze any object that is Freezable (like a brush or a pen) when they won't be changed. This shrinks them down in size (since Windows Presentation Foundation doesn't have to keep track of changed event handlers) and improves performance.

Interoperability and Migration

Most developers who see Windows Presentation Foundation will be concerned about the potential impact on their existing applications. Will they have to rewrite everything, or is there a better story? What about plug-ins and controls? Do they all have to be rewritten too?

The good news is that Windows Presentation Foundation provides good interoperability: you can use Windows Presentation Foundation inside existing code, or you can use existing code inside Windows Presentation Foundation. For the maximum richness, however, it's true that a 100% Windows Presentation Foundation experience is going to offer benefits that will be missing from a mixed approach, for example data binding, animation and layout services across all elements.

Airspace

Having one piece of content render on another piece of content can be problematic. For example, alpha-blended transparencies can't be built satisfactorily. The concept of airspace is "one pixel per technology". The airspaces don't need to be rectangular: we support HREGIONS, but we don't support layered windows (WS_EX_LAYERED) for all meaningful purposes.

Here are a few ideas of how you could take advantage of Windows Presentation Foundation in your application to offer incremental benefit without rewriting it all. Firstly, you could use it to provide a new look for your chrome (the menus, toolboxes, wizards, help systems etc.). Secondly, you could use it for your application canvas while keeping the chrome in Win32. Thirdly, if your application offers the opportunity to generate an output format such as HTML, you could support XAML in addition and integrate into the develop/design workspace. Lastly, you could wrap an existing control in Windows Presentation Foundation to expose it to a broader audience.

Migrating to /clr

The first steps to take an existing Win32 C++ application to Windows Presentation Foundation are to migrate the code to Visual C++ 2005, to get the benefits of seamless managed code integration. Other benefits of moving to Visual C++ include security (/gs), reliability, etc. You can probably expect to get compilation errors, as a result of increased ISO standard compliance and breaking changes in libraries and their headers. In addition, you might get a bunch of compilation warnings relating to security issues or 64-bit unfriendly code. This first step can be a little painful, but the end result is worth it.

Adding /clr works well, but the trick is knowing where to use it. The recommendation is to use this just on the relevant source files. Putting it in more places can slow compilation times, and cause more work than necessary. For example, C files need to be compiled as C++, with all the resulting source issues you might run into. Another issue that might be experienced involves assembly code in an included header file. There are also issues with having managed code in DllMain; check the Visual C++ documentation for more information on this topic.

Make sure you set the debugger mode to mixed, as if you just compile a DLL with the /clr switch, the wrong debugger may be selected (since Visual Studio checks based on the executable type).

Embedding Windows Presentation Foundation within a Win32 App

The secret to making this functional is to put Windows Presentation Foundation application logic inside a HWND. You create an HwndSource, which makes Windows Presentation Foundation look like a big HWND.

HwndSource source = new Source.RootVisual();

Firstly, you need to add CLR support by adding the /clr switch to compile. Secondly, you need to mark the WinMain with [System::STAThreadAttribute]. Next, you need to add references to: PresenationCore.dll, PresentationFramework.dll, System.dll, and UIAutomationTypes.dll. Now, we add namespaces for the managed code:

namespace ManagedCode
{
   using namespace System;
   using namespace System::Windows;
   using namespace System::Windows::Interop;
   using namespace System::Windows::Media;
}

Now we need to create a new HwndSource. Use code like the following:

HwndSource^ source= gcnew HwndSource(...);
UIElement^ page = gcnew AvClock::Clock();
source->RootVisual = page;
return (HWND) source->Handle.ToPointer();

Challenges

Here are a few challenges you may want to consider before adopting this route:

  • Compared to rewriting the application natively for Windows Presentation Foundation, there's a higher long-term cost in return for a lower initial cost. You'll have to deal with interoperability issues (such as airspace) wherever you cross the boundary between Win32 and Windows Presentation Foundation.
  • Partial trust isn't available for a mixed-mode app, so you can't embed legacy code in a Web-Browser Application. If you plan to use this model, you should write your code as a native Windows Presentation Foundation application.
  • You can't have XAML and C++ in the same assembly. It's possible to put them in separate assemblies and load the XAML from the Win32 C++ host.
  • You may need to run your application across a mix of machines, some of which have WinFX installed and others of which have just Win32. You can check for WinFX with the following code in the current release:
if (Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\WAP" != null)
 // WinFX Runtime Components are installed

Conclusion

Windows Presentation Foundation is a powerful addition to the application developer or designer's toolbox. As the strategic presentation foundation for future releases of Windows, it provides a model which takes full advantage of the underlying graphical hardware and offers support for everything from standalone applications to Web browser-based applications to documents. Application developers who want to build rich immersive application user experiences or who are reaching the limits of the Web model will get particular benefit from early adoption of Windows Presentation Foundation.

Useful Resources

Authoring Tools

Blogs on Windows Presentation Foundation