of which language your project targets, the XAML defining the user interface will be the same.
Consequently, along with the new capabilities of the user interface controls there have been a number
of new supporting concepts on the code side of things, such as the introduction of dependency
properties (properties that can accept an expression that must be resolved as their value — which is
required in many binding scenarios to support XAML’s advanced binding capabilities). However,
you will find that the code-behind in a WPF application is much the same as a standard Windows
Forms application — the XAML side of things is where you need to do most of your learning.
When developing WPF applications, you need to think differently than the way you think when
developing Windows Forms applications. A core part of your new thought processes should be to take
full advantage of XAML’s advanced binding capabilities, with the code-behind no longer acting as
the controller for the user interface but serving it instead. Instead of the code “pushing” data into the
user interface and telling it what to do, the user interface should ask the code what it should do, and
request (that is, “pull”) data from it. It’s a subtle difference, but it greatly changes the way in which the
presentation layer of your application will be defined. Think of it as having a user interface that is now
in charge. The code can (and should) act as a decision manager, but no longer provides the muscle.
This “new thinking” has also led to new design patterns for how the code and the user interface
elements interact, such as the popular Model-View-ViewModel (MVVM) pattern, which enables
much better unit testing of the code serving the user interface and maintains a clean separation
between the designer and developer elements of the project. This results in changing the way you
write the code-behind, and ultimately changes the way you design your application. This clear
separation supports the designer/developer workflow, enabling a designer to work in Expression
Blend on the same part of the project as the developer (working in Visual Studio) without clashing.
By taking advantage of the flexibility of XAML, WPF enables you to design unique user interfaces
and user experiences. At the heart of this is WPF’s styling and templating functionality that
separates the look of controls from their behavior. This enables you to alter the appearance of
controls easily by simply defining an alternate “style” on that particular use without having to
modify the control itself.
Ultimately you could say that WPF uses a much better way of defining user interfaces than Windows
Forms does, through its use of XAML to define user interfaces, along with a number of additional
supporting concepts thrown in. The bad news is that the flexibility and power of XAML comes with
Getting started with WPf .
353
a corresponding steep learning curve that will take some time to climb, even for the experienced
developer. If you are a productive developer in Windows Forms, WPF will no doubt create
considerable frustration for you while you get your head around its concepts, and it really requires
a change in your developer mindset to truly get a grasp on it and how things hold together. Many
simple tasks will initially seem a whole lot harder than they should be, and would have been were
you to implement the same functionality or feature in Windows Forms. However, if you can make it
through this period you will start to see the benefits and appreciate the new possibilities that WPF
and XAML provide. Because Silverlight shares a lot conceptually with WPF (both being XAML
based, with Silverlight essentially being a subset of WPF), by learning and understanding WPF you
are also learning and understanding how to develop Silverlight applications.
If you’ve looked at earlier versions of WPF (those that shipped in the .NET
Framework 3.0 and 3.5 versions) you may have noticed that text rendered in
WPF often took on a rather blurry appearance instead of being crisp and sharp,
generating numerous complaints from the developer community. Fortunately in
the .NET Framework 4.0 the text rendering has been vastly improved, and if this
has held you back from developing WPF applications previously it is probably
time to take another look. Microsoft has demonstrated its faith in WPF by
rewriting Visual Studio’s code editor in WPF for the 2010 version to take
advantage of its power and flexibility.
GettinG started with wPf
When you open the New Project dialog you see a number of built-in project templates for WPF that
ship with Visual Studio 2010: WPF Application, WPF Browser Application, WPF Custom Control
Library, and WPF User Control Library, as shown in Figure 18-1.
fiGure 18-1
354 .
chaPter 18 WindoWS preSenTATion FoundATion (WpF)
You will notice that these projects are for the most part a direct parallel to the Windows Forms
equivalent. The exception is the WPF Browser Application, which generates an XBAP file that uses
the browser as the container for your rich client application (in much the same way as Silverlight
does, except an XBAP application targets the full .NET Framework, which must be installed on the
client machine).
For this example you create a project using the WPF Application template, but most of the features
of Visual Studio 2010 discussed herein apply equally to the other project types. The project
structure generated should look similar to Figure 18-2.
fiGure 18-2
Here you can see that the project structure consists of App.xaml and MainWindow.xaml, each with
a corresponding code-behind file (.cs or .vb), which you can view if you expand out the relevant
project items. At this stage the App.xaml contains an Application XAML element, which has a
StartupUri attribute used to define which XAML file will be your initial XAML file to load (by
default MainWindow.xaml). For those familiar with Windows Forms, this is the equivalent of the
startup form. So if you were to change the name of MainWindow.xaml and its corresponding class to
something more meaningful, you would need to make the following changes:
.
Change the filename of the .xaml file. The code-behind file will automatically be renamed
accordingly.
.
Change the class name in the code-behind file, along with its constructor, and change
the value of the x:Class attribute of the Window element in the .xaml file to reference the
new name of the class (fully qualified with its namespace). Note that the last two steps are
Getting started with WPf .
355
automatically performed if you change the class name in the code-behind file first and use the
smart tag that appears after doing so to rename the object in all the locations that reference it.
.
Finally, change the StartupUri attribute of the Application element in App.xaml to point
toward the new name of the .xaml file (because it is your startup object).
As you can see, a few more changes need to be made when renaming a file in a WPF project than
you would have to do in a standard Windows Forms project, however it ’s reasonably straightforward
when you know what you are doing (and using the smart tag reduces the number of steps required).
Working around the Visual Studio layout of Figure 18-2, you can see that the familiar Toolbox
tool window attached to the left side of the screen has been populated with WPF controls that
are similar to what you would be used to when building a Windows Forms application. Below
this window, still on the left side, is the Document Outline tool window. As with both Windows
Forms and Web Applications this gives you a hierarchical view of the elements on the current
window. Selecting any of these nodes in this window highlights the appropriate control in the
main editor window, making it easier to navigate more complex documents. An interesting
feature of the Document Outline when working with WPF is that as you hover over an item
you get a mini-preview of the control. This helps you identify that you are selecting the correct
control.
If the Document Outline tool window is not visible it may be collapsed against
one of the edges of Visual Studio. Alternatively, you may need to force it to be
displayed by selecting it from the View . Other Windows menu.
On the right side of Figure 18-2 is the Properties tool window. You may note that it has a very
similar layout and behavior to the Windows Forms designer Properties tool window. However, this
window in the WPF designer has additional features for editing WPF windows and controls. Finally,
in the middle of the screen is the main editor/preview space, which is currently split to show both
the visual layout of the window (above) and the XAML code that defines it (below).
xaMl fundamentals
If you have some familiarity working with XML (or to some extent HTML), you should find the
syntax of XAML relatively straightforward because it is XML based. XAML can have only a
single root level node, and elements are nested within each other to define the layout and content
of the user interface. Every XAML element maps to a .NET class, and the attribute names map to
properties/events on that class. Note that element and attribute names are case sensitive.
Take a look at the default XAML file created for the MainWindow class:
< Window x:Class="Chapter18Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300" >
< Grid >
< /Grid >
< /Window >
356 .
chaPter 18 WindoWS preSenTATion FoundATion (WpF)
Here you have Window as your root node, and a Grid element within it. To make sense of it, think of
it in terms of “your window contains a grid.” The root node maps to its corresponding code-behind
class via the x:Class attribute, and also contains some namespace prefix declarations (discussed
shortly) and some attributes used to set the value of properties (Title, Height, and Width) of the
Window class. The value of all attributes (regardless of type) should be enclosed within quotes.
You’ll note two namespace prefixes defined on the root node, both declared using xmlns (the XML
attribute used for declaring namespaces). You could consider XAML namespace prefix declarations
to be somewhat like the using/Imports statements at the top of a class in C#/VB, but not quite.
These declarations assign a unique prefix to the namespaces used within the XAML file, with the
prefix used to qualify that namespace when referring to a class within it (that is, specify the location
of the class). Prefixes reduce the verbosity of XAML by letting you use that prefix rather than
including the whole namespace when referring to a class within it in your XAML file. The prefix is
defined immediately following the colon after xmlns. The first definition actually doesn’t specify
a prefix because it is defining your default namespace (the WPF namespace). However, the second
namespace defines x as its prefix (the XAML namespace). Both definitions map to URIs rather than
specific namespaces — these are consolidated namespaces (that is, they cover multiple namespaces),
and hence reference the unique URI that is used to define that consolidation. However, you don’t need
to worry about this concept — leave these definitions as they are and simply add your own definitions
following them. When adding your own namespace definitions they will almost always begin with
clr-namespace and reference a CLR namespace and the assembly that contains it. For example:
xmlns:wpf="clr-namespace:Microsoft.Windows.Controls;assemblty=WPFToolkit"
Prefixes can be anything of your choosing, but it is best to make them short yet meaningful.
Namespaces are generally defined on the root node in the XAML file. This is not necessary because
a namespace prefix can be defined at any level in a XAML file, but it is generally a standard practice
to keep them together on the root node for maintainability purposes.
If you want to refer to a control in the code-behind or by binding it to another control in the XAML
file (such as ElementName binding) you will need to give your control a name. Many controls
implement the Name property for this purpose, but you may also find that controls are assigned a name
using the x:Name attribute. This is defined in the XAML namespace (hence the x: prefix) and can be
applied to any control. If the Name property is implemented (which it will be in most cases because it
is defined on the base classes that most controls inherit from), it simply maps to this property anyway
and they serve the same purpose. For example:
<Button x:Name="OKButton" Content="OK" />
is the same as:
<Button Name="OKButton" Content="OK" />
Either way is technically valid (although in Silverlight most controls don’t support the Name
attribute and you must use the x:Name attribute instead). Once one of these properties is set, a
field is generated (in the automatically generated code that you won’t see) that you can use to
refer to that control.
Getting started with WPf .
357
the wPf controls
WPF contains a rich set of controls to use in your user interfaces, roughly comparable to the standard
controls for Windows Forms. If you looked at previous versions of WPF you may have noticed a
number of controls (such as the Calendar, DatePicker, DataGrid, and so on), which are included in
the standard controls for Windows Forms but were not included in the standard controls for WPF.
Instead you had to turn to the free WPF Toolkit hosted on CodePlex to obtain these controls. This
toolkit was developed by Microsoft over time to help fill this hole in the original WPF release by
providing some of the missing controls. With WPF 4.0, however, you will find many of the controls
within the WPF Toolkit are now included within WPF’s standard controls, providing a reasonably
complete set of controls “out of the box.” Of course you can still use third-party controls where the