By now you should have heard of several new acronyms that are usually associated with Windows Vista (codenamed Longhorn).

These acronyms include WinFX, WinFS, WCF (Windows Communication Foundation; codenamed Indigo), and WPF (Windows Presentation Foundation; codenamed Avalon). In recent months there has been a lot of buzz going around WPF, which is one of the core components of WinFX. In this article, I will take you on a whirlwind tour of what WPF is and how you can start preparing for Vista by developing applications today using the available SDK.

Why Windows Presentation Foundation?

Windows Presentation Foundation (WPF) is the new graphics subsystem in Windows Vista that will enable developers to build applications that provide breakthrough user experiences. If you look at the applications in use today, they are either Windows applications or Web applications. While Windows applications offer immensely rich client functionality, deploying Windows applications requires considerable resources and makes maintenance a constant challenge. On the other hand, Web applications offers ease of deployment and maintenance, but do so at the expense of increased complexity in the development process (since the Web is stateless) as well as less-than-ideal platform integration.

It is the goal of WPF to offer a development platform that offers the best of both worlds, allowing administrators to deploy and manage applications securely.

Microsoft's goal when they created WPF was to offer a development platform that offers the best of both worlds, allowing administrators to deploy and manage applications securely.

While application development technologies have evolved rapidly, hardware advances have also been moving at a rapid rate. In particular, the processing power of video cards has been improving at a much more rapid rate than developers can make use of. Increasingly, computers are equipped with an over-powered graphics subsystem that is under utilized. Applications could jolly well take advantage of the power of these graphics cards (such as for three-dimensional (3-D) processing) to enhance the user experience.

And this is exactly the aim of WPF-that is, to take advantage of the under-utilized power of the video card and use it to enhance the user experience of Windows applications. WPF uses Direct3D for vector-based rendering, enabling applications to incorporate a wide assortment of media such as 2-D, 3-D, audio, text, video, animation, etc.

Building User Interfaces Using XAML

In WPF, Microsoft introduces a new language for creating WPF applications-XAML (Extensible Application Markup Language). Using XAML, developers can create UIs declaratively using XML elements and attributes. This provides for a clean separation of application logic and the UI of the application, allowing interface designers to use external tools (more on this later) to design the UI and then wire up with the code-behinds using .NET languages.

XAMLPad

To get developers started with XAML, Microsoft provides a useful tool known as XAMLPad. XAMLPad is a XAML editor that allows you to quickly preview your UI. To use XAMLPad, go to Start, choose Programs, choose Microsoft Windows SDK, then choose Tools, and finally choose XAMLPad. Figure 1 shows the various components in XAMLPad.

Figure 1: The various components in XAMLPad.
Figure 1: The various components in XAMLPad.

XAMLPad offers the following functions:

To see the XAMLPad in action, let's populate the Edit Pane with some XAML code (see Listing 1). Figure 2 shows the resulting UI. Notice that the XAML code looks like HTML as all UI controls are defined declaratively.

Figure 2: Using XAMLPad to preview XAML code.
Figure 2: Using XAMLPad to preview XAML code.

XAML supports a few layout patterns for UI controls, and the one just shown uses the Canvas layout. The Canvas layout pattern is similar to what you have today in Windows Forms. The controls in a Canvas layout are positioned using the x and y-coorindates. The Canvas layout is useful in cases where you need to precisely position the various controls on the UI.

You may have noticed that in the Canvas element there is a LayoutTransform attribute. This attribute allows you to scale the output by simply specifying the scale factor. For example, if you specify a factor of 0.5 (LayoutTransform=“scale 0.5”), then the entire Canvas layout would shrink by 50% (see Figure 3).

Figure 3: Using LayoutTransform to shrink the output.
Figure 3: Using LayoutTransform to shrink the output.

Layouts

Besides the Canvas layout, there are a couple of other layouts available in XAML. They are:

  • StackPanel
  • DockPanel
  • Grid

I'll now describe the various layouts.

StackPanel

A StackPanel layout positions controls like they are on a stack. You can stack controls vertically or horizontally. The XAML code in Listing 2 shows how the StackPanel works. Figure 4 shows the output of the XAML code above.

Figure 4: Using the StackPanel layout.
Figure 4: Using the StackPanel layout.

DockPanel

A DockPanel layout docks controls on either one of the four sides (Top, Left, Right, or Bottom) of a DockPanel control. The XAML code in Listing 3 shows how to dock four Button controls using the DockPanel.Dock attribute. Figure 5 shows the output for the above code.

Figure 5: Using the DockPanel layout.
Figure 5: Using the DockPanel layout.

Grid

The Grid layout allows controls to be positioned in cells, just like in a grid. The XAML code in Listing 4 shows how to define a grid with three columns and four rows, and then add twelve Button controls to each cell within the grid. Figure 6 shows the output for the XAML code shown above.

Figure 6: Using Grid layout.
Figure 6: Using Grid layout.

Building WPF Applications Using Visual Studio 2005

While Windows Vista is slated to be released by the end of 2006, you can start developing WPF applications today using Visual Studio 2005.

Project Types

Once you have installed all the prerequisites for WPF, you can develop WPF applications using Visual Studio 2005. To develop WPF applications, from the File menu choose New and then choose Project**….** Under the Avalon project type, you should see the three Visual Studio installed templates-Avalon Application, Avalon Web Browser Application, and Avalon Control Library (Figure 7).

Figure 7: The three Avalon application templates.
Figure 7: The three Avalon application templates.

The Avalon Application template is similar to the standalone Windows application that you are familiar with today.

The aim of WPF is to take advantage of the under-utilized power of the video card and use it to enhance the user experience of Windows applications.

For the Avalon Web Browser application, it is hosted within a Web browser and looks like that shown in Figure 8. This type of Avalon application is well-suited for scenarios where you would want to refrain from deploying additional components to the client. As such, it runs within the context of a partial trust sandbox. As shown in Figure 8, an Avalon Web Browser application lives within the browser and uses pages instead of windows for navigation (as evident by the two navigation buttons at the top of the window).

Figure 8: An Avalon Web browser application.
Figure 8: An Avalon Web browser application.

You can use the Avalon Control Library to create user controls that can be used by other Avalon applications.

Programmatically Generating the WPF UI

Earlier on, I showed how to use XAML to create the UI of a WPF application. It is important to know that XAML is not the only means to create WPF applications. In fact, at compile-time, all the XAML elements are compiled into a partial class (a new language feature in .NET 2.0, for both C# and Visual Basic 2005) and combined with the partial classes containing the application logic. Thus, instead of declaratively creating the UI of a WPF application using XAML, you can also programmatically create it using code.

I'll now show you how to write a WPF UI using code. Create a new Avalon Windows application and in the code-behind of the default Window1.xaml (Window1.xaml.vb), add the event handler shown in Listing 5.

When you compile and execute the application, your output will look like Figure 9.

Figure 9: No visual designer for WPF in Visual Studio 2005.
Figure 9: No visual designer for WPF in Visual Studio 2005.

2D Graphics

As mentioned in the beginning of this article, graphics is one of the strengths of WPF. The code example in Listing 6 shows how you can draw 2-D graphics using one of the many graphics elements available in WPF.

In the above code, three rectangles are drawn using the Rectangle element. Each rectangle is filled with a color and bound to a Slider control. When each slider moves, the height of the corresponding rectangle changes and the value of the slider is displayed next to it (see Figure 10).

Figure 10: 2-D drawings.
Figure 10: 2-D drawings.

Besides filling a rectangle with a solid color, you can also fill it with shades using a brush. For example, the code shown in Listing 7 fills the first rectangle with the colors Lavender and Blue using the VerticalGradient fill method. The second rectangle is filled with the colors Lavender and Yellow using the HorizontalGradient fill method. The third rectangle allows you to specify the various offsets to be used for the gradient fill.

Figure 11 shows the effect of the various gradients fills.

Figure 11: Applying gradient fills to the rectangles.
Figure 11: Applying gradient fills to the rectangles.

3-D Graphics

3-D graphics is the main highlight of WPF. While it is possible to create 3-D graphics by hand using XAML, it is too mundane a task to do. Instead, Microsoft is readying a new set of tools that will greatly simplify the task of creating XAML content.

Microsoft Expression Interactive Designer (codenamed Sparkle), a member of the Microsoft Expression family of professional design tools, allows application developers to create exciting user interface designs using a full spectrum of media types, including vectors, pixel images, 3-D content, video and audio, high quality text, and animation (see Figure 12).

Figure 12: Microsoft Expression Interactive Designer.
Figure 12: Microsoft Expression Interactive Designer.

As I'm writing this article, Microsoft Expression Interactive Designer (http://www.microsoft.com/products/expression/en/interactive_designer/default.aspx) is not yet available for download. However, there are third-party tools that can help you create exciting UI designs.

Electric Rain's ZAM 3D

Electric Rain ZAM 3D (http://www.erain.com/products/ZAM3D/DefaultPDC.asp) is a full-featured 3-D modeling application that enables easy creation, customization, and animation of 3-D interface elements for WPF applications. You can use ZAM 3-D to export 3-D graphics into XAML code. You can then directly integrate the XAML files created with ZAM 3-D into your application development environment to create rich and engaging user experiences.

Figure 13 shows a 3-D model rendered using ZAM 3D. To export the graphics as XAML, go to the File menu, choose Export… and save the XAML code to a text file.

Figure 13: 3-D designing in ZAM 3D.
Figure 13: 3-D designing in ZAM 3D.

When you double-click on the saved XAML file, it will be loaded in IE as a WPF application (Figure 14).

Figure 14: The saved XAML code loaded as a WPF application.
Figure 14: The saved XAML code loaded as a WPF application.

MobiForm's Aurora XAML Designer for WinFX

Aurora (http://www.mobiform.com/Eng/aurora.html) is another visual designer that produces XAML documents from the Microsoft Windows Presentation Foundation Object Model.

You can either use Aurora as a standalone application (Figure 15) to design your UI, or you can use Aurora within Visual Studio 2005 (Figure 16).

Figure 15: Using Aurora for WPF UI design.
Figure 15: Using Aurora for WPF UI design.
Figure 16: Aurora's integration with Visual Studio 2005.
Figure 16: Aurora's integration with Visual Studio 2005.

To use Aurora within Visual Studio 2005, right-click on a form (such as Window1.xaml), select the Open with… item and select Aurora.

Imaging

Besides 2-D and 3-D graphics, WPF also comes with extensive support for imaging. For example, the code in Listing 8 shows how to clip an image using a geometry control (see Figure 17).

Figure 17: Clipping an image.
Figure 17: Clipping an image.

Data-Binding

Any decent application worth its salt would make use of data. And in WPF, you can bind UI elements to a wide variety of data sources, including XML data, Web services, and of course, databases.

To demonstrate data-binding in WPF, I have built a simple RSS reader. Listing 9 shows my XML Data Provider defined to point to an online resource (an RSS document). It is then bound to a ListBox control that displays a list of titles contained within the RSS document, as well as a TextBox control that displays the description of the news item.

When the items in the ListBox are selected, the TitleChanged event will be fired. This event will then set the DataContext property of the StackPanel so that the description for the selected news title will be displayed in the TextBox control.

Private Sub TitleChanged( _
   ByVal sender As Object, _
   ByVal args As _
   SelectionChangedEventArgs)
    Dim lstbox As ListBox = sender

If lstbox.SelectedItem IsNot _
  Nothing Then
        spDetails.DataContext = _
           lstbox.SelectedItem
    End If

End Sub

Figure 18 shows what happens when the application is executed.

Figure 18: Running the RSS reader application.
Figure 18: Running the RSS reader application.

Summary

In this article, you have seen some of the features of WPF, the new graphics subsystem in Windows Vista. There is a lot more to WPF than I could possibly cover in just one article. Hopefully you now have a better idea of what WPF can offer. I will cover some other features of WPF in a future article.

Listing 1: Sample XAML code

<Canvas 
 xmlns="<a href="http://schemas.microsoft.com/winfx/avalon/2005";>http://schemas.microsoft.com/winfx/avalon/2005<;/a>" 
 Background="Ivory" LayoutTransform="scale 1">
   <Label 
      Canvas.Top="10" Canvas.Left="10" 
      BorderBrush="Crimson" BorderThickness="1">
      Image Source
   </Label>

   <TextBox Canvas.Top="40" Canvas.Left="10" >
   </TextBox>

   <Button Canvas.Top="40" Canvas.Left="120" 
      Height="25">OK</Button>
   <Image Width="400" Canvas.Top="75" 
      Canvas.Left="10" >
      <Image.Source>
         <BitmapImage UriSource="C:\Sunset.jpg" />
      </Image.Source>
   </Image>
</Canvas>

Listing 2: The StackPanel control

<StackPanel 
 xmlns="<a href="http://schemas.microsoft.com/winfx/avalon/2005";>http://schemas.microsoft.com/winfx/avalon/2005<;/a>" 
 Background="Ivory" LayoutTransform="scale 1"
 Orientation="Vertical" >

   <StackPanel Orientation="Horizontal"  
      VerticalAlignment="Top">
      <Label Margin="10,5,5,5" Height="30" 
         BorderBrush="Crimson" BorderThickness="1">
         Image Source</Label>
      <TextBox Margin="5,5,5,5" Height="30"></TextBox>
      <Button Margin="5,5,5,5" Height="30">OK</Button>
   </StackPanel>

   <StackPanel Orientation="Horizontal"  
      VerticalAlignment="Top">
      <Image Margin="10,5,10,5" 
         VerticalAlignment="Bottom" Width="400" >
         <Image.Source>
            <BitmapImage UriSource="C:\Sunset.jpg" />
         </Image.Source>
      </Image>
   </StackPanel>

</StackPanel>

Listing 3: The DockPanel control

<DockPanel 
 xmlns="<a href="http://schemas.microsoft.com/winfx/avalon/2005";>http://schemas.microsoft.com/winfx/avalon/2005<;/a>" 
   Background="Ivory" LayoutTransform="scale 1" >
   <Button Margin="5,5,5,5" Height="30" Width="80" 
      DockPanel.Dock="Left">Left</Button>
   <Button Margin="5,5,5,5" Height="30" Width="80"
      DockPanel.Dock="Right">Right</Button>
   <Button Margin="5,5,5,5" Height="30" Width="80" 
      DockPanel.Dock="Top">Top</Button>
   <Button Margin="5,5,5,5" Height="30" Width="80" 
      DockPanel.Dock="Bottom">Bottom</Button>

   <Image Margin="10,5,10,5" Width="400" >
      <Image.Source>
         <BitmapImage UriSource="C:\Sunset.jpg" />
      </Image.Source>
   </Image>

</DockPanel>

Listing 4: The Grid control

<Grid 
 xmlns="<a href="http://schemas.microsoft.com/winfx/avalon/2005";>http://schemas.microsoft.com/winfx/avalon/2005<;/a>" 
 Background="Ivory" LayoutTransform="scale 1" 
 ShowGridLines="True" >

      <ColumnDefinition Width="40" />
      <ColumnDefinition Width="40" />
      <ColumnDefinition Width="40" />
      <RowDefinition Height="40" />
      <RowDefinition Height="40" />
      <RowDefinition Height="40" />
      <RowDefinition Height="40" />

      <Button Grid.Column="0" Width="30" 
         Margin="5,5,5,5">1</Button>
      <Button Grid.Column="1" Width="30" 
         Margin="5,5,5,5">2</Button>
      <Button Grid.Column="2" Width="30" 
         Margin="5,5,5,5">3</Button>

      <Button Grid.Column="0" Grid.Row="1" Width="30"
         Margin="5,5,5,5">4</Button>
      <Button Grid.Column="1" Grid.Row="1" Width="30" 
         Margin="5,5,5,5">5</Button>
      <Button Grid.Column="2" Grid.Row="1" Width="30" 
         Margin="5,5,5,5">6</Button>
      <Button Grid.Column="0" Grid.Row="2" Width="30" 
         Margin="5,5,5,5">7</Button>
      <Button Grid.Column="1" Grid.Row="2" Width="30" 
         Margin="5,5,5,5">8</Button>
      <Button Grid.Column="2" Grid.Row="2" Width="30" 
         Margin="5,5,5,5">9</Button>
      <Button Grid.Column="0" Grid.Row="3" Width="30" 
         Margin="5,5,5,5">*</Button>
      <Button Grid.Column="1" Grid.Row="3" Width="30"
         Margin="5,5,5,5">0</Button>
      <Button Grid.Column="2" Grid.Row="3" Width="30" 
         Margin="5,5,5,5">#</Button>
</Grid>

Listing 5: An Avalon application using code

Private Sub OnLoaded( _
   ByVal sender As Object, _
   ByVal e As RoutedEventArgs) Handles Me.Loaded

    Dim dp As New DockPanel
    With dp
        .Background = Brushes.Ivory
        .LayoutTransform = New ScaleTransform(1, 1)
    End With
        
    Dim btn1, btn2, btn3, btn4 As New Button

    With btn1
        .Margin = New Thickness(5)
        .Height = 30
        .Width = 80
        .Content = "Left"
    End With

    With btn2
        .Margin = New Thickness(5)
        .Height = 30
        .Width = 80
        .Content = "Right"
    End With

    With btn3
        .Margin = New Thickness(5)
        .Height = 30
        .Width = 80
        .Content = "Top"
    End With

    With btn4
        .Margin = New Thickness(5)
        .Height = 30
        .Width = 80
        .Content = "Bottom"
    End With

    Dim img As New Image

    Dim BI As Imaging.BitmapImage = _
       New Imaging.BitmapImage()
    BI.BeginInit()
    BI.UriSource = New Uri("C:\Sunset.jpg")
    BI.EndInit()
    img.Source = BI

    DockPanel.SetDock(btn1, Dock.Left)
    DockPanel.SetDock(btn2, Dock.Right)
    DockPanel.SetDock(btn3, Dock.Top)
    DockPanel.SetDock(btn4, Dock.Bottom)

    dp.Children.Add(btn1)
    dp.Children.Add(btn2)
    dp.Children.Add(btn3)
    dp.Children.Add(btn4)
    dp.Children.Add(img)

    Me.Content = dp

End Sub

Listing 6: Drawing 2-D graphics

<Canvas
 xmlns="<a href="http://schemas.microsoft.com/winfx/avalon/2005";>http://schemas.microsoft.com/winfx/avalon/2005<;/a>"
 Background="Ivory" LayoutTransform="scale 1">
   <StackPanel Orientation="Vertical" >

      <StackPanel Orientation="Horizontal" >
         <Slider Margin="5,5,5,5" Name="slider1" 
            DockPanel.Dock="Top" Maximum="100" 
            Minimum="1" />
         <Label Content="{Binding ElementName=slider1,
            Path=Value}"></Label>
      </StackPanel>

      <StackPanel Orientation="Horizontal" >
         <Slider Margin="5,5,5,5" Name="slider2" 
            DockPanel.Dock="Top" Maximum="100" 
            Minimum="1" />
         <Label Content="{Binding ElementName=slider2,
            Path=Value}"></Label>
      </StackPanel>

      <StackPanel Orientation="Horizontal" >
         <Slider Margin="5,5,5,5" Name="slider3" 
            DockPanel.Dock="Top" Maximum="100" 
            Minimum="1" />
         <Label Content="{Binding ElementName=slider3,
            Path=Value}"></Label>
      </StackPanel>

   </StackPanel>

   <Rectangle
      Width="50"
      Height="{Binding ElementName=slider1, 
               Path=Value}"
      Fill="Blue"
      Canvas.Left="10"
      Canvas.Bottom="325" />

   <Rectangle
      Width="50"
      Height="{Binding ElementName=slider2, 
               Path=Value}"
      Fill="Yellow"
      Canvas.Left="60"
      Canvas.Bottom="325" />

   <Rectangle
      Width="50"
      Height="{Binding ElementName=slider3, 
               Path=Value}"
      Fill="Red"
      Canvas.Left="110"
      Canvas.Bottom="325" />
</Canvas>

Listing 7: Using shadings in Avalon

<Rectangle
   Width="50"
   Height="{Binding ElementName=slider1, Path=Value}"
   Fill="VerticalGradient Lavender Blue"
   Canvas.Left="10"
   Canvas.Bottom="325" />

<Rectangle
   Width="50"
   Height="{Binding ElementName=slider2, Path=Value}"
   Fill="HorizontalGradient Lavender yellow"
   Canvas.Left="60"
   Canvas.Bottom="325" />

<Rectangle
   Width="50"
   Height="{Binding ElementName=slider3, Path=Value}"
   Canvas.Left="110"
   Canvas.Bottom="325" >
      <Rectangle.Fill>
         <LinearGradientBrush>
            <LinearGradientBrush.GradientStops>
               <GradientStop Offset="0" Color="red"/>
               <GradientStop Offset="1" Color="green"/>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
      </Rectangle.Fill>
</Rectangle>

Listing 8: Imaging in Avalon

<Canvas
 xmlns="<a href="http://schemas.microsoft.com/winfx/avalon/2005";>http://schemas.microsoft.com/winfx/avalon/2005<;/a>" 
 xmlns:x="<a href="http://schemas.microsoft.com/winfx/xaml/2005";>http://schemas.microsoft.com/winfx/xaml/2005<;/a>"
 Background="Ivory" LayoutTransform="scale 1">

   <Image Width="400" Canvas.Top="75" 
      Canvas.Left="10" >
      <Image.Source>
         <BitmapImage UriSource="C:\Sunset.jpg" />
      </Image.Source>

      <Image.Clip>
         <EllipseGeometry RadiusX="200" RadiusY="100" 
             Center="200,200" />
      </Image.Clip>
   </Image>
</Canvas>

Listing 9: Data-binding in Avalon

<Window x:Class="Window1"
 xmlns="<a href="http://schemas.microsoft.com/winfx/avalon/2005";>http://schemas.microsoft.com/winfx/avalon/2005<;/a>"
 xmlns:x="<a href="http://schemas.microsoft.com/winfx/xaml/2005";>http://schemas.microsoft.com/winfx/xaml/2005<;/a>"
 Title="DataBinding in WPF">

   <DockPanel>
      <DockPanel.Resources>
         <XmlDataProvider
            x:Key="XMLData" 
            Source="http://www.code-
            magazine.com/CodeRSS.aspx" 
            XPath="/rss/channel" />

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

   <StackPanel Background="Khaki" 
      Name="spDetails"
      Width="500">

   <TextBlock DockPanel.Dock="Left" 
      FontSize="14" 
      FontWeight="Bold" Margin="10" >
      Titles
   </TextBlock>

   <ListBox 
      Margin="10,0,10,10" 
      Foreground="Black"
      ItemsSource="{Binding Source={StaticResource
                    XMLData}, 
         XPath=item}"
      ItemTemplate="{StaticResource DATATemplate}" 
      SelectionChanged="TitleChanged"
      MaxHeight="100"/>

   <TextBlock DockPanel.Dock="Left" 
      FontSize="14" 
      FontWeight="Bold" Margin="10" >
      Description
   </TextBlock>

   <TextBlock Name="txtDescription"  
      Height="100"
      TextWrapping="WrapWithOverflow" 
      Margin="10,0,10,10" 
      Background="Black" 
      Foreground="LightGreen"  
      TextAlignment="Justify"   
      Text="{Binding XPath=description}" />

   <Label Name="lblURL"
      Content="{Binding XPath=link}" 
      Margin="10,0,10,10"
      FontStyle="Oblique" 
      Foreground="Blue" />

   </StackPanel>
   </DockPanel>
</Window>