BUY THIS BOOK
Add to Cart

Print Book $49.99


Add to Cart

PDF $39.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £30.99

What is this?

Looking to Reprint or License this content?


Programming WPF
Programming WPF, Second Edition Building Windows UI with Windows Presentation Foundation

By Chris Sells, Ian Griffiths
Book Price: $49.99 USD
£30.99 GBP
PDF Price: $39.99

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Hello, WPF
WPF is a completely new presentation framework, integrating the capabilities of many frameworks that have come before it, including User, GDI, GDI+, and HTML, as well as being heavily influenced by toolkits targeted at the Web, such as Adobe Flash, and popular Windows applications like Microsoft Word. This chapter will give you the basics of WPF from scratch, and then a whirlwind tour of the things you'll read about in detail in the chapters that follow.
is pretty much the smallest WPF "application" you can write in C#.
Example . Minimal C# WPF application
// MyApp.cs
using System;
using System.Windows; // the root WPF namespace
namespace MyFirstWpfApp {
  class MyApp {
    [STAThread]
    static void Main(  ) {
     // the WPF message box
     MessageBox.Show("Hello, WPF");
    }
  }
}
The STAThread attribute signals .NET to make sure that when COM is initialized on the application's main thread, it's initialized to be compatible with single-threaded UI work, as required by WPF applications.
In fact, this is such a lame WPF application that it doesn't even use any of the services of WPF; the call to MessageBox.Show is just an interop call to Win32. However, it does require the same infrastructure required of other WPF applications, so it serves as a useful starting point for our explorations.
Building this application () is a matter of firing off the C# compiler from a command shell with the appropriate environment variables. (The command line here has been spread across multiple lines for readability, but you need to put it all on one line.)
Example . Building a WPF application manually
C:\1st> csc /target:winexe /out:.\1st.exe
  /r:System.dll
  /r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll"
  /r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\
PresentationCore.dll"
  /r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\
PresentationFramework.dll"
  MyApp.cs

Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.312
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
WPF from Scratch
is pretty much the smallest WPF "application" you can write in C#.
Example . Minimal C# WPF application
// MyApp.cs
using System;
using System.Windows; // the root WPF namespace
namespace MyFirstWpfApp {
  class MyApp {
    [STAThread]
    static void Main(  ) {
     // the WPF message box
     MessageBox.Show("Hello, WPF");
    }
  }
}
The STAThread attribute signals .NET to make sure that when COM is initialized on the application's main thread, it's initialized to be compatible with single-threaded UI work, as required by WPF applications.
In fact, this is such a lame WPF application that it doesn't even use any of the services of WPF; the call to MessageBox.Show is just an interop call to Win32. However, it does require the same infrastructure required of other WPF applications, so it serves as a useful starting point for our explorations.
Building this application () is a matter of firing off the C# compiler from a command shell with the appropriate environment variables. (The command line here has been spread across multiple lines for readability, but you need to put it all on one line.)
Example . Building a WPF application manually
C:\1st> csc /target:winexe /out:.\1st.exe
  /r:System.dll
  /r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll"
  /r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\
PresentationCore.dll"
  /r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\
PresentationFramework.dll"
  MyApp.cs

Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.312
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
Here, we're telling the C# compiler that we'd like to create a Windows application (instead of a Console application, which we get by default), putting the result, 1st.exe, into the current folder, referencing the three main WPF assemblies (WindowsBase, PresentationCore, and PresentationFramework), along with the core .NET System assembly, and compiling the MyApp.cs source file.
Running the resulting
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
XAML Browser Applications (XBAPs)
While we're talking about Visual Studio tools for WPF, you may notice that a few icons away from the "Windows Application (WPF)" project template is another one called "XAML Browser Application (WPF)," as shown in .
Figure : The WPF XAML Browser Application project template in VS05
WPF itself was created as a unified presentation framework, meant to enable building Windows applications with the best features from existing Windows application practice and existing web application practice. One of the nice things that web applications provide is a single window showing the user one page of content/functionality at a time, allowing for navigation among the pages. For some applications, including Internet Explorer, the shell Explorer, Microsoft Money, and a bunch of Control Panel applets, this is thought to be preferable to the more common Windows application practice of showing more than one window at a time.
To enable more of these kinds of applications, WPF provides the page, which is the unit of navigation in an XML Browser Application (XBAP). Instead of setting an application's StartupUri to a XAML file that defines a window, we point an XBAP's StartupUri at a XAML file that defines a page ().
Example . Starting with a Page instead of a Window
<!-- App.xaml -->
<Application
  x:Class="MyFirstXbapApp.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  StartupUri="Page1.xaml" />
A WPF page is a class that derives from the Page class, as shown in .
Example . A sample page
<!-- Page1.xaml -->
<Page
  x:Class="MyFirstXbapApp.Page1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowTitle="Page1">
  <TextBlock FontSize="36">
    Check out <Hyperlink NavigateUri="page2.xaml">page 2</Hyperlink>, too.
  </TextBlock>
</Page>

    // Page1.xaml.cs
    ...
    namespace MyFirstXbapApp {
      public partial class Page1 : System.Windows.Controls.Page {
        public Page1(  ) {
          InitializeComponent(  );
        }
      }
    }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Content Models
Although the different kinds of WPF application types are useful, the core of any presentation framework is in the presentation elements themselves. In presentation systems of old, fundamentally we had "chunks of look and behavior" (often called controls) and "containers of chunks of look and behavior." In WPF, this characterization doesn't really hold up very well. Many elements that provide their own content and behavior can also be containers of elements (and so on). As an example, let's take a look at a Button.
The first thing that may surprise you about a WPF Button object is that you don't need to use a string as the content; it will take any .NET object. You've already seen a string as a button's content (see ).
Example . A button with string content
<Window ...>
  <Button Width="100" Height="100">Hi</Button>
</Window>
However, as shows, you can also use an image (see ).
Example . A button with image content
<Window ...>
  <Button Width="100" Height="100">
        <Image Source="tom.png" />
  </Button>
</Window>
Figure : A button with image content
You can even use an arbitrary control, like a TextBox, as shown in and .
Example . A button with control content
<Window ...>
  <Button Width="100" Height="100">
        <TextBox Width="75">edit me</TextBox>
  </Button>
</Window>
Figure : A button with control content
Further, as you'll see in and , you can get fancy and show a collection of nested elements in a Button or even nonvisual objects as the content of a Button. The Button can take any object as content because it's derived ultimately from a class called ContentControl, as are many other WPF classes (e.g., Label, ListBoxItem, ToolTip, CheckBox, RadioButton, and, in fact, Window itself).
A ContentControl knows how to hold anything that's able to be rendered, not just a string. A ContentControl gets its content from the Content property, so you could specify a Button's content like so (this is the longhand version of ):
<Button Width="100" Height="100" Content="Hi" />
ContentControls are especially useful because you get all the behavior of the "thing" (e.g.,
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Layout
Taking another look at with the TextBlock and the Image as content for the Button, we don't really have enough information to place them inside the area of the button. Should they be stacked left to right or top to bottom? Should one be docked on one edge and one docked to the other? How will things be stretched or arranged if the button resizes? These are questions best answered with a panel.
A panel is a control that knows how to arrange its content. WPF comes with the following general-purpose panel controls:
Canvas
Arranges content by position and size with no automatic rearrangement when the Canvas is resized
DockPanel
Arranges content according to the edge that each piece of content "docks" to, except for the last, which fills the remaining area
Grid
Arranges content in rows and columns as specified by the developer
StackPanel
Arranges content top to bottom or left to right according to the orientation of the panel
UniformGrid
Arranges content in a grid with the same number of rows and columns generated as needed to display the content
WrapPanel
Arranges things in a horizontal row until the next item won't fit, in which case it wraps to the next row
The most flexible panel by far is the grid, which arranges content elements in rows and columns, including the ability to span multiple rows and/or multiple columns, as shown in .
Example . A sample usage of the Grid panel
<Window ...>
    <Grid>
     <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition />
      <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Button Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">A</Button>
    <Button Grid.Row="0" Grid.Column="2">C</Button>
    <Button Grid.Row="1" Grid.Column="0" Grid.RowSpan="2">D</Button>
    <Button Grid.Row="1" Grid.Column="1">E</Button>
    <Button Grid.Row="1" Grid.Column="2">F</Button>
    <Button Grid.Row="2" Grid.Column="1">H</Button>
    <Button Grid.Row="2" Grid.Column="2">I</Button>
   </Grid>
</Window>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Controls
Although the layout panels provide the container, the controls are the important things you'll be arranging. So far, you've seen how to create instances of controls, set properties, and handle events. You've also seen the basics of the content models that make controls in WPF special. However, for the details of event routing, command handling, mouse/keyboard input, and an enumeration of the controls in WPF, you'll want to check out and . Further, for information about packaging up custom UI and behavior, you'll want to read .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Data Binding
Once we've got a set of controls and a way to lay them out, we still need to fill them with data and keep that data in sync with wherever the data actually lives. (Controls are a great way to show data but a poor place to keep it.) For example, imagine that we'd like to build a WPF application for keeping track of people's nicknames. Something like would do the trick.
Figure : Data binding to a collection of custom types
In , we've got two TextBox controls, one for the name and one for the nickname. We've also got the actual nickname entries in a ListBox in the middle and a Button to add new entries. We could easily build the core data of such an application with a class, as shown in .
Example . A custom type with data binding support
public class Nickname : INotifyPropertyChanged {
    // INotifyPropertyChanged Member
    public event PropertyChangedEventHandler PropertyChanged;
    void Notify(string propName) {
      if( PropertyChanged != null ) {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
  }

  string name;
  public string Name {
    get { return name; }
    set {
      name = value;
      Notify("Name"); // notify consumers
    }
  }

  string nick;
  public string Nick {
    get { return nick; }
    set {
      nick = value;
      Notify("Nick"); // notify consumers
    }
  }

  public Nickname(  ) : this("name", "nick") { }
  public Nickname(string name, string nick) {
    this.name = name;
    this.nick = nick;
  }
}
This class knows nothing about data binding, but it does have two public properties that expose the data, and it implements the standard INotifyPropertyChanged interface to let consumers of this data know when it has changed.
In the same way that we have a standard interface for notifying consumers of objects when they change, we also have a standard way to notify consumers of collections of changes, called INotifyCollectionChanged. WPF provides an implementation of this interface, called ObservableCollection, which we'll use so that appropriate events are fired when Nickname objects are added or removed ().
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Dependency Properties
Although our data source Nickname object made its data available via standard .NET properties, we need something special to support data binding on the target element. Even though the TextContent property of the TextBlock element is exposed with a standard property wrapper, in order for it to integrate with WPF services like data binding, styling, and animation, it also needs to be a dependency property. A dependency property provides several features not present in .NET properties, including the ability to inherit its value from a container element, provide for object-independent storage (providing a potentially huge memory savings), and change tracking.
Most of the time, you won't have to worry about dependency properties versus .NET properties, but when you need the details, you can read about them in .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Resources
Resources are named chunks of data defined separately from code and bundled with your application or component. .NET provides a great deal of support for resources, a bit of which we already used when we referenced tom.png from our XAML button earlier in this chapter. WPF also provides special support for resources scoped to elements defined in the tree.
As an example, let's declare some default instances of our custom Nickname objects in XAML (see ).
Example . Declaring objects in XAML
<!-- Window1.xaml -->
<Window ... xmlns:local="clr-namespace:DataBindingDemo" />

  <Window.Resources>
    <local:Nicknames x:Key="names">
      <local:Nickname Name="Don" Nick="Naked" />
      <local:Nickname Name="Martin" Nick="Gudge" />
      <local:Nickname Name="Tim" Nick="Stinky" />
    </local:Nicknames>
  </Window.Resources>

  <DockPanel DataContext="{StaticResource names}">
    <TextBlock DockPanel.Dock="Top" Orientation="Horizontal">
      <TextBlock VerticalAlignment="Center">Name: </TextBlock>
      <TextBox Text="{Binding Path=Name}" />
      <TextBlock VerticalAlignment="Center">Nick: </TextBlock>
      <TextBox Text="{Binding Path=Nick}" />
    </TextBlock>
    ...
  </DockPanel>
</Window>
Notice the Window.Resources, which is property element syntax to set the Resources property of the Window1 class. Here we can add as many named objects as we like, with the name coming from the Key attribute and the object coming from the XAML elements (remember that a XAML element is just a mapping to .NET class names). In this example, we're creating a Nicknames collection named names to hold three Nickname objects, each constructed with the default constructor, and then setting each of the Name and Nick properties.
Also notice the use of the StaticResource markup extension to reference the names resource as the collection to use for data binding. With this XAML in place, our window construction reduces to the code shown in .
Example . Finding a resource in code
public partial class Window1 : Window {
  Nicknames names;

  public Window1(  ) {
    InitializeComponent(  );
    this.addButton.Click += addButton_Click;

    
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Styles
One of the major uses for resources is to specify styles. A style is a set of property/value pairs to be applied to one or more elements. For example, recall the two TextBlock controls from our Nickname sample, each of which was set to the same VerticalAlignment ().
Example . Multiple TextBlock controls with the same settings
<!-- Window1.xaml -->
<Window ...>
  <DockPanel ...>
    <TextBlock ...>
      <TextBlock VerticalAlignment="Center">Name: </TextBlock>
      <TextBox Text="{Binding Path=Name}" />
      <TextBlock VerticalAlignment="Center">Nick: </TextBlock>
      <TextBox Text="{Binding Path=Nick}" />
    </TextBlock>
    ...
  </DockPanel>
</Window>
If we wanted to bundle the VerticalAlignment setting into a style, we could do this with a Style element in a Resources block ().
Example . An example TextBlock style
<Window ...>
  <Window.Resources>
    ...
    <Style x:Key="myStyle" TargetType="{x:Type TextBlock}">
      <Setter Property="VerticalAlignment" Value="Center" />
      <Setter Property="Margin" Value="2" />
      <Setter Property="FontWeight" Value="Bold" />
      <Setter Property="FontStyle" Value="Italic" />
    </Style>
  </Window.Resources>
  <DockPanel ...>
    <TextBlock ...>
      <TextBlock Style="{StaticResource myStyle}">Name: </TextBlock>
      <TextBox Text="{Binding Path=Name}" />
      <TextBlock Style="{StaticResource myStyle}">Nick: </TextBlock>
      <TextBox Text="{Binding Path=Nick}" />
    </TextBlock>
    ...
  </DockPanel>
</Window>
The Style element is really just a named collection of Setter elements for a specific target type (and specified with the Type markup extension). The new TextBlock style centers the vertical alignment property and, just for fun, sets the margin, font width, and font style. With the style in place, you can use it to set the Style property of any TextBlock that references the style resource. illustrates the use to which we've put this style.
Figure : Named style in action on two TextBlock controls
Styles provide one great way to set the look of a control without building a custom control, by merely setting properties. There's much more on this topic in .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Animation
If you'd like to apply property changes to a control (or other visual element) over time, you can do so with styles that include animation information, which is discussed in (although is a small taste of what WPF animations can produce).
Figure : Buttons with animated glow ()
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Control Templates
In addition to changing a control's look by manipulating properties, you can replace it with something completely different by setting a control's Template property.
In , we've decided that our Add button is a yellow ellipse, as shown in .
Example . Replacing a control's look completely with a control template
<Button DockPanel.Dock="Bottom" x:Name="addButton" Content="Add">
  <Button.Template>
    <ControlTemplate TargetType="{x:Type Button}">
      <Grid>
        <Ellipse Width="128" Height="32" Fill="Yellow" Stroke="Black" />
        <ContentPresenter
          VerticalAlignment="Center" HorizontalAlignment="Center" />
      </Grid>
     </ControlTemplate>
  </Button.Template>
</Button>
Figure : A yellow ellipse button
The template of a control in WPF is what defines the look, whereas the code defines the behavior. The default template comes from the system-scope resources (as described in ), but if you don't like that one, you can replace it with whatever you like, using a content presenter to drop in the content provided by the developer using your control. However, the behavior remains the same (e.g., if you click on the ellipse-shaped button in , a Click event is still fired). We explore in detail the power of replacing the look of a control in .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Graphics
When building up a control's template, you'll likely build it with a set of graphics primitives that WPF provides, including rectangles, polygons, lines, ellipses, and so on. WPF also lets you affect the way it renders graphics in any element, offering facilities that include bordering, rotating, or scaling another shape or control. WPF's support for graphics is engineered to fit right into the content model we're already familiar with, as shown in , from .
Example . Adding graphics to a Button
<Button>
  <Button.LayoutTransform>
    <ScaleTransform ScaleX="3" ScaleY="3" />
  </Button.LayoutTransform>
  <StackPanel Orientation="Horizontal">
    <Canvas Width="20" Height="18" VerticalAlignment="Center">
         <Ellipse Canvas.Left="1" Canvas.Top="1" Width="16" Height="16"
               Fill="Yellow" Stroke="Black" />
      <Ellipse Canvas.Left="4.5" Canvas.Top="5" Width="2.5" Height="3"
               Fill="Black" />
      <Ellipse Canvas.Left="11" Canvas.Top="5" Width="2.5" Height="3"
               Fill="Black" />
      <Path Data="M 5,10 A 3,3 0 0 0 13,10" Stroke="Black" />
    </Canvas>
    <TextBlock VerticalAlignment="Center">Click!</TextBlock>
  </StackPanel>
</Button>
Here we've got three ellipses and a path composed inside a canvas that is hosted inside a stack panel with a text block that, when scaled via the LayoutTransform property on the button, produces .
Figure : A scaled button with a collection of graphics primitives
Notice that there's nothing special about the graphics primitives in XAML; they're declared and integrated as content just like any of the other WPF elements we've discussed. The graphics and the transformation are integrated into the same presentation stack as the rest of WPF, which is a bit of a difference for experienced User/GDI programmers.
For a complete discussion of how graphics primitives, retained drawings, color, lines, brushes, and transformations happen in WPF, both declaratively and in code, and for an introduction to 3D and video, read .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
3D
Graphics in WPF are not limited to 2D; shows an example of a figure that was defined using WPF's 3D capabilities.
Figure : 3D plot of data ()
For an introduction to 3D and how it integrates with your WPF applications, you'll want to read .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Documents and Printing
The document support in WPF is about flowing all the different content types you've seen in the rest of this chapter, along with special text-specific content types, into a seamless whole, a small sample of which is shown in .
Figure : A flowing document
The text-specific content support is provided with the flow document and related elements that provide advanced typography; adaptive, flow-based layout; spellchecking; hyphenation; and more, as described in .
In addition, the base of the flow document supports printing, as do the rest of the WPF visual elements, via the XML Paper Specification (XPS), as covered in .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Where Are We?
WPF applications have a great deal of power, at which this chapter can only hint. The base services of the application aren't too surprising, but the support for page-based navigation and browser hosting certainly adds a new capability for Windows applications, further enhanced with .NET 2.0 ClickOnce support.
Building your application is a matter of grouping controls in containers—either single content containers, like windows or buttons, or multiple content containers that provide layout capabilities, like the canvas and the grid.
When bringing your controls together, you'll want to populate them with data that's synchronized with the in-memory home of the data, which is what data binding is for, and keep them pretty, which is what styles are for. If you want to declare data or styles in your XAML, you can do so using resources, which are just arbitrarily named objects that aren't used to render the WPF UI directly.
If no amount of data or style property settings makes you satisfied with the look of your control, you can replace it completely with control templates, which can comprise other controls or graphics primitives. In addition, you can apply graphics operations, like rotating, scaling, or animation, to 2D or 3D graphics primitives or controls in WPF's integrated way. These elements can further be gathered into documents for viewing or printing.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Applications and Settings
A WPF application is a Windows process in which you have an instance of the WPF Application object. The Application object provides lifetime services and integration with ClickOnce deployment. Between application sessions, you'll want to be able to keep application and user settings in a way that integrates well with WPF applications. All of these topics are the focus of this chapter.
On the other hand, if you're interested in XML Browser Applications (XBAPs)—applications hosted in the browser and deployed over the Web—read .
In the Windows sense, an "application" is an address space and at least one thread of execution (a.k.a. a "process"). In the WPF sense, an application is a singleton object that provides services for UI components and UI programmers in the creation and execution of a WPF program. More specifically, in WPF, an application is an instance of the Application class from the System.Windows namespace.
shows code for creating an instance of the Application class.
Example . Creating an application explicitly
using System;
System.Windows; // the home of the Application class

class Program {
    [STAThread]
    static void Main(  ) {
        Application app = new System.Windows.Application(  );
        Window1 window = new Window1(  );
        window.Show(  );
        app.Run(  );
    }
}
Here, we're creating an application inside an STA thread, creating a window and showing it, and then running the application. While the application is running, WPF processes Windows messages and routes events to WPF UI objects as necessary. When the Run method returns, messages have stopped being routed and generally don't start again (unless you show a modal window after the Run method returns, but that's not something you'll usually do). During its lifetime, the application provides various services.
One of the services the Application class provides is access to the current instance. Once an instance of the Application class is created, it's available via the Current static property of the Application class. For example, the code in is equivalent to the code in .
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Application Lifetime
In the Windows sense, an "application" is an address space and at least one thread of execution (a.k.a. a "process"). In the WPF sense, an application is a singleton object that provides services for UI components and UI programmers in the creation and execution of a WPF program. More specifically, in WPF, an application is an instance of the Application class from the System.Windows namespace.
shows code for creating an instance of the Application class.
Example . Creating an application explicitly
using System;
System.Windows; // the home of the Application class

class Program {
    [STAThread]
    static void Main(  ) {
        Application app = new System.Windows.Application(  );
        Window1 window = new Window1(  );
        window.Show(  );
        app.Run(  );
    }
}
Here, we're creating an application inside an STA thread, creating a window and showing it, and then running the application. While the application is running, WPF processes Windows messages and routes events to WPF UI objects as necessary. When the Run method returns, messages have stopped being routed and generally don't start again (unless you show a modal window after the Run method returns, but that's not something you'll usually do). During its lifetime, the application provides various services.
One of the services the Application class provides is access to the current instance. Once an instance of the Application class is created, it's available via the Current static property of the Application class. For example, the code in is equivalent to the code in .
Example . Implicitly filling in the Application.Current property
using System;
using System.Windows;

class Program {
    [STAThread]
    static void Main(  ) {
        // Fills in Application.Current
        Application app = new System.Windows.Application(  );

        Window1 window = new Window1(  );
        window.Show(  );

        Application.Current.Run(); // same as app.Run(  )
    }
}
Here, in the process's entry point, we're creating an application, creating and showing the main window, and then running the application. Creation of the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Application Deployment
For the purposes of demonstration, let's build something vital for procrastinators the world over: an application to generate excuses. The application was started with the "Windows Application (WPF)" project template in Visual Studio 2005 and was implemented with some very simple code. When you run it, it gives you an excuse from its vast database, as shown in .
Figure : A WPF excuse-generation application
For anyone to use this wonderful application, it must be published. The simplest way to publish your WPF application is by right-clicking on the project in the Solution Explorer and choosing the Publish option, which will bring up the first page of the Publish Wizard (shown in ).
Figure : Publish Wizard publish location
asks you to choose where you'd like to deploy your application, including to the disk, to a network share, to an FTP server, or to a web site. By default, the Publish Wizard will assume you want to publish to the Publish subdirectory of your project directory. Clicking the Next button yields .
Figure : Publish Wizard installation options
Because we've chosen to publish to something besides a web site, the Publish Wizard wants to know how users will access your published application—in other words, from a URL, from a UNC path, or from some optical media. (If you choose to publish to a web site, the only way to access the application is from a URL, so it won't bother to ask.) We'd like to test web deployment, so we pick that option and leave the default URL alone. Clicking Next yields .
Figure : Install mode in the Publish Wizard
For WPF applications, lets us choose whether we'd like this application to be made available online (when the computer is able to connect to the application's URL) as well as offline (when the computer can't connect to the URL), or whether you'd like the application to be only available online. These two options correspond to the ClickOnce terms locally installed and online only, respectively.
The job of the Publish Wizard is to bundle up the files needed to deploy an application using ClickOnce, including the manifest files that ClickOnce needs to deploy the application to a client machine after it's been published.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Settings
WPF applications gain access to all the same application and user setting options that any other .NET application can use (e.g., the Registry, .config files, special folders, isolated storage, etc.).
The preferred settings mechanism for WPF applications is the one provided by .NET 2.0 and Visual Studio 2005: the ApplicationSettingsBase class from the System.Configuration namespace with the built-in designer. To access the settings for your application, click on the Settings tab in your project settings. This will bring up the Settings Designer shown in .
Figure : The Settings Designer
Here we've defined two settings: a user setting of type System.String, called LastExcuse; and an application setting of type System.Boolean, called ExcludeAnimalExcuses with a default value of True. These two settings will be loaded automatically when I run my application, pulled from the application's configuration file (named MyApplication.exe.config) and the user settings file saved from the application's last session.
The Settings Designer manages a settings file and generates a class that allows you to program against the settings. For instance, our settings example will result in the class in being generated (roughly).
Example . The Settings Designer-generated class
using namespace System.Configuration;

namespace excusegen.Properties {
  sealed partial class Settings : ApplicationSettingsBase {
    static Settings defaultInstance =
       ((Settings)(ApplicationSettingsBase.Synchronized(new Settings(  ))));


   public static Settings Default {
      get { return defaultInstance; }
  }

  [UserScopedSettingAttribute(  )]
  [DefaultSettingValueAttribute("")]
  public string LastExcuse {
      get { return ((string)(this["LastExcuse"])); }
      set { this["LastExcuse"] = value; }
  }

  [ApplicationScopedSettingAttribute(  )]
  [DefaultSettingValueAttribute("True")]
  public bool ExcludeAnimalExcuses {
      get { return ((bool)(this["ExcludeAnimalExcuses"])); }
     }
  }
}
There are several interesting things to notice about . The first is the defaultInstance
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Where Are We?
In WPF, the application contains an instance of the Application object. This object provides management services that let you control the lifetime of your application, as well as resource management and navigation, covered in , , and , respectively. In this chapter, we also discussed deploying standalone applications using ClickOnce. (XBAP deployment can be found in .) Finally, to manage user and application settings between application sessions, we briefly discussed the ApplicationSettingsBase-related settings services provided by .NET 2.0 and Visual Studio 2005.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Layout
WPF provides a powerful and flexible array of tools for controlling the layout of the user interface. These tools enable applications to present information to users in a clear and logical way.
There is a fine line between giving developers or designers enough control over the user interface's layout, and leaving them to do all the work. A good layout system should be able to automate common scenarios such as resizing, scaling, and adaptation to localization, but should allow manual intervention where necessary. In this chapter, we will look at how WPF's layout system helps fulfill these goals.
WPF provides a set of panels—special-purpose user interface elements whose job is to arrange the elements they contain. Each individual panel type offers a straightforward and easily understood layout mechanism. As with all WPF elements, layout objects can be composed in any number of different ways, so although each individual panel type is fairly simple, the flexible way in which they can be combined makes for a very powerful layout system. And you can even create your own layout element types should the built-in ones not meet your needs.
describes the main panel types built into WPF. Whichever panel you use, the same basic rule always applies: an element's position is always determined by the containing panel. Most panels also manage the size of their children.
Table : Main panel types
Panel type
Usage
StackPanel
Lays children out in a vertical or horizontal stack; extremely simple, useful for managing small-scale aspects of layout.
WrapPanel
Lays children out from left to right, moving onto a new line each time it fills the available width.
DockPanel
Allocates an entire edge of the panel area to each child; useful for defining the rough layout of simple applications at a coarse scale.
Grid
Arranges children within a grid; useful for aligning items without resorting to fixed sizes and positions. The most powerful of the built-in panels.
Canvas
Performs no layout logic—puts children where you tell it to; allows you to take complete control of the layout process.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Layout Basics
WPF provides a set of panels—special-purpose user interface elements whose job is to arrange the elements they contain. Each individual panel type offers a straightforward and easily understood layout mechanism. As with all WPF elements, layout objects can be composed in any number of different ways, so although each individual panel type is fairly simple, the flexible way in which they can be combined makes for a very powerful layout system. And you can even create your own layout element types should the built-in ones not meet your needs.
describes the main panel types built into WPF. Whichever panel you use, the same basic rule always applies: an element's position is always determined by the containing panel. Most panels also manage the size of their children.
Table : Main panel types
Panel type
Usage
StackPanel
Lays children out in a vertical or horizontal stack; extremely simple, useful for managing small-scale aspects of layout.
WrapPanel
Lays children out from left to right, moving onto a new line each time it fills the available width.
DockPanel
Allocates an entire edge of the panel area to each child; useful for defining the rough layout of simple applications at a coarse scale.
Grid
Arranges children within a grid; useful for aligning items without resorting to fixed sizes and positions. The most powerful of the built-in panels.
Canvas
Performs no layout logic—puts children where you tell it to; allows you to take complete control of the layout process.
UniformGrid
Arranges children in a grid where every cell is the same size.
By default, panels have no appearance of their own, the only visible effect of their presence being how they size and position their children. However, they can be made visible by setting their Background property.
We'll start with one of the most basic panels, StackPanel.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
StackPanel
StackPanel is a very simple panel that arranges its children in a row or a column. You will not normally use StackPanel to lay out your whole user interface. It is most useful for arranging small subsections. shows how to build a simple search user interface.
Example . StackPanel search layout
<StackPanel Background="#ECE9D8">
  <TextBlock Margin="3">Look for:</TextBlock>
  <ComboBox  Margin="3"/>
  <TextBlock Margin="3">Filtered by:</TextBlock>
  <ComboBox  Margin="3"/>
  <Button    Margin="3,5">Search</Button>
  <CheckBox  Margin="3">Search in titles only</CheckBox>
  <CheckBox  Margin="3">Match related words</CheckBox>
  <CheckBox  Margin="3">Search in previous results</CheckBox>
  <CheckBox  Margin="3">Highlight search hits (in topics)</CheckBox>
</StackPanel>
shows the results. As you can see, the UI elements have simply been stacked vertically one after another. This example used the Margin property to space the elements out a little. Most elements use a single number, indicating a uniform margin all around. The Button uses a pair of numbers to specify different vertical and horizontal margins. This is one of several standard layout properties available on all WPF elements, which are all described in the "" section, later in this chapter.
Many of the examples in this book represent typical snippets of XAML, rather than complete self-contained programs. You can download runnable versions of the examples from the book's web site at http://sellsbrothers.com/writing/wpfbook. If you would prefer to type in the examples, you can do that using the XamlPad tool that ships with the Windows SDK, but because the examples are only snippets, you will need to host them in a suitable root element such as a Page.
Figure : Search StackPanel with Margin
There is one problem with this layout: the Search button is much wider than you would normally expect a button to look. The default behavior of a vertical StackPanel is to make all of the controls the same width as the panel. Likewise, a horizontal StackPanel will make all of the controls the same height. For the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
WrapPanel
WrapPanel works just like a StackPanel until it runs out of space. If you provide a horizontal WrapPanel with more children than will fit in the available width, it will arrange its content in a way similar to how a word processor lays out words on a line. It puts the children in a row from left to right until it runs out of space, at which point it starts on the next line.
WrapPanel is very simple to use. Just as with a StackPanel, you add a sequence of children, as shows.
Example . WrapPanel
<WrapPanel Background="Beige">
  <Button>One</Button>
  <Button>Two</Button>
  <Button>Three</Button>
  <Button>Four</Button>
  <Button>Five</Button>
  <Button>Six</Button>
  <Button>Seven</Button>
  <Button>Eight</Button>
</WrapPanel>
As shows, the items are arranged from left to right. As you can see from the panel's filled-in background, it is not wide enough to accommodate all the items, so the last three have been wrapped onto the next line.
Figure : WrapPanel
WrapPanel also offers an Orientation property. Setting this to Vertical will arrange the children in a sequence of vertical stacks, a layout style very similar to Windows Explorer's "List" view.
WrapPanel and StackPanel really are useful only for small-scale layout. You will need to use a more powerful panel to define the overall layout of your application, such as DockPanel.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
DockPanel
Content preview·Buy PDF of this chapter|