You are on page 1of 138

INDEX

DAY 1 - GETTING STARTED.................................................................................................................................. 6

LEARN WPF IN ONE WEEK.............................................................................................................................................6


WPF DEVELOPMENT TOOLS...........................................................................................................................................7
MICROSOFT VISUAL STUDIO 2010..................................................................................................................................7
MICROSOFT EXPRESSION BLEND 3 + SKETCH FLOW............................................................................................................8
OTHER USEFUL TOOLS....................................................................................................................................................8
INTRODUCTION TO WINDOWS PRESENTATION FOUNDATION.................................................................................................9
Overview.................................................................................................................................................................9
Separation of Appearance and Behavior................................................................................................................9
Rich composition....................................................................................................................................................9
Highly customizable..............................................................................................................................................10
Resolution independence.....................................................................................................................................10
HOW TO CREATE A SIMPLE WPF APPLICATION.................................................................................................................10
In Visual Studio 2008............................................................................................................................................10
USER EXPERIENCE DESIGN PROCESS...............................................................................................................................13
User Experience becomes a Key Success Factor...................................................................................................13
New Tools for Designers.......................................................................................................................................13
Development Workflow of a WPF Project............................................................................................................14
1. Elicit Requirements..........................................................................................................................................15
2. Create and Validate UI Prototype...................................................................................................................15
3. Implement Business Logic and Raw User Interface........................................................................................16
4. Integrate Graphical Design.............................................................................................................................16
5. Test software...................................................................................................................................................16
Roles.....................................................................................................................................................................16
More Infos............................................................................................................................................................17

DAY 2 - CONCEPTS OF WPF................................................................................................................................ 18

INTRODUCTION TO XAML............................................................................................................................................18
Advantages of XAML............................................................................................................................................18
XAML vs. Code......................................................................................................................................................18
Properties as Elements.........................................................................................................................................19
Implicit Type conversion.......................................................................................................................................19
Markup Extensions...............................................................................................................................................20
Namespaces.........................................................................................................................................................20
LOGICAL- AND VISUAL TREE..........................................................................................................................................21
Introduction..........................................................................................................................................................21
Why do we need two different kind of trees?......................................................................................................21
The Logical Tree....................................................................................................................................................22
The Visual Tree.....................................................................................................................................................22
Programmatically Find an Ancestor in the Visual Tree......................................................................................22
DEPENDENCY PROPERTIES............................................................................................................................................23
Introduction..........................................................................................................................................................23
Value resolution strategy.....................................................................................................................................24
The magic behind it..............................................................................................................................................24
How to create a DependencyProperty.................................................................................................................25
Value Changed Callback......................................................................................................................................26
Coerce Value Callback.........................................................................................................................................26

1
Validation Callback..............................................................................................................................................27
Readonly DependencyProperties..........................................................................................................................27
Attached Properties..............................................................................................................................................28
Listen to dependency property changes...............................................................................................................29
How to clear a local value....................................................................................................................................30
ROUTED EVENTS........................................................................................................................................................ 30
How to Create a Custom Routed Event................................................................................................................31

DAY 3 - LAYOUT AND CONTROLS....................................................................................................................... 32

INTRODUCTION TO WPF LAYOUT..................................................................................................................................32


Why layout is so important..................................................................................................................................32
Best Practices........................................................................................................................................................32
Vertical and Horizontal Alignment.......................................................................................................................33
Margin and Padding.............................................................................................................................................33
Height and Width.................................................................................................................................................33
Overflow Handling................................................................................................................................................33
Clipping................................................................................................................................................................33
Scrolling................................................................................................................................................................34
Related Articles.....................................................................................................................................................34
GRID PANEL.............................................................................................................................................................. 34
Introduction..........................................................................................................................................................34
Define Rows and Columns....................................................................................................................................35
How to add controls to the grid...........................................................................................................................36
Resizable columns or rows...................................................................................................................................37
How to share the width of a column over multiple grids.....................................................................................38
Useful Hints..........................................................................................................................................................39
Using GridLenghts from code...............................................................................................................................39
More on this topic................................................................................................................................................39
WPF STACKPANEL..................................................................................................................................................... 39
Introduction..........................................................................................................................................................40
Stack Items horizontally.......................................................................................................................................40
BUILT-IN CONTROLS OF WPF.......................................................................................................................................41

DAY 4 - DATABINDING AND UI ARCHITECTURE.................................................................................................. 43

DATABINDING IN WPF................................................................................................................................................43
Introduction..........................................................................................................................................................43
DataContext.........................................................................................................................................................44
ValueConverters...................................................................................................................................................44
HOW TO NAVIGATE, GROUP, SORT AND FILTER DATA IN WPF...........................................................................................45
What is a CollectionView?....................................................................................................................................46
How to Create and Use a CollectionView.............................................................................................................46
Navigation............................................................................................................................................................47
Filtering.................................................................................................................................................................48
Refresh the filter...................................................................................................................................................48
Sorting..................................................................................................................................................................48
Fast Sorting...........................................................................................................................................................49
Grouping...............................................................................................................................................................49
How to create a CollectionView in XAML.............................................................................................................50
MODEL-VIEW-VIEWMODEL PATTERN............................................................................................................................51
Introduction..........................................................................................................................................................51

2
Introducing the Model-View-ViewModel pattern................................................................................................51
DATA VALIDATION IN WPF..........................................................................................................................................52
Implementing a ValidationRule (.NET 3.0 style)...................................................................................................52
Build a converter to convert ValidationErrors to a multi-line string....................................................................54
Create an ErrorTemplate for the TextBox............................................................................................................55
The ValidationRule and the ErrorTemplate in Action...........................................................................................56
How to manually force a Validation.....................................................................................................................56
VALUECONVERTERS.................................................................................................................................................... 57
Introduction..........................................................................................................................................................57
How to implement a ValueConverter...................................................................................................................57
How to use a ValueConverter in XAML.................................................................................................................58
Simplify the usage of ValueConvers.....................................................................................................................58
StringFormat Converter........................................................................................................................................59
BEHAVIORS................................................................................................................................................................60
Introduction..........................................................................................................................................................60
How to use behaviors in Expression Blend 3........................................................................................................60
How does it work..................................................................................................................................................61
How to implement your own behavior.................................................................................................................62
List of some popular behaviors.............................................................................................................................63

DAY 5 - TEMPLATES AND STYLES....................................................................................................................... 64

USER EXPERIENCE DESIGN PROCESS...............................................................................................................................64


User Experience becomes a Key Success Factor...................................................................................................64
New Tools for Designers.......................................................................................................................................64
Development Workflow of a WPF Project............................................................................................................65
1. Elicit Requirements...........................................................................................................................................66
2. Create and Validate UI Prototype....................................................................................................................66
3. Implement Business Logic and Raw User Interface..........................................................................................67
4. Integrate Graphical Design...............................................................................................................................67
7
Roles.....................................................................................................................................................................67
More Infos............................................................................................................................................................68
INTRODUCTION TO STYLES IN WPF................................................................................................................................68
Style inheritance...................................................................................................................................................69
CONTROL TEMPLATES..................................................................................................................................................70
Introduction..........................................................................................................................................................70
ContentPresenter..................................................................................................................................................71
What if a Binding working or a Setter is not applied when using a control template.........................................72
DATA TEMPLATES.......................................................................................................................................................72
Introduction..........................................................................................................................................................72
DataTemplates in Action: Building a simple PropertyGrid...................................................................................72
How to use a DataTemplateSelector to switch the Template depending on the data........................................74
How to react to IsSelected in the DataTemplate.................................................................................................76

LOCALIZATION.................................................................................................................................................. 77

HOW TO EVALUATE A LOCALIZATION MECHANISM.............................................................................................................77


Different WPF translation mechanisms compared..............................................................................................77
LOCALIZATION OF A WPF APPLICATION USING A CUSTOM MARKUPEXTENSION......................................................................77
The Idea................................................................................................................................................................77
Other Implementations........................................................................................................................................78

3
How to use it.........................................................................................................................................................78
Implementation details of the translation infrastructure....................................................................................78

INTERACTION.................................................................................................................................................... 85

BEHAVIORS................................................................................................................................................................85
Introduction..........................................................................................................................................................85
How to use behaviors in Expression Blend 3........................................................................................................85
How does it work..................................................................................................................................................86
How to implement your own behavior.................................................................................................................87
List of some popular behaviors.............................................................................................................................88
DRAG AND DROP IN WPF............................................................................................................................................88
Drag&Drop in 6 Steps...........................................................................................................................................89
Drag......................................................................................................................................................................89
Drop......................................................................................................................................................................91

RESOURCE........................................................................................................................................................ 94

IMPROVE THE PERFORMANCE OF MERGED RESOURCEDICTIONARIES......................................................................................94


HOW TO READ WPF RESOURCEDICTIONARIES FROM WINFORMS........................................................................................96

2D GRAPHICS.................................................................................................................................................... 98

DRAW LINES EXCACTLY ON PHYSICAL DEVICE PIXELS...........................................................................................................98


Why do my lines appear so blurry?......................................................................................................................98
Resolution independence.....................................................................................................................................98
Align the edges not the center points..................................................................................................................99
Using SnapToDevicePixels for controls.................................................................................................................99
Using GuidelineSets for custom drawing.............................................................................................................99
Adjust the penwidth to the screen resolution....................................................................................................100
HOW TO GET A BITMAP FROM A VISUAL.......................................................................................................................101
WPF GEOMETRY TRANSFORMATION TOOL...................................................................................................................101
IMAGES IN WPF.......................................................................................................................................................102
How to create a Thumbnail of an Image............................................................................................................102
How to automatically crop an image.................................................................................................................103

3D GRAPHICS.................................................................................................................................................. 106

INTRODUCTION TO WPF 3D.......................................................................................................................................106


3D Graphic Basics...............................................................................................................................................106
A world of triangles............................................................................................................................................106
A right handed coordinate system.....................................................................................................................107
Elements of a 3D scene.......................................................................................................................................107
Hello 3D-World - A Simple Cube.........................................................................................................................108

ANIMATION.................................................................................................................................................... 110

DEBUGGING STYLE AND TEMPLATE ERRORS....................................................................................................................110


Common Errors...................................................................................................................................................110
HOW TO CONTROL THE FRAME RATE FOR WPF ANIMATIONS............................................................................................110

MULTIMEDIA.................................................................................................................................................. 111

HOW TO USE THE SPEECH SYNTHESIZER IN WPF............................................................................................................111

WINDOWS 7................................................................................................................................................... 112

HOW TO EXTEND THE AERO GLASS INTO THE CLIENT AREA...............................................................................................112

4
Introduction........................................................................................................................................................112
Extending the Glass............................................................................................................................................112
HOW TO USE THE WINDOWS VISTA TASKDIALOG IN WPF...............................................................................................116
Introduction........................................................................................................................................................117
HOW TO ADD TASKS TO JUMPLISTS IN .NET 4.0 AND WINDOWS 7...................................................................................117
Introduction........................................................................................................................................................117
How to add a Task to the Jumplist.....................................................................................................................118

INTEROPERABILITY.......................................................................................................................................... 120

How to get the Handle of a WPF Window.........................................................................................................120

PERFORMANCE............................................................................................................................................... 121

50 WPF PERFORMANCE TIPS.....................................................................................................................................121


Application Startup.............................................................................................................................................121

EXPRESSION BLEND......................................................................................................................................... 122

PROTOTYPING WITH EXPRESSION BLEND 3 + SKETCHFLOW..............................................................................................122


Introduction........................................................................................................................................................122
The idea of SketchFlow.......................................................................................................................................122
Workspace setup................................................................................................................................................123
Create a new SketchFlow project.......................................................................................................................123
Create and connect screens................................................................................................................................123
Drop sketchy controls onto screens....................................................................................................................124
Extract common parts to component screens....................................................................................................125
Wire-up navigation.............................................................................................................................................126
Add sample data.................................................................................................................................................127
Add assets from Photoshop, Illustrator or PowerPoint......................................................................................129
Test prototype and get feedback.......................................................................................................................130
Generate prototype documentation..................................................................................................................132
HOW TO IMPORT PHOTOSHOP FILES INTO WPF.............................................................................................................134
Introduction........................................................................................................................................................134
Preparing the Photoshop File.............................................................................................................................134
Directly Import Photoshop Files in Expression Blend.........................................................................................135
How to convert Path to Resources.....................................................................................................................136
Import Photoshop Files in Expression Design and Export to XAML....................................................................136
EXPRESSION BLEND 2 ADDINS.....................................................................................................................................138
Introduction........................................................................................................................................................138
Popular Addins...................................................................................................................................................138
How to Load and Run an AddIn..........................................................................................................................138

TOOLS............................................................................................................................................................. 139

XAML CONVERTERS.................................................................................................................................................139
DEBUGGING AND DEVELOPMENT UTILITIES....................................................................................................................139
XAML EDITORS....................................................................................................................................................... 139
GRAPHICAL WPF DESIGNERS......................................................................................................................................140

5
Day 1 - Getting Started

Learn WPF in one Week


I started to build a onw week training course to learn WPF. Starting with the basics and going
through the important concepts of the framework up to more complex topics. I hope you like it.

Day 1 - Getting started


Install the development tools

Learn the basic concepts of WPF

Create your first WPF application

Learn how WPF changed the development workflow

Day 2 - Concepts of WPF


Get an introduction to XAML

Learn about the hierarchical relation of elements in WPF

Find out about the magic behind DependencyProperties

Get familiar with routed events.

Day 3 - Layout and Controls


Learn the layout basics

See the grid layout panel in action

Stack elements with the stackpanel

Get an overview about the variety of included controls.

Have a look at 3rd-party libraries

6
Day 4 - DataBinding and UI Architecture
Introduction to WPF DataBinding

How to display, sort and filter data

Using the Model-View-ViewModel Pattern

Learn how to validate user input

Create your own ValueConverter

Enhance the MVVM pattern by using Behaviors and Actions

Day 5 - Templates and Styles


Learn how to build rich user experience with WPF

Style the appearance of your controls

Completely replace the look of a control

How to display complex data in lists by using DataTemplates.

WPF Development Tools


Microsoft provides two development tools for WPF applications. One is Visual Studio, made for
developers and the other is Expression Blend made for designers. While Visual Studio is good
in code and XAML editing, it has a rare support for all the graphical stuff like gradients, template
editing, animation, etc. This is the point where Expression Blend comes in. Blend covers the
graphical part very well but it has (still) rare support for code and XAML editing.

So the conclusion is that you will need both of them.

Microsoft Visual Studio 2010


Visual Studio is the tool for developers to develop WPF applications. It includes a graphical
designer for WPF since version 2008. If you're using Visual Studio 2005 you can install an add-
on that enables you to develop WPF applications.

7
Microsoft provides a free Express Edition of Visual Studio that also includes the WPF designer.
You can download it from the following URL

Download Microsoft Visual C# 2010 - Express Edition

Microsoft Expression Blend 3 + Sketch Flow


Expression Blend is the tool for designers. It's part of the Expression Studio, a new tool suite
from Microsoft especially created for user experience designers. Blend covers all the missing
features of the Visual Studio designer like styling, templating, animations, 3D graphics, resources
and gradients.

In the latest Version it also includes a powerful prototyping tool called SketchFlow. Expression
Blend can open solution files created by visual studio.

Download Microsoft Expression Blend 3

Other useful tools


 Snoop (Inspect the Visual Tree of running WPF applications)
 Mole (Data Visualizer for Visual Studio
 XAML Power Toys

8
 WPF Performance Suite

Introduction to Windows Presentation Foundation


Overview

The Windows Presentation Foundation is Microsofts next generation UI framework to create


applications with a rich user experience. It is part of the .NET framework 3.0 and higher.

WPF combines application UIs, 2D graphics, 3D graphics, documents and multimedia into one
single framework. Its vector based rendering engine uses hardware acceleration of modern
graphic cards. This makes the UI faster, scalable and resolution independent.

The followinig illustration gives you an overview of the main new features of WPF

Separation of Appearance and Behavior

WPF separates the appearance of an user interface from its behavior. The appearance is
generally specified in the Extensible Application Markup Language (XAML), the behavior is
implemented in a managed programming language like C# or Visual Basic. The two parts are
tied together by databinding, events and commands. The separation of appearance and
behavior brings the following benefits:

 Appearance and behaviour are loosely coupled


 Designers and developers can work on separate models.
 Graphical design tools can work on simple XML documents instead of parsing code.

Rich composition

9
Controls in WPF are extremely composable. You can define almost any type of controls as
content of another. Although these flexibility sounds horrible to designers, its a very powerful
feature if you use it appropriate. Put an image into a button to create an image button, or put a
list of videos into a combobox to choose a video file.

<Button>
<StackPanel Orientation="Horizontal">
<Image Source="speaker.png" Stretch="Uniform"/>
<TextBlock Text="Play Sound" />
</StackPanel>
</Button> 

Highly customizable

Because of the strict separation of appearance and behavior you can easily change the look of a
control. The concept of styles let you skin controls almost like CSS in HTML. Templates let you
replace the entire appearance of a control.

The following example shows an default WPF button and a customized button.

Resolution independence

All measures in WPF are logical units - not pixels. A logical unit is a 1/96 of an inch. If you
increase the resolution of your screen, the user interface stays the same size - if just gets
crispier. Since WPF builds on a vector based rendering engine it's incredibly easy to build
scaleable user interfaces.

How to create a simple WPF application


In Visual Studio 2008

10
Open Visual Studio 2008 and choose "File", "New", "Project..." in the main menu. Choose "WPF
Application" as project type.

Choose a folder for your project and give it a name. Then press "OK"

Visual Studio creates the project and automatically adds some files to the solution. A
Window1.xaml and an App.xaml. The structure looks quite similar to WinForms, except that the
Window1.designer.cs file is no longer code but it's now declared in XAML as
Window1.xaml

Open the Window1.xaml file in the WPF designer and drag a Button and a TextBox from the
toolbox to the Window

11
Select the Button and switch to the event view in the properties window (click on the little
yellow lightning icon). Doubleclick on the "Click" event to create a method in the codebehind
that is called, when the user clicks on the button.

Note: If you do not find a yellow lightning icon, you need to install the Service Pack 1 for
VisualStudio on your machine. Alternatively you can doubleclick on the button in the
designer to achieve the same result.

Visual Studio automatically creates a method in the code-behind file that gets called when the
button is clicked.
private void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Text = "Hello WPF!";

The textbox has automatically become assigned the name textBox1 by the WPF designer. Set
text Text to "Hello WPF!" when the button gets clicked and we are done! Start the application by
hit [F5] on your keyboard.

12
Isn't this cool!

User Experience Design Process


User Experience becomes a Key Success Factor

In the past, we focused mainly on building products that fulfilled the functional requirements of
the user. User experience was often considered late in the development process. But today the
customer demands more than just a working product. Providing the right features is still the
prerequisite for a good product, but to turn it into something extraordinary you need to provide
a good user experience!

Providing a rich user experience is not a thing of fortune. It needs to be planed, designed and
integrated into the development of a product. Designing a rich user experience is not only
about make up your user interface by some graphics and gradients - its a much broader
concept. Its about creating an emotional connection between the user and your software. It
makes the user feel good and so he likes to continue using the software.

New Tools for Designers

Microsoft recognized, give development teams the power to create rich user experiences it
needs a lot more graphical tool support than VisualStudio can provide today. So they decided to
create a new tool suite - made for designers.

13
This tool suite is called Microsoft Expression. It consists of the four products:

 Expression Blend is built to create user interfaces in WPF and Silverlight. It builds the
bridge between designer and developers. It can open VisualStudio solutions
 Expression Design is a leightweight version of Adobe Illustrator to create and edit
vector graphics.
 Expression Media is built to encode, cut and enrich video files and optimize them for
silverlight streaming
 Expression Web is Microsoft next generation of HTML and Javascript editor. Its the
replacement for Frontpage.

Together they are a powerful package. The following illustration shows a sample workflow of
integrating a vector image that is created by a graphics designer in Adobe Illustrator into a WPF
project that is part of a VisualStudio solution.

Development Workflow of a WPF Project

14
Developing a WPF application with a rich user experience requires a lot more skills than just a
requirements analyst that defines a list of use cases and developer that implements the
software. You have to find out what the user really needs. This can be done by following a user
centered approach.

1. Elicit Requirements

Like in any kind of software projects its important to know and focus the target of your
development. You should talk to stakeholders and users to find out the real needs. These needs
should be refined to features and expressed in use cases (abstract) or user scenarios
(illustrative). Priorize the tasks by risk and importance and work iteratively. This work is done by
the role of the requirements engineer.

2. Create and Validate UI Prototype

Creating a user interface prototype is an important step to share ideas between users and
engineers to create a common understanding of the interaction design. This task is typically
done by an interaction designer. It's helpful to only sketch the user interface in a rough way to
prevent early discussions about design details. There are multiple techniques and tools to do
this. Some of them are:

 Paper prototype
Use paper and pencil to draw rough sketches of your user interface. No tools and
infrastructure is needed. Everyone can just scribble thier ideas on the paper.
 Wireframes
Wireframes are often used to sketch the layout of a page. It's called wireframes because

15
you just draw the outlines of controls and images. This can be done with tools like
PowerPoint or Visio
 Expression Blend 3 - Sketch Flow Sketch flow is a new cool feature to create interactive
prototypes directly in WPF. You can use the integrated "wiggly style" to make it look
sketchy. The prototype can be run in a standalone player that has an integrated feedback
mechanism.
 Interactive Prototype The most expensive and real approach is to create an (reusable)
interactive prototype that works as the real application but with dummy data.

It is strongly recommended to test your UI prototype on real users. This helps you to find out
and address design problems early in the development process. The following techniques are
very popular to evaluate UI prototypes:

 Walktrough
A walktrough is usually done early in a project with wireframes or paper prototypes. The
user gets a task to solve and he controlls the prototype by touching on the paper. The
test leader than presents a new paper showing the state after the interaction.
 Usability Lab
To do a usability lab, you need a computer with a screen capture software and a camera.
The proband gets an task to do and the requirements and interaction engineer watch
him doing this. They should not talk to him to find out where he gets stuck and why.

3. Implement Business Logic and Raw User Interface

4. Integrate Graphical Design

5. Test software

Roles

Buliding a modern user interface with a rich user experience requires additional skills from your
development team. These skills are described as roles that can be distributed among peoples in
your development team.

 Developer
The developer is responsible to implement the functionality of the application. He
creates the data model, implements the business logic and wires all up to a simple view.
 Graphical Designer
The graphical designer is responsible to create a graphical concept and build graphical
assets like icons,logos, 3D models or color schemes. If the graphical designer is familiar
with Microsoft Expression tools he directly creates styles and control templates.
 Interaction Designer
The interaction designer is responsible for the content and the flow of a user interface.

16
He creates wireframes or UI sketches to share its ideas with the team or customer. He
should validate his work by doing walktroughs or storyboards.
 Integrator
The integrator is the artist between the designer and the developer world. He takes the
assets of the graphical designer and integrates them into the raw user interface of the
developer. This role needs a rare set of skills and so it's often hard to find the right
person for it.

More Infos

The New Iteration - Microsoft Paper about the Designer/Developer collaboration

17
Day 2 - Concepts of WPF

Introduction to XAML
XAML stands for Extensible Application Markup Language. Its a simple language based on XML
to create and initialize .NET objects with hierarchical relations. Altough it was originally invented
for WPF it can by used to create any kind of object trees.

Today XAML is used to create user interfaces in WPF, Silverlight, declare workflows in WF and
for electronic paper in the XPS standard.

All classes in WPF have parameterless constructors and make excessive usage of properties. That
is done to make it perfectly fit for XML languages like XAML.

Advantages of XAML

All you can do in XAML can also be done in code. XAML ist just another way to create and
initialize objects. You can use WPF without using XAML. It's up to you if you want to declare it in
XAML or write it in code. Declare your UI in XAML has some advantages:

 XAML code is short and clear to read


 Separation of designer code and logic
 Graphical design tools like Expression Blend require XAML as source.
 The separation of XAML and UI logic allows it to clearly separate the roles of designer
and developer.

XAML vs. Code

As an example we build a simple StackPanel with a textblock and a button in XAML and
compare it to the same code in C#.
<StackPanel>
<TextBlock Margin="20">Welcome to the World of XAML</TextBlock>
<Button Margin="10" HorizontalAlignment="Right">OK</Button>
</StackPanel> 
The same expressed in C# will look like this:

// Create the StackPanel


StackPanel stackPanel = new StackPanel();
this.Content = stackPanel;
// Create the TextBlock

18
TextBlock textBlock = new TextBlock();
textBlock.Margin = new Thickness(10);
textBlock.Text = "Welcome to the World of XAML";
stackPanel.Children.Add(textBlock);
// Create the Button
Button button = new Button();
button.Margin= new Thickness(20);
button.Content = "OK";
stackPanel.Children.Add(button); 
As you can see is the XAML version much shorter and clearer to read. And that's the power of
XAMLs expressiveness.

Properties as Elements

Properties are normally written inline as known from XML <Button Content="OK" />. But
what if we want to put a more complex object as content like an image that has properties itself
or maybe a whole grid panel? To do that we can use the property element syntax. This allows us
to extract the property as an own chlild element.
<Button>
<Button.Content>
<Image Source="Images/OK.png" Width="50" Height="50" />
</Button.Content>
</Button> 

Implicit Type conversion

A very powerful construct of WPF are implicit type converters. They do their work silently in the
background. When you declare a BorderBrush, the word "Blue" is only a string. The implicit
BrushConverter makes a System.Windows.Media.Brushes.Blue out of it. The same
regards to the border thickness that is beeing converted implicit into a Thickness object. WPF
includes a lot of type converters for built-in classes, but you can also write type converters for
your own classses.
<Border BorderBrush="Blue" BorderThickness="0,10">
</Border> 

Markup Extensions

Markup extensions are dynamic placeholders for attribute values in XAML. They resolve the
value of a property at runtime. Markup extensions are surrouded by curly braces (Example:
Background="{StaticResource NormalBackgroundBrush}"). WPF has some built-in
markup extensions, but you can write your own, by deriving from MarkupExtension. These
are the built-in markup extensions:

 Binding
To bind the values of two properties together.

19
 StaticResource
One time lookup of a resource entry
 DynamicResource
Auto updating lookup of a resource entry
 TemplateBinding
To bind a property of a control template to a dependency property of the control
 x:Static
Resolve the value of a static property.
 x:Null
Return null

The first identifier within a pair of curly braces is the name of the extension. All preciding
identifiers are named parameters in the form of Property=Value. The following example shows a
label whose Content is bound to the Text of the textbox. When you type a text into the text
box, the text property changes and the binding markup extension automatically updates the
content of the label.
<TextBox x:Name="textBox"/>
<Label Content="{Binding Text, ElementName=textBox}"/>

Namespaces

At the beginning of every XAML file you need to include two namespaces.
The first is http://schemas.microsoft.com/winfx/2006/xaml/presentation. It is
mapped to all wpf controls in System.Windows.Controls.
The second is http://schemas.microsoft.com/winfx/2006/xaml it is mapped to
System.Windows.Markup that defines the XAML keywords.
The mapping between an XML namespace and a CLR namespace is done by the
XmlnsDefinition attribute at assembly level. You can also directly include a CLR namespace
in XAML by using the clr-namespace: prefix.
 

<Window
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>
</Window>

Logical- and Visual Tree

20
Introduction

Elements of a WPF user interface are hierarchically related. This relation is called the
LogicalTree. The template of one element consists of multiple visual elements. This tree is called
the VisualTree. WPF differs between those two trees, because for some problems you only need
the logical elements and for other problems you want all elements.
<Window>
<Grid>
<Label Content="Label" />
<Button Content="Button" />
</Grid>
</Window>

Why do we need two different kind of trees?

A WPF control consists of multiple, more primitive controls. A button - for example - consists of
a border, a rectangle and a content presenter. These controls are visual children of the button.
When WPF renders the button, the element itself has no appearance, but it iterates through the
visual tree and renders the visual children of it. This hierarchical relation can also be used to do
hit-testing, layout etc.
But sometimes you are not interested in the borders and rectangles of a controls' template.
Particulary because the template can be replaced, and so you should not relate on the visual
tree structure! Because of that you want a more robust tree that only contains the "real" controls
- and not all the template parts. And that is the eligibility for the logical tree.

The Logical Tree

21
The logical tree describes the relations between elements of the user interface. The logical tree
is responsible for:

 Inherit DependencyProperty values


 Resolving DynamicResources references
 Looking up element names for bindings
 Forwaring RoutedEvents

The Visual Tree

The visual tree contains all logical elements including all visual elements of the template of
each element.<BR

The visual tree is responsible for:

 Rendering visual elements


 Propagate element opacity
 Propagate Layout- and RenderTransforms
 Propagate the IsEnabled property.
 Do Hit-Testing
 RelativeSource (FindAncestor)

Programmatically Find an Ancestor in the Visual Tree

If you are a child element of a user interface and you want to access data from a parent element,
but you don't know how many levels up that elemens is, it's the best solution to navigate up the
tree until it finds an element of the requested type.

This helper does excactly this. You can use almost the same code to navigate through the logical
tree.
public static class VisualTreeHelperExtensions
{
public static T FindAncestor<T>(DependencyObject dependencyObject)
where T : class
{
DependencyObject target = dependencyObject;
do
{
target = VisualTreeHelper.GetParent(target);
}
while (target != null && !(target is T));
return target as T;
}

22

The following example shows how to use the helper. It starts at this and navigates up the
visual tree until it finds an element of type Grid. If the helper reaches the root element of the
tree, it returns null.
var grid = VisualTreeHelperExtensions.FindAncestor<Grid>(this); 

Dependency Properties
Introduction

Value resolution strategy

The magic behind it

How to create a DepdencyProperty

Readonly DependencyProperties

Attached DependencyProperties

Listen to dependency property changes

How to clear a local value

Introduction

When you begin to develop appliations with WPF, you will soon stumble across
DependencyProperties. They look quite similar to normal .NET properties, but the concept
behind is much more complex and powerful.

The main difference is, that the value of a normal .NET property is read directly from a private
member in your class, whereas the value of a DependencyProperty is resolved dynamically
when calling the GetValue() method that is inherited from DependencyObject.
When you set a value of a dependency property it is not stored in a field of your object, but in
a dictionary of keys and values provided by the base class DependencyObject. The key of an
entry is the name of the property and the value is the value you want to set.
The advantages of dependency properties are

 Reduced memory footprint


It's a huge dissipation to store a field for each property when you think that over 90% of
the properties of a UI control typically stay at its initial values. Dependency properties
solve these problems by only store modified properties in the instance. The default
values are stored once within the dependency property.

 Value inheritance
When you access a dependency property the value is resolved by using a value
resolution strategy. If no local value is set, the dependency property navigates up the

23
logical tree until it finds a value. When you set the FontSize on the root element it
applies to all textblocks below except you override the value.

 Change notification
Dependency properties have a built-in change notification mechanism. By registering a
callback in the property metadata you get notified, when the value of the property has
been changed. This is also used by the databinding.

Value resolution strategy

Every time you access a dependency property, it internally resolves the value by following the
precedence from high to low. It checks if a local value is available, if not if a custom style trigger
is active,... and continues until it founds a value. At last the default value is always available.

The magic behind it

Each WPF control registers a set of DependencyProperties to the static


DependencyProperty class. Each of them consists of a key - that must be unique per type -
and a metadata that contain callbacks and a default value.
All types that want to use DependencyProperties must derive from DependencyObject.
This baseclass defines a key, value dictionary that contains local values of dependency
properties. The key of an entry is the key defined with the dependency property.
When you access a dependency property over its .NET property wrapper, it internally calls
GetValue(DependencyProperty) to access the value. This method resolves the value by
using a value resolution strategy that is explained in detail below. If a local value is available, it
reads it directly from the dictionary. If no value is set if goes up the logical tree and searches for
an inherited value. If no value is found it takes the default value defined in the property
metadata. This sequence is a bit simplified, but it shows the main concept.

24
How to create a DependencyProperty

To create a DependencyProperty, add a static field of type DepdencyProperty to your type


and call DependencyProperty.Register() to create an instance of a dependency property.
The name of the DependendyProperty must always end with ...Property. This is a naming
convention in WPF.
To make it accessable as a normal .NET property you need to add a property wrapper. This
wrapper does nothing else than internally getting and setting the value by using the GetValue()
and SetValue() Methods inherited from DependencyObject and passing the
DependencyProperty as key.

Important: Do not add any logic to these properties, because they are only called when
you set the property from code. If you set the property from XAML the SetValue() method
is called directly.

If you are using Visual Studio, you can type propdp and hit 2x tab to create a dependency
property.
// Dependency Property
public static readonly DependencyProperty CurrentTimeProperty =
DependencyProperty.Register( "CurrentTime", typeof(DateTime),
typeof(MyClockControl), new
FrameworkPropertyMetadata(DateTime.Now));
// .NET Property wrapper
public DateTime CurrentTime
{

25
get { return (DateTime)GetValue(CurrentTimeProperty); }
set { SetValue(CurrentTimeProperty, value); }

Each DependencyProperty provides callbacks for change notification, value coercion and
validation. These callbacks are registered on the dependency property.
new FrameworkPropertyMetadata( DateTime.Now,
OnCurrentTimePropertyChanged,

OnCoerceCurrentTimeProperty ),
OnValidateCurrentTimeProperty ); 

Value Changed Callback

The change notification callback is a static method, that is called everytime when the value of
the TimeProperty changes. The new value is passed in the EventArgs, the object on which the
value changed is passed as the source.
private static void OnCurrentTimePropertyChanged(DependencyObject
source,
DependencyPropertyChangedEventArgs e)
{
MyClockControl control = source as MyClockControl;
DateTime time = (DateTime)e.NewValue;
// Put some update logic here...

Coerce Value Callback

The coerce callback allows you to adjust the value if its outside the boundaries without throwing
an exception. A good example is a progress bar with a Value set below the Minimum or above
the Maximum. In this case we can coerce the value within the allowed boundaries. In the
following example we limit the time to be in the past.
private static object OnCoerceTimeProperty( DependencyObject sender,
object data )
{
if ((DateTime)data > DateTime.Now )
{
data = DateTime.Now;
}
return data;

Validation Callback

26
In the validate callback you check if the set value is valid. If you return false, an
ArgumentException will be thrown. In our example demand, that the data is an instance of a
DateTime.
private static bool OnValidateTimeProperty(object data)
{
return data is DateTime;

Readonly DependencyProperties

Some dependency property of WPF controls are readonly. They are often used to report the
state of a control, like the IsMouseOver property. Is does not make sense to provide a setter
for this value.
Maybe you ask yourself, why not just use a normal .NET property? One important reason is that
you cannot set triggers on normal .NET propeties.

Creating a read only property is similar to creating a regular DependencyProperty. Instead of


calling DependencyProperty.Register() you call
DependencyProperty.RegisterReadonly(). This returns you a
DependencyPropertyKey. This key should be stored in a private or protected static readonly
field of your class. The key gives you access to set the value from within your class and use it like
a normal dependency property.
Second thing to do is registering a public dependency property that is assigned to
DependencyPropertyKey.DependencyProperty. This property is the readonly property
that can be accessed from external.
// Register the private key to set the value
private static readonly DependencyPropertyKey IsMouseOverPropertyKey =
DependencyProperty.RegisterReadOnly("IsMouseOver",
typeof(bool), typeof(MyClass),
new FrameworkPropertyMetadata(false));
// Register the public property to get the value
public static readonly DependencyProperty IsMouseoverProperty =
IsMouseOverPropertyKey.DependencyProperty;
// .NET Property wrapper
public int IsMouseOver
{
get { return (bool)GetValue(IsMouseoverProperty); }
private set { SetValue(IsMouseOverPropertyKey, value); }

Attached Properties

Attached properties are a special kind of DependencyProperties. They allow you to attach a
value to an object that does not know anything about this value.

27
A good example for this concept are layout panels. Each layout panel needs different data to
align its child elements. The Canvas needs Top and Left, The DockPanel needs Dock, etc. Since
you can write your own layout panel, the list is infinite. So you see, it's not possible to have all
those properties on all WPF controls.
The solution are attached properties. They are defined by the control that needs the data from
another control in a specific context. For example an element that is aligned by a parent layout
panel.

To set the value of an attached property, add an attribute in XAML with a prefix of the element
that provides the attached property. To set the the Canvas.Top and Canvas.Left property of a
button aligned within a Canvas panel, you write it like this:
<Canvas>
<Button Canvas.Top="20" Canvas.Left="20" Content="Click me!"/>
</Canvas>
public static readonly DependencyProperty TopProperty =
DependencyProperty.RegisterAttached("Top",
typeof(double), typeof(Canvas),
new FrameworkPropertyMetadata(0d,
FrameworkPropertyMetadataOptions.Inherits));
public static void SetTop(UIElement element, double value)
{
element.SetValue(TopProperty, value);
}
public static double GetTop(UIElement element)
{
return (double)element.GetValue(TopProperty);

Listen to dependency property changes

If you want to listen to changes of a dependency property, you can subclass the type that
defines the property and override the property metadata and pass an PropertyChangedCallback.
But an much easier way is to get the DependencyPropertyDescriptor and hookup a
callback by calling AddValueChanged()
 

DependencyPropertyDescriptor textDescr = DependencyPropertyDescriptor.


FromProperty(TextBox.TextProperty, typeof(TextBox));
if (textDescr!= null)
{
textDescr.AddValueChanged(myTextBox, delegate
{
// Add your propery changed logic here...
});

28
}  

How to clear a local value

Because null is also a valid local value, there is the constant


DependencyProperty.UnsetValue that describes an unset value.
button1.ClearValue( Button.ContentProperty );

Routed Events

Routed events are events which navigate up or down the visual tree acording to their
RoutingStrategy. The routing strategy can be bubble, tunnel or direct. You can hook up
event handlers on the element that raises the event or also on other elements above or below it
by using the attached event syntax: Button.Click="Button_Click".
Routed events normally appear as pair. The first is a tunneling event called
PreviewMouseDown and the second is the bubbling called MouseDown. They don't stop
routing if the reach an event handler. To stop routing then you have to set e.Handled =
true;
 Tunneling The event is raised on the root element and navigates down to the visual tree
until it reaches the source element or until the tunneling is stopped by marking the
event as handeld. By naming convention it is called Preview... and appears before
corresponding bubbling event.
 Bubbling The event is raised on the source element and navigates up to the visual tree
until it reaches the root element or until the bubbling is stopped by marking the event as
handled. The bubbling event is raised after the tunneling event.

 Direct The event is raised on the source element and must be handled on the source
element itself. This behavior is the same as normal .NET events.

How to Create a Custom Routed Event

// Register the routed event

29
public static readonly RoutedEvent SelectedEvent =
EventManager.RegisterRoutedEvent( "Selected",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(MyCustomControl));
 

// .NET wrapper
public event RoutedEventHandler Selected
{
add { AddHandler(SelectedEvent, value); }
remove { RemoveHandler(SelectedEvent, value); }
}
// Raise the routed event "selected"
RaiseEvent(new RoutedEventArgs(MyCustomControl.SelectedEvent)); 

30
Day 3 - Layout and Controls

Introduction to WPF Layout


Why layout is so important

Best Practices

Vertical and Horizontal Alignment

Margin and Padding

Width and Height

Content Overflow Handling

Why layout is so important

Layout of controls is critical to an applications usability. Arranging controls based on fixed pixel
coordinates may work for an limited enviroment, but as soon as you want to use it on different
screen resolutions or with different font sizes it will fail. WPF provides a rich set built-in layout
panels that help you to avoid the common pitfalls.

These are the five most popular layout panels of WPF:

 Grid Panel
 Stack Panel
 Dock Panel
 Wrap Panel
 Canvas Panel

Best Practices

 Avoid fixed positions - use the Alignment properties in combination with Margin to
position elements in a panel
 Avoid fixed sizes - set the Width and Height of elements to Auto whenever possible.
 Don't abuse the canvas panel to layout elements. Use it only for vector graphics.
 Use a StackPanel to layout buttons of a dialog
 Use a GridPanel to layout a static data entry form. Create a Auto sized column for the
labels and a Star sized column for the TextBoxes.

31
 Use an ItemControl with a grid panel in a DataTemplate to layout dynamic key value lists.
Use the SharedSize feature to synchronize the label widths.

Vertical and Horizontal Alignment

Use the VerticalAlignment and HorizontalAlignmant properties to dock the controls


to one or multiple sides of the panel. The following illustrations show how the sizing behaves
with the different combinations.

Margin and Padding

The Margin and Padding properties can be used to reserve some space around of within the
control.

 The Margin is the extra space around the control.


 The Padding is extra space inside the control.
 The Padding of an outer control is the Margin of an inner control.

Height and Width

Alltough its not a recommended way, all controls provide a Height and Width property to give
an element a fixed size. A better way is to use the MinHeight, MaxHeight, MinWidth and
MaxWidth properties to define a acceptable range.
If you set the width or height to Auto the control sizes itself to the size of the content.

Overflow Handling

32
Clipping

Layout panels typically clip those parts of child elements that overlap the border of the panel.
This behavior can be controlled by setting the ClipToBounds property to true or false.

Scrolling

When the content is too big to fit the available size, you can wrap it into a ScrollViewer. The
ScrollViewer uses two scroll bars to choose the visible area.
The visibility of the scrollbars can be controlled by the vertical and horizontal
ScrollbarVisibility properties.
<ScrollViewer>
<StackPanel>
<Button Content="First Item" />
<Button Content="Second Item" />
<Button Content="Third Item" />
</StackPanel>
</ScrollViewer>

Related Articles

MSDN - The Layout System

Grid Panel
Introduction

How to define rows and columns

How to add controls to the grid

Resize columns or rows

How to share the width of a column over multiple grids

Using GridLenghts from code

Introduction

33
The grid is a layout panel that arranges its child controls in a tabular structure of rows and
columns. Its functionality is similar to the HTML table but more flexible. A cell can contain
multiple controls, they can span over multiple cells and even overlap themselves.

The resize behaviour of the controls is defined by the HorizontalAlignment and


VerticalAlignment properties who define the anchors. The distance between the anchor
and the grid line is specified by the margin of the control

Define Rows and Columns

The grid has one row and column by default. To create additional rows and columns, you have
to add RowDefinition items to the RowDefinitions collection and ColumnDefinition
items to the ColumnDefinitions collection. The following example shows a grid with three
rows and two columns.
The size can be specified as an absolute amount of logical units, as a percentage value or
automatically.

Fixed size of logical units (1/96 inch)

Takes as much space as needed by the contained control

Takes as much space as available, percentally divided over all star-sized columns.
Star-sizes are like percentages, except that the sum of all star columns does not
have to be 100%. Remember that star-sizing does not work if the grid size is
calculated based on its content.

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />

34
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
</Grid>

How to add controls to the grid

To add controls to the grid layout panel just put the declaration between the opening and
closing tags of the Grid. Keep in mind that the row- and columndefinitions must precced any
definition of child controls.
The grid layout panel provides the two attached properties Grid.Column and Grid.Row to
define the location of the control.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Name:"/>
<Label Grid.Row="1" Grid.Column="0" Content="E-Mail:"/>
<Label Grid.Row="2" Grid.Column="0" Content="Comment:"/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="3" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="3" />
<TextBox Grid.Column="1" Grid.Row="2" Margin="3" />
<Button Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right"
MinWidth="80" Margin="3" Content="Send" />
</Grid>

Resizable columns or rows

35
WPF provides a control called the GridSplitter. This control is added like any other control
to a cell of the grid. The special thing is that is grabs itself the nearest gridline to change its
width or height when you drag this control around.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Left" Grid.Column="0" />
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Grid.Column="1" ResizeBehavior="PreviousAndNext"
Width="5" Background="#FFBCBCBC"/>
<Label Content="Right" Grid.Column="2" />
</Grid>
The best way to align a grid splitter is to place it in its own auto-sized column. Doing it this way
prevents overlapping to adjacent cells. To ensure that the grid splitter changes the size of the
previous and next cell you have to set the ResizeBehavior to PreviousAndNext.
The splitter normally recognizes the resize direction according to the ratio between its height
and width. But if you like you can also manually set the ResizeDirection to Columns or
Rows.
<GridSplitter ResizeDirection="Columns"/>

How to share the width of a column over multiple grids

The shared size feature of the grid layout allows it to synchronize the width of columns over
multiple grids. The feature is very useful if you want to realize a multi-column listview by using a
grid as layout panel within the data template. Because each item contains its own grid, the
columns will not have the same width.

By setting the attached property Grid.IsSharedSizeScope to true on a parent element


you define a scope within the column-widths are shared.

36
To synchronize the width of two columndefinitions, set the SharedSizeGroup to the same
name.
<ItemsControl Grid.IsSharedSizeScope="True" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="FirstColumn"
Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Key}" TextWrapping="Wrap"/>
<TextBlock Text="{Binding Path=Value}" Grid.Column="1"
TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl> 

Useful Hints

Columns and rows that participate in size-sharing do not respect Star sizing. In the size-sharing
scenario, Star sizing is treated as Auto. Since TextWrapping on TextBlocks within an SharedSize
column does not work you can exclude your last column from the shared size. This often helps
to resolve the problem.

Using GridLenghts from code

If you want to add columns or rows by code, you can use the GridLength class to define the
differenz types of sizes.

GridLength.Auto

Grid grid = new Grid();


 

ColumnDefinition col1 = new ColumnDefinition();


col1.Width = GridLength.Auto;
ColumnDefinition col2 = new ColumnDefinition();
col2.Width = new GridLength(1,GridUnitType.Star);
 

grid.ColumnDefinitions.Add(col1);
grid.ColumnDefinitions.Add(col2);

37
More on this topic

How to create a resizable column

WPF StackPanel

Introduction

The StackPanel in WPF is a simple and useful layout panel. It stacks its child elements below
or beside each other, dependening on its orientation. This is very useful to create any kinds of
lists. All WPF ItemsControls like ComboBox, ListBox or Menu use a StackPanel as their
internal layout panel.
<StackPanel>
<TextBlock Margin="10" FontSize="20">How do you like your coffee?
</TextBlock>
<Button Margin="10">Black</Button>
<Button Margin="10">With milk</Button>
<Button Margin="10">Latte machiato</Button>
<Button Margin="10">Chappuchino</Button>
</StackPanel> 

Stack Items horizontally

A good example for a horizontal stack panel are the "OK" and "Cancel" buttons of a dialog
window. Because the size of the text can change if the user changes the font-size or switches the
language we should avoid fixed sized buttons. The stack panel aligns the two buttons
depending on their desired size. If they need more space they will get it automatically. Never
mess again with too small or too large buttons.

38
<StackPanel Margin="8" Orientation="Horizontal">
<Button MinWidth="93">OK</Button>
<Button MinWidth="93" Margin="10,0,0,0">Cancel</Button>
</StackPanel> 

Built-in Controls of WPF


The WPF framework provides a rich set of built-in controls. The controls can be devided in the
following categories.

Fixed

Auto

Star (*)

Auto sized

Star sized

new GridLength(1,GridUnitType.Star)

39
Fixed size

new GridLength(100,GridUnitType.Pixel)

Third Party Controls

DataGrid

ItemsControl

LivePreview ComboBox

Dialogs

Slider

Popup

RadioButton

ToolTips

TextBox

Menus

Expander

PasswordBox

ContextMenu

Calendar

ListBox

ListView

Window

40
Day 4 - DataBinding and UI
Architecture

DataBinding in WPF

Introduction

WPF provides a simple and powerful way to auto-update data between the business model
and the user interface. This mechanism is called DataBinding. Everytime when the data of your
business model changes, it automatically reflects the updates to the user interface and vice
versa. This is the preferred method in WPF to bring data to the user interface.

Databinding can be unidirectional (source -> target or target <- source), or bidirectional
(source <-> target).

The source of a databinding can be a normal .NET property or a DependencyProperty. The


target property of the binding must be a DependencyProperty.

To make the databinding properly work, both sides of a binding must provide a change
notification that tells the binding when to update the target value. On normal .NET properties
this is done by raising the PropertyChanged event of the INotifyPropertyChanged
interface. On DependencyProperties it is done by the PropertyChanged callback of the property
metadata

Databinding is typically done in XAML by using the {Binding} markup extension. The
following example shows a simple binding between the text of a TextBox and a Label that
reflects the typed value:

<StackPanel>

<TextBox x:Name="txtInput" />

<Label Content="{Binding Text, ElementName=txtInput,

41
UpdateSourceTrigger=PropertyChanged}" />

</StackPanel> 

DataContext

Every WPF control derived from FrameworkElement has a DataContext property. This
property is meant to be set to the data object it visualizes. If you don't explicity define a
source of a binding, it takes the data context by default.

The DataContext property inherits its value to child elements. So you can set the
DataContext on a superior layout container and its value is inherited to all child elements. This
is very useful if you want to build a form that is bound to multiple properties of the same data
object.

<StackPanel DataContext="{StaticResource myCustomer}">

<TextBox Text="{Binding FirstName}"/>

<TextBox Text="{Binding LastName}"/>

<TextBox Text="{Binding Street}"/>

<TextBox Text="{Binding City}"/>

</StackPanel> 

ValueConverters

If you want to bind two properties of different types together, you need to use a
ValueConverter. A ValueConverter converts the value from a source type to a target type and
back. WPF already includes some value converters but in most cases you will need to write your
own by implementing the IValueConverter interface.

A typical example is to bind a boolean member to the Visibility property. Since the visibility
is an enum value that can be Visible, Collapsed or Hidden, you need a value converter.

<StackPanel>

<StackPanel.Resources>

<BooleanToVisibilityConverter x:Key="boolToVis" />

</StackPanel.Resources>

<CheckBox x:Name="chkShowDetails" Content="Show Details" />

<StackPanel x:Name="detailsPanel"

Visibility="{Binding IsChecked,
ElementName=chkShowDetails,

42
Converter={StaticResource boolToVis}}">

</StackPanel>

</StackPanel> 

The following example shows a simple converter that converts a boolen to a visibility property.
Note that such a converter is already part of the .NET framework.

public class BooleanToVisibilityConverter : IValueConverter

public object Convert(object value, Type targetType, object


parameter,

CultureInfo culture)

if (value is Boolean)

return ((bool)value) ? Visibility.Visible :


Visibility.Collapsed;

return value;

public object ConvertBack(object value, Type targetType, object


parameter,

CultureInfo culture)

throw new NotImplementedException();

Tip: you can derive your value converter from MarkupExtension and return its own instance
in the ProvideValue override. So you can use it directly without referencing it from the
resources.

How to Navigate, Group, Sort and Filter Data in WPF


43
What is a CollectionView?

Navigation

Filtering

Sorting

Grouping

How to create a CollectionView in XAML

What is a CollectionView?

WPF has a powerful data binding infrastructure. It allows you to bind almost any kind of
collection directly to a view. But when it comes to sorting, filtering and grouping the support of
the collections is rare. That's the point where the CollectionView comes into play. A collection
view is a wrapper around a collection that provides the following additional features:

 Navigation
 Sorting
 Filtering
 Grouping

How to Create and Use a CollectionView

The following example shows you how to create a collection view and bind it to a ListBox

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<ListBox ItemsSource={Binding Customers} />

</Window>

public class CustomerView

public CustomerView()

DataContext = new CustomerViewModel();

44
public class CustomerViewModel

private ICollectionView _customerView;

public ICollectionView Customers

get { return _customerView; }

public CustomerViewModel()

IList<Customer> customers = GetCustomers();

_customerView = CollectionViewSource.GetDefaultView(customers);

Navigation

The collection view adds support for selection tracking. If you set the property
IsSynchronizedWithCurrentItem to True on the view that the collection is bound to, it
automatically synchronizes the current item of the CollectionView and the View.

<ListBox ItemsSource="{Binding Customers}"


IsSynchronizedWithCurrentItem="True" /> 

If you are using a MVVM (Model-View-ViewModel) pattern, you don't have to extra wire-up the
SelectedItem of the control, because it's implicity available over the CollectionView.

IList<Customer> customers = GetCustomers();

ICollectionView _customerView =
CollectionViewSource.GetDefaultView(customers);

_customerView.CurrentChanged = CustomerSelectionChanged;

private CustomerSelectionChanged(object sender, EventArgs e)

// React to the changed selection

45
You can also manually control the selection from the ViewModel by calling the
MoveCurrentToFirst() or MoveCurrentToLast() methods on the CollectionView.

Filtering

To filter a collection view you can define a callback method that determines if the item should
be part of the view or not. That method should have the following signature: bool
Filter(object item). Now set the delegate of that method to the Filter property of the
CollectionView and you're done.

ICollectionView _customerView =
CollectionViewSource.GetDefaultView(customers);

_customerView.Filter = CustomerFilter

private bool CustomerFilter(object item)

Customer customer = item as Customer;

return customer.Name.Contains( _filterString );

Refresh the filter

If you change the filter criteria and you want to refresh the view, you have to call Refresh() on
the collection view

public string FilterString

get { return _filterString; }

set

_filterString = value;

NotifyPropertyChanged("FilterString");

_customerView.Refresh();

Sorting

46
Sorting data ascending or descending by one or multiple criterias is a common requirement for
viewing data. The collection view makes it so easy to achieve this goal. Just add as many
SortDescriptions as you like to the CollectionView

ICollectionView _customerView =
CollectionViewSource.GetDefaultView(customers);

_customerView.SortDescriptions.Add(

new SortDescription("LastName",
ListSortDirection.Ascending );

_customerView.SortDescriptions.Add(

new SortDescription("FirstName",
ListSortDirection.Ascending );

Fast Sorting

The sorting technique explained above is really simple, but also quite slow for a large amount of
data, because it internally uses reflection. But there is an alternative, more performant way to do
sorting by providing a custom sorter.

ListCollectionView _customerView =
CollectionViewSource.GetDefaultView(customers);

as ListCollectionView;

_customerView.CustomSort = new CustomerSorter();

public class CustomerSorter : IComparer

public int Compare(object x, object y)

Customer custX = x as Customer;

Customer custY = y as Customer;

return custX.Name.CompareTo(custY.Name);

Grouping

Grouping is another powerful feature of the CollectionView. You can define as many groups as
you like by adding GroupDescriptions to the collection view.

47
Note: Grouping disables virtualization! This can bring huge performance issues on large data
sets. So be careful when using it.

ICollectionView _customerView =
CollectionViewSource.GetDefaultView(customers);

_customerView.GroupDescriptions.Add(new
PropertyGroupDescription("Country")); 

To make the grouping visible in the view you have to define a special GroupStyle on the view.

<ListBox ItemsSource="{Binding Customers}">

<ListBox.GroupStyle>

<GroupStyle.HeaderTemplate>

<DataTemplate>

<TextBlock Text="{Binding Path=Name}"/>

</DataTemplate>

</GroupStyle.HeaderTemplate>

</ListBox.GroupStyle>

</ListBox> 

How to create a CollectionView in XAML

It's also possible to create a CollectionView completely in XAML

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Window.Resources>

<CollectionViewSource Source="{Binding}" x:Key="customerView">

<CollectionViewSource.GroupDescriptions>

<PropertyGroupDescription PropertyName="Country" />

</CollectionViewSource.GroupDescriptions>

</CollectionViewSource>

</Window.Resources>

<ListBox ItemSource="{Binding Source={StaticResource


customerView}}" />

48
</Window> 

Model-View-ViewModel Pattern
This article is not yet finished...

Introduction

In conventional user interface programming techniques (as we know it from WinForms) we


usually add event handlers to controls and implement the logic of a view in the code-behind. It
is the most simple and fastest way to get a functional user interface. But this approach has some
disadvantages:

 Presentation and logic are tightly coupled


 Replacing a control on the view often requires code changes
 You cannot have more than one view sharing the same logic
 To test the user interface logic you need to do complex UI testing.

Introducing the Model-View-ViewModel pattern

WPF brings up a very flexible and powerful databinding framework and this favors a new pattern
how to bind presentation and logic together.

The idea of the MVVM pattern is the following:

 A model that contains the data


 A passive view-model that collects and prepares the data so that is can easy be
consumed by the view.
 And a view that is defined in XAML and should not have any logic in the code-behind. It
binds to the view-model by only using data binding.

49
Model-View-ViewModel Example

Model

ViewModel

View

Data Validation in WPF


What we want to do is a simple entry form for an e-mail address. If the user enters an invalid e-
mail address, the border of the textbox gets red and the tooltip is showing the reason.

Implementing a ValidationRule (.NET 3.0 style)

50
In this example I am implementing an generic validation rule that takes a regular expression as
validation rule. If the expression matches the data is treated as valid.

 /// <summary>

/// Validates a text against a regular expression

/// </summary>

public class RegexValidationRule : ValidationRule

private string _pattern;

private Regex _regex;

public string Pattern

get { return _pattern; }

set

_pattern = value;

_regex = new Regex(_pattern, RegexOptions.IgnoreCase);

public RegexValidationRule()

public override ValidationResult Validate(object value, CultureInfo


ultureInfo)

if (value == null || !_regex.Match(value.ToString()).Success)

return new ValidationResult(false, "The value is not a


valid e-mail address");

51
else

return new ValidationResult(true, null);

First thing I need to do is place a regular expression pattern as string to the windows resources

<Window.Resources>

<sys:String x:Key="emailRegex">^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@

[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]

*[a-zA-Z]$</sys:String>

</Window.Resources> 

Build a converter to convert ValidationErrors to a multi-line string

The following converter combines a list of ValidationErrors into a string. This makes the
binding much easier. In many samples on the web you see the following binding expression:

{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors)


[0].ErrorContent}

This expression works if there is one validation error. But if you don't have any validation errors
the data binding fails. This slows down your application and causes the following message in
your debug window:

System.Windows.Data Error: 16 : Cannot get ‘Item[]‘ value (type


‘ValidationError’) from ‘(Validation.Errors)’ (type
‘ReadOnlyObservableCollection`1′). BindingExpression:Path=(0).
[0].ErrorContent; DataItem=’TextBox’...

The converter is both, a value converter and a markup extension. This allows you to create and
use it at the same time.

[ValueConversion(typeof(ReadOnlyObservableCollection<ValidationError>),
typeof(string))]

public class ValidationErrorsToStringConverter : MarkupExtension,


IValueConverter

52
public override object ProvideValue(IServiceProvider
serviceProvider)

return new ValidationErrorsToStringConverter();

public object Convert(object value, Type targetType, object


parameter,

CultureInfo culture)

ReadOnlyObservableCollection<ValidationError> errors =

value as ReadOnlyObservableCollection<ValidationError>;

if (errors == null)

return string.Empty;

return string.Join("\n", (from e in errors

select e.ErrorContent as
string).ToArray());

public object ConvertBack(object value, Type targetType, object


parameter,

CultureInfo culture)

throw new NotImplementedException();

Create an ErrorTemplate for the TextBox

53
Next thing is to create an error template for the text box.

<ControlTemplate x:Key="TextBoxErrorTemplate" TargetType="Control">

<Grid ClipToBounds="False" >

<Image HorizontalAlignment="Right" VerticalAlignment="Top"

Width="16" Height="16" Margin="0,-8,-8,0"

Source="{StaticResource ErrorImage}"

ToolTip="{Binding ElementName=adornedElement,

Path=AdornedElement.(Validation.Errors),

Converter={k:ValidationErrorsToStringConverter}}"/>

<Border BorderBrush="Red" BorderThickness="1" Margin="-1">

<AdornedElementPlaceholder Name="adornedElement" />

</Border>

</Grid>

</ControlTemplate>

The ValidationRule and the ErrorTemplate in Action

Finally we can add the validation rule to our binding expression that binds the Text property of
a textbox to a EMail property of our business object.

<TextBox x:Name="txtEMail" Template={StaticResource


TextBoxErrorTemplate}>

<TextBox.Text>

<Binding Path="EMail" UpdateSourceTrigger="PropertyChanged" >

<Binding.ValidationRules>

<local:RegexValidationRule Pattern="{StaticResource
emailRegex}"/>

</Binding.ValidationRules>

</Binding>

</TextBox.Text>

</TextBox>

How to manually force a Validation

54
If you want to force a data validation you can manually call UpdateSource() on the binding
expression. A useful scenario could be to validate on LostFocus() even when the value is
empty or to initially mark all required fields. In this case you cann call ForceValidation() in
the Loaded event of the window. That is the time, when the databinding is established.

The following code shows how to get the binding expression from a property of a control.

private void ForceValidation()

txtName.GetBindingExpression(TextBox.TextProperty).UpdateSource();

ValueConverters

Introduction

If you want to databind two properties that have incompatible types, you need a piece of code
in between, that converts the value from source to target type and back. This piece of code is
called ValueConverter. A value converter is a class, that implements the simple interface
IValueConverter with the two methods object Convert(object value) and object
ConvertBack(object value).

How to implement a ValueConverter

WPF already provides a few value converts, but you will soon need to implement your own
converts. To do this, add a class to your project and call it
[SourceType]To[TargetType]Converter. This is a common naming for value converters.
Make it public and implement the IValueConverter interface. That's all you need to do.

public class BoolToVisibilityConverter : IValueConverter

public object Convert(object value, Type targetType,

object parameter, CultureInfo culture)

55
// Do the conversion from bool to visibility

public object ConvertBack(object value, Type targetType,

object parameter, CultureInfo culture)

// Do the conversion from visibility to bool

How to use a ValueConverter in XAML

First thing you need to do is to map the namespace of your converter to a XAML namespace.
Then you can create an instance of a value converter in the resources of the view and give it a
name. Then you can reference it by using {StaticResource}

<Window x:Class="VirtualControlDemo.Window1"

...

xmlns:l="clr-namespace:VirtualControlDemo"

...>

<Window.Resources>

<l:BoolToVisibilityConverter x:Key="converter" />

</Window.Resources>

<Grid>

<Button Visibility="{Binding HasFunction,

Converter={StaticResource converter}}" />

</Grid>

</Window> 

Simplify the usage of ValueConvers

If you want to use a normal ValueConverter in XAML, you have to add an instance of it to the
resources and reference it by using a key. This is cumbersome, because and the key is typically
just the name of the converter.

56
A simple and cool trick is to derive value converters from MarkupExtension. This way you can
create and use it in the binding like this: Text={Binding Time,
Converter={x:MyConverter}}, and that is quite cool!

public abstract class BaseConverter : MarkupExtension

public override object ProvideValue(IServiceProvider


serviceProvider)

return this;

StringFormat Converter

The StringFormatConverter is a useful converter to control the format of an implicit string


conversion of an object (e.g. if you bind a DateTime to a TextBlock ).

[ValueConversion(typeof(object), typeof(string))]

public class StringFormatConverter : BaseConverter, IValueConverter

public object Convert(object value, Type targetType, object


parameter,

System.Globalization.CultureInfo culture)

string format = parameter as string;

if (!string.IsNullOrEmpty(format))

return string.Format(culture, format, value);

else

return value.ToString();

57
public object ConvertBack(object value, Type targetType, object
parameter,

System.Globalization.CultureInfo culture)

return null;

Behaviors

A simple Border can be dragged by mouse - because of an attached drag behavior.

Introduction

Behaviors are a new concept, introduced with Expression Blend in Version 3, to encapsulate
pieces of functionality into a reusable component. These components than can be attached
to controls to give them an additional behavior.

The ideas behind behaviors are to give the interaction designer more flexibility to design
complex user interactions without writing any code.

Example of a behaviors are drag&drop, input validation, pan and zoom, re-position of elements,
etc... The list of possible behaviors is very long.

Imaging an application that has a list of customers and the user can add some of them to
subscriber lists. This interaction can be designed by providing an "Add" button next to each
subscriber list. But if the interaction designer wants to add drag&drop functionality, he needs to
discuss it with the developer and wait until the implementation is done. With behaviors he just
drags a drag and drop behavior on each list and we are done.

How to use behaviors in Expression Blend 3

58
Using behaviors in Expression Blend is as simple as adding an element to the design surface. In
the asset library you find a new secion called "Behaviors". It lists all behaviors available within
your project. Just grab one of these and drag it onto the element you want to add this behavior
and thats it.

The behavior appears as an child element in the visual tree. By clicking on it you can configure
the properties of the behavior.

How does it work

To add behaviors to an element you need some kind of an extension point. This is an attached
property called Interaction.Behaviors.

This attached property holds the list of behaviors for that element and pass a reference to the
element into the behavior. The behavior than can register itself to events and property changes
and so extend the functionality of the element.

59
The idea is simple, but very clever. They don't need any new infrastructure, they just reuse the
existing one.

<Border Background="LightBlue" >

<e:Interaction.Behaviors>

<b:DragBehavior/>

</e:Interaction.Behaviors>

<TextBlock Text="Drag me around!" />

</Border> 

How to implement your own behavior

The following example shows the implementation of the drag behavior we used above. Just
derive from Behavior<T;gt; and override the OnAttached() method.

public class DragBehavior : Behavior<UIElement>

private Point elementStartPosition;

private Point mouseStartPosition;

private TranslateTransform transform = new TranslateTransform();

protected override void OnAttached()

Window parent = Application.Current.MainWindow;

AssociatedObject.RenderTransform = transform;

AssociatedObject.MouseLeftButtonDown += (sender, e) =>

elementStartPosition = AssociatedObject.TranslatePoint( new


Point(), parent );

mouseStartPosition = e.GetPosition(parent);

AssociatedObject.CaptureMouse();

};

AssociatedObject.MouseLeftButtonUp += (sender, e) =>

60
AssociatedObject.ReleaseMouseCapture();

};

AssociatedObject.MouseMove += (sender, e) =>

Vector diff = e.GetPosition( parent ) - mouseStartPosition;

if (AssociatedObject.IsMouseCaptured)

transform.X = diff.X;

transform.Y = diff.Y;

};

List of some popular behaviors

Since its so cool and easy to create your own pice of interactivity, I am sure that we will find
hunderts of behaviors available soon. I tried to make a list of some popular ones.

 Zoom Behavior
 Glass Behavior
 Shake Behavior
 Transparency Behavior

61
Day 5 - Templates and Styles

User Experience Design Process


User Experience becomes a Key Success Factor

In the past, we focused mainly on building products that fulfilled the functional requirements of
the user. User experience was often considered late in the development process. But today the
customer demands more than just a working product. Providing the right features is still the
prerequisite for a good product, but to turn it into something extraordinary you need to provide
a good user experience!

Providing a rich user experience is not a thing of fortune. It needs to be planed, designed and
integrated into the development of a product. Designing a rich user experience is not only
about make up your user interface by some graphics and gradients - its a much broader
concept. Its about creating an emotional connection between the user and your software. It
makes the user feel good and so he likes to continue using the software.

New Tools for Designers

Microsoft recognized, give development teams the power to create rich user experiences it
needs a lot more graphical tool support than VisualStudio can provide today. So they decided to
create a new tool suite - made for designers.

This tool suite is called Microsoft Expression. It consists of the four products:

 Expression Blend is built to create user interfaces in WPF and Silverlight. It builds the
bridge between designer and developers. It can open VisualStudio solutions

62
 Expression Design is a leightweight version of Adobe Illustrator to create and edit
vector graphics.
 Expression Media is built to encode, cut and enrich video files and optimize them for
silverlight streaming
 Expression Web is Microsoft next generation of HTML and Javascript editor. Its the
replacement for Frontpage.

Together they are a powerful package. The following illustration shows a sample workflow of
integrating a vector image that is created by a graphics designer in Adobe Illustrator into a WPF
project that is part of a VisualStudio solution.

Development Workflow of a WPF Project

Developing a WPF application with a rich user experience requires a lot more skills than just a
requirements analyst that defines a list of use cases and developer that implements the
software. You have to find out what the user really needs. This can be done by following a user
centered approach.

63
1. Elicit Requirements

Like in any kind of software projects its important to know and focus the target of your
development. You should talk to stakeholders and users to find out the real needs. These needs
should be refined to features and expressed in use cases (abstract) or user scenarios
(illustrative). Priorize the tasks by risk and importance and work iteratively. This work is done by
the role of the requirements engineer.

2. Create and Validate UI Prototype

Creating a user interface prototype is an important step to share ideas between users and
engineers to create a common understanding of the interaction design. This task is typically
done by an interaction designer. It's helpful to only sketch the user interface in a rough way to
prevent early discussions about design details. There are multiple techniques and tools to do
this. Some of them are:

 Paper prototype
Use paper and pencil to draw rough sketches of your user interface. No tools and
infrastructure is needed. Everyone can just scribble thier ideas on the paper.
 Wireframes
Wireframes are often used to sketch the layout of a page. It's called wireframes because
you just draw the outlines of controls and images. This can be done with tools like
PowerPoint or Visio
 Expression Blend 3 - Sketch Flow Sketch flow is a new cool feature to create interactive
prototypes directly in WPF. You can use the integrated "wiggly style" to make it look

64
sketchy. The prototype can be run in a standalone player that has an integrated feedback
mechanism.
 Interactive Prototype The most expensive and real approach is to create an (reusable)
interactive prototype that works as the real application but with dummy data.

It is strongly recommended to test your UI prototype on real users. This helps you to find out
and address design problems early in the development process. The following techniques are
very popular to evaluate UI prototypes:

 Walktrough
A walktrough is usually done early in a project with wireframes or paper prototypes. The
user gets a task to solve and he controlls the prototype by touching on the paper. The
test leader than presents a new paper showing the state after the interaction.
 Usability Lab
To do a usability lab, you need a computer with a screen capture software and a camera.
The proband gets an task to do and the requirements and interaction engineer watch
him doing this. They should not talk to him to find out where he gets stuck and why.

3. Implement Business Logic and Raw User Interface


4. Integrate Graphical Design
5. Test software
Roles

Buliding a modern user interface with a rich user experience requires additional skills from your
development team. These skills are described as roles that can be distributed among peoples in
your development team.

 Developer
The developer is responsible to implement the functionality of the application. He
creates the data model, implements the business logic and wires all up to a simple view.
 Graphical Designer
The graphical designer is responsible to create a graphical concept and build graphical
assets like icons,logos, 3D models or color schemes. If the graphical designer is familiar
with Microsoft Expression tools he directly creates styles and control templates.
 Interaction Designer
The interaction designer is responsible for the content and the flow of a user interface.
He creates wireframes or UI sketches to share its ideas with the team or customer. He
should validate his work by doing walktroughs or storyboards.
 Integrator
The integrator is the artist between the designer and the developer world. He takes the
assets of the graphical designer and integrates them into the raw user interface of the

65
developer. This role needs a rare set of skills and so it's often hard to find the right
person for it.

More Infos

The New Iteration - Microsoft Paper about the Designer/Developer collaboration

Introduction to Styles in WPF


Introduction

Imagine you want to create an application with a unique design. All your buttons should have an
orange background and an italic font. Doing this the conventional way means that you have to
set the Background and the FontStyle property on every single button.

<StackPanel Orientation="Horizontal" VerticalAlignment="Top">

<Button Background="Orange" FontStyle="Italic"

Padding="8,4" Margin="4">Styles</Button>

<Button Background="Orange" FontStyle="Italic"

Padding="8,4" Margin="4">are</Button>

<Button Background="Orange" FontStyle="Italic"

Padding="8,4" Margin="4">cool</Button>

</StackPanel> 

This code is neither maintainable nor short and clear. The solution for this problem are styles.

The concept of styles let you remove all properties values from the individual user interface
elements and combine them into a style. A style consists of a list of setters. If you apply this style
to an element it sets all properties with the specified values. The idea is quite similar to
Cascading Styles Sheets (CSS) that we know from web development.

To make the style accessible to your controls you need to add it to the resources. Any control in
WPF have a list of resources that is inherited to all controls beneath the visual tree. That's the
reason why we need to specify a x:Key="myStyle" property that defines a unique resource
identifier.

To apply the style to a control we set the Style property to our style. To get it from the
resources we use the {StaticResource [resourceKey]} markup extension.

<Window>

66
<Window.Resources>

<Style x:Key="myStyle" TargetType="Button">

<Setter Property="Background" Value="Orange" />

<Setter Property="FontStyle" Value="Italic" />

<Setter Property="Padding" Value="8,4" />

<Setter Property="Margin" Value="4" />

</Style>

</Window.Resources>

<StackPanel Orientation="Horizontal" VerticalAlignment="Top">

<Button Style="{StaticResource myStyle}">Styles</Button>

<Button Style="{StaticResource myStyle}">are</Button>

<Button Style="{StaticResource myStyle}">cool</Button>

</StackPanel>

</Window> 

What we have achieved now is

 A maintainable code base


 Removed the redundancy
 Change the appearance of a set of controls from a single point
 Possibility to swap the styles at runtime.

Style inheritance

A style in WPF can base on another style. This allows you to specify a base style that sets
common properties and derive from it for specialized controls.

<Style x:Key="baseStyle">

<Setter Property="FontSize" Value="12" />

<Setter Property="Background" Value="Orange" />

</Style>

<Style x:Key="boldStyle" BasedOn="{StaticResource baseStyle}">

<Setter Property="FontWeight" Value="Bold" />

67
</Style> 

Control Templates
Introduction

Controls in WPF are separated into logic, that defines the states, events and properties and
template, that defines the visual appearance of the control. The wireup between the logic and
the template is done by DataBinding.

Each control has a default template. This gives the control a basic appearance. The default
template is typically shipped together with the control and available for all common windows
themes. It is by convention wrapped into a style, that is identified by value of the
DefaultStyleKey property that every control has.

The template is defined by a dependency property called Template. By setting this property to
another instance of a control template, you can completely replace the appearance (visual tree)
of a control.

The control template is often included in a style that contains other property settings. The
following code sample shows a simple control template for a button with an ellipse shape.

<Style x:Key="DialogButtonStyle" TargetType="Button">

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="{x:Type Button}">

68
<Grid>

<Ellipse Fill="{TemplateBinding Background}"

Stroke="{TemplateBinding BorderBrush}"/>

<ContentPresenter HorizontalAlignment="Center"

VerticalAlignment="Center"/>

</Grid>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

<Button Style="{StaticResource DialogButtonStyle}" />

A Button without and with a custom control template

ContentPresenter

When you create a custom control template and you want to define a placeholder that renders
the content, you can use the ContentPresenter. By default it adds the content of the
Content property to the visual tree of the template. To display the content of another property
you can set the ContentSource to the name of the property you like.

Triggers

{RelativeSource TemplatedParent} not working in DataTriggers of a ControlTemplate

69
If you want to bind to a property of a property on your control like Data.IsLoaded you
cannot use a normal Trigger, since it does not support this notation, you have to use a
DataTrigger.

But when you are using a DataTrigger, with {RelativeSource TemplatedParent} it will
not work. The reason is, that TemplatedParent can only be used within the
ControlTemplate. It is not working in the Trigger section. You have to use the
{RelativeSource Self} instead.

What if a Binding working or a Setter is not applied when using a control template

There is something you need to know when setting a value of an element within a control
template: The value does have a lower precendence as the local value! So if you are setting the
local value in the constructor of the contained element, you cannot override it within the
controltemplate. But if you use the element directly in your view, it will work. So be aware of this
behavior!.

Here you can find more information about DependencyProperty value precendence:
Dependency Property Value Precedence

Data Templates
Introduction

Data Template are a similar concept as Control Templates. They give you a very flexible and
powerful solution to replace the visual appearance of a data item in a control like ListBox,
ComboBox or ListView. In my opinion this is one of the key success factory of WPF.

If you don't specify a data template, WPF takes the default template that is just a TextBlock. If
you bind complex objects to the control, it just calls ToString() on it. Within a DataTemplate,
the DataContext is set the data object. So you can easily bind against the data context to display
various members of your data object

DataTemplates in Action: Building a simple PropertyGrid

Whereas it was really hard to display complex data in a ListBox with WinForms, its super easy
with WPF. The following example shows a ListBox with a list of DependencyPropertyInfo
instances bound to it. Without a DataTemplate you just see the result of calling ToString() on
the object. With the data template we see the name of the property and a TextBox that even
allows us to edit the value.

70
<!-- Without DataTemplate -->

<ListBox ItemsSource="{Binding}" />

<!-- With DataTemplate -->

<ListBox ItemsSource="{Binding}" BorderBrush="Transparent"

Grid.IsSharedSizeScope="True"

HorizontalContentAlignment="Stretch">

<ListBox.ItemTemplate>

<DataTemplate>

<Grid Margin="4">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="Auto"
SharedSizeGroup="Key" />

<ColumnDefinition Width="*" />

</Grid.ColumnDefinitions>

<TextBlock Text="{Binding Name}" FontWeight="Bold" />

<TextBox Grid.Column="1" Text="{Binding Value }" />

</Grid>

</DataTemplate>

</ListBox.ItemTemplate>

71
</ListBox>

How to use a DataTemplateSelector to switch the Template depending on the data

Our property grid looks nice so far, but it would be much more usable if we could switch the
editor depending on the type of the property.

The simplest way to do this is to use a DataTemplateSelector. The DataTemplateSelector


has a single method to override: SelectTemplate(object item, DependencyObject
container). In this method we decide on the provided item which DataTemplate to choose.

The following exmple shows an DataTemplateSelector that decides between tree data
templates:

public class PropertyDataTemplateSelector : DataTemplateSelector

public DataTemplate DefaultnDataTemplate { get; set; }

public DataTemplate BooleanDataTemplate { get; set; }

public DataTemplate EnumDataTemplate { get; set; }

public override DataTemplate SelectTemplate(object item,

DependencyObject container)

DependencyPropertyInfo dpi = item as DependencyPropertyInfo;

if (dpi.PropertyType == typeof(bool))

return BooleanDataTemplate;

if (dpi.PropertyType.IsEnum)

return EnumDataTemplate;

return DefaultnDataTemplate;

72
}

<Window x:Class="DataTemplates.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:l="clr-namespace:DataTemplates"

xmlns:sys="clr-namespace:System;assembly=mscorlib">

<Window.Resources>

<!-- Default DataTemplate -->

<DataTemplate x:Key="DefaultDataTemplate">

...

</DataTemplate>

<!-- DataTemplate for Booleans -->

<DataTemplate x:Key="BooleanDataTemplate">

...

</DataTemplate>

<!-- DataTemplate for Enums -->

<DataTemplate x:Key="EnumDataTemplate">

...

</DataTemplate>

<!-- DataTemplate Selector -->

<l:PropertyDataTemplateSelector x:Key="templateSelector"

DefaultnDataTemplate="{StaticResource
DefaultDataTemplate}"

BooleanDataTemplate="{StaticResource
BooleanDataTemplate}"

EnumDataTemplate="{StaticResource EnumDataTemplate}"/>

</Window.Resources>

73
<Grid>

<ListBox ItemsSource="{Binding}" Grid.IsSharedSizeScope="True"

HorizontalContentAlignment="Stretch"

ItemTemplateSelector="{StaticResource
templateSelector}"/>

</Grid>

</Window> 

How to react to IsSelected in the DataTemplate

If you want to change the appearance of a ListBoxItem when it is selected, you have to bind the
IsSelected property of the ListBoxItem. But this is a bit tricky, you have to use a relative source
with FindAcestor to navigate up the visual tree until you reach the ListBoxItem.

<DataTemplate x:Key="DefaultDataTemplate">

<Border x:Name="border" Height="50">

...

</Border>

<DataTemplate.Triggers>

<DataTrigger Binding="{Binding RelativeSource=

{RelativeSource Mode=FindAncestor, AncestorType=

{x:Type ListBoxItem}},Path=IsSelected}" Value="True">

<Setter TargetName="border" Property="Height" Value="100"/>

</DataTrigger>

</DataTemplate.Triggers>

</DataTemplate>

74
Localization
How to evaluate a localization mechanism
To choose an appropriate localization mechanism you have to find one that meets the
requirements and your companys established translation process.

Criterias to compare the localization mechanisms among each others:

 Dynamic language switching


 Usage in XAML and Code
 Types of applicable resources
 Ease and flexibility of use
 Translation performance

Different WPF translation mechanisms compared

 Localization using a MarkupExtension


 Localization using Satellite Assemblies

Localization of a WPF application using a custom


MarkupExtension

The Idea

75
A simple and effective way to localize application resources is to write a custom
MarkupExtension that provides a localized value. The extension takes a parameter in the
constructor that is the unique resource key. When the DepdendencyProperty asks for the value,
the markup extension looks up the value from a generic resource provider. This gives you the
flexibility to reuse the resource management and translation process that is already established
within your company.

Using a custom markup extension has some advantages

 Lightweight and flexible solution


 Dynamic language switch at runtime
 Works with any kind of resource providers.

Other Implementations
The idea of using a markup extension for localization is not unique by me. There are also other
similar implementations out there. Here you find some links:

 LocalizeExtension by SeriousM
 Resx MarkupExtension by Grant Frisken

How to use it
The usage of the markup extension is very simple. Just replace the string you want to localize by
{l:Translate resourceKey}.

<TextBlock Text="{l:Translate CustomerForm.FirstName}" />

Implementation details of the translation infrastructure


The translation infrastructure consists of the folling parts

 Translation manager
The translation manager is a static class that manages the current language and notifies
all markup extensions, to update their values when the language changes. It also
provides access to translated resources. The resources itself are provided by a generic
translation provider.

 Translate markup extension


The tanslate markup extension knows the resource key and provides the translated
value. It listens to the LanguageChanged event of the translation manager and updates
its value. This event handler is implemented by the weak event pattern to prevent
memory leaks.

76
 Translation provider
The translation provider is a class that provides the translated resources. It has to
implement the ITranslationProvider and can access any kind of resources you like.
For e.g. ResX, XML or text files.

public class TranslateExtension : MarkupExtension

private string _key;

public TranslateExtension(string key)

_key = key;

[ConstructorArgument("key")]

public string Key

get { return _key; }

set { _key = value;}

public override object ProvideValue(IServiceProvider serviceProvider)

var binding = new Binding("Value")

Source = new TranslationData(_key)

};

return binding.ProvideValue(serviceProvider);

77
}

public class TranslationData : IWeakEventListener,

INotifyPropertyChanged, IDisposable

private string _key;

public TranslationData( string key)

_key = key;

LanguageChangedEventManager.AddListener(

TranslationManager.Instance, this);

~TranslationData()

Dispose(false);

public void Dispose()

Dispose(true);

GC.SuppressFinalize(this);

78
 

protected virtual void Dispose(bool disposing)

if (disposing)

LanguageChangedEventManager.RemoveListener(

TranslationManager.Instance, this);

public object Value

get

return TranslationManager.Instance.Translate(_key);

public bool ReceiveWeakEvent(Type managerType,

object sender, EventArgs e)

if (managerType == typeof(LanguageChangedEventManager))

OnLanguageChanged(sender, e);

return true;

return false;

79
}

private void OnLanguageChanged(object sender, EventArgs e)

if( PropertyChanged != null )

PropertyChanged( this, new PropertyChangedEventArgs("Value"));

public event PropertyChangedEventHandler PropertyChanged;

public class TranslationManager

private static TranslationManager _translationManager;

public event EventHandler LanguageChanged;

public CultureInfo CurrentLanguage

get { return Thread.CurrentThread.CurrentUICulture; }

set

if( value != Thread.CurrentThread.CurrentUICulture)

80
Thread.CurrentThread.CurrentUICulture = value;

OnLanguageChanged();

public IEnumerable<CultureInfo> Languages

get

if( TranslationProvider != null)

return TranslationProvider.Languages;

return Enumerable.Empty<CultureInfo>();

public static TranslationManager Instance

get

if (_translationManager == null)

_translationManager = new TranslationManager();

return _translationManager;

81
public ITranslationProvider TranslationProvider { get; set; }

private void OnLanguageChanged()

if (LanguageChanged != null)

LanguageChanged(this, EventArgs.Empty);

public object Translate(string key)

if( TranslationProvider!= null)

object translatedValue =TranslationProvider.Translate(key);

if( translatedValue != null)

return translatedValue;

return string.Format("!{0}!", key);

82
Interaction
Behaviors

A simple Border can be dragged by mouse - because of an attached drag behavior.

Introduction
Behaviors are a new concept, introduced with Expression Blend in Version 3, to encapsulate
pieces of functionality into a reusable component. These components than can be attached
to controls to give them an additional behavior.

The ideas behind behaviors are to give the interaction designer more flexibility to design
complex user interactions without writing any code.

Example of a behaviors are drag&drop, input validation, pan and zoom, re-position of elements,
etc... The list of possible behaviors is very long.

Imaging an application that has a list of customers and the user can add some of them to
subscriber lists. This interaction can be designed by providing an "Add" button next to each
subscriber list. But if the interaction designer wants to add drag&drop functionality, he needs to
discuss it with the developer and wait until the implementation is done. With behaviors he just
drags a drag and drop behavior on each list and we are done.

How to use behaviors in Expression Blend 3


Using behaviors in Expression Blend is as simple as adding an element to the design surface. In
the asset library you find a new secion called "Behaviors". It lists all behaviors available within
your project. Just grab one of these and drag it onto the element you want to add this behavior
and thats it.

The behavior appears as an child element in the visual tree. By clicking on it you can configure
the properties of the behavior.

83
How does it work
To add behaviors to an element you need some kind of an extension point. This is an attached
property called Interaction.Behaviors.
This attached property holds the list of behaviors for that element and pass a reference to the
element into the behavior. The behavior than can register itself to events and property changes
and so extend the functionality of the element.

The idea is simple, but very clever. They don't need any new infrastructure, they just reuse the
existing one.

<Border Background="LightBlue" >

<e:Interaction.Behaviors>

<b:DragBehavior/>

</e:Interaction.Behaviors>

84
<TextBlock Text="Drag me around!" />

</Border>

How to implement your own behavior


The following example shows the implementation of the drag behavior we used above. Just
derive from Behavior<T;gt; and override the OnAttached() method.

public class DragBehavior : Behavior<UIElement>

private Point elementStartPosition;

private Point mouseStartPosition;

private TranslateTransform transform = new TranslateTransform();

protected override void OnAttached()

Window parent = Application.Current.MainWindow;

AssociatedObject.RenderTransform = transform;

AssociatedObject.MouseLeftButtonDown += (sender, e) =>

elementStartPosition = AssociatedObject.TranslatePoint( new


Point(), parent );

mouseStartPosition = e.GetPosition(parent);

AssociatedObject.CaptureMouse();

};

AssociatedObject.MouseLeftButtonUp += (sender, e) =>

85
AssociatedObject.ReleaseMouseCapture();

};

AssociatedObject.MouseMove += (sender, e) =>

Vector diff = e.GetPosition( parent ) - mouseStartPosition;

if (AssociatedObject.IsMouseCaptured)

transform.X = diff.X;

transform.Y = diff.Y;

};

List of some popular behaviors


Since its so cool and easy to create your own pice of interactivity, I am sure that we will find
hunderts of behaviors available soon. I tried to make a list of some popular ones.

 Zoom Behavior
 Glass Behavior
 Shake Behavior
 Transparency Behavior

Drag and Drop in WPF

Introduction

Drag&Drop can drasticly improve the productiviy and user experience of a software. But only a
few programmers provide drag and drop functionality in their applications, because they think

86
its much more dificult than it really is. This article shows how simple drag and drop can be
implemented in WPF.

Drag&Drop in 6 Steps

1. Detect a drag as a combinatination of MouseMove and MouseLeftButtonDown


2. Find the data you want to drag and create a DataObject that contains the format, the
data and the allowed effects.
3. Initiate the dragging by calling DoDragDrop()
4. Set the AllowDrop property to True on the elements you want to allow dropping.
5. Register a handler to the DragEnter event to detect a dragging over the drop location.
Check the format and the data by calling GetDataPresent() on the event args. If the data
can be dropped, set the Effect property on the event args to display the appropriate
mouse cursor.
6. When the user releases the mouse button the DragDrop event is called. Get the data by
calling the GetData() method on the Data object provided in the event args.

...and that's all the magic.

Drag
To start the drag operation, we have to detect a mouse move while the left mouse button is
pressed. To do this we have to hook up handlers on the PreviewMouseMove and
PreviewMouseLeftButtonDown events.

To prevent occasionally drags, its a good design to not start the drag operation until the user
has moved the mouse cursor by a couple of pixels. WPF provides a constant that contains the
amount of pixel that Windows uses.

When the drag is initiated, we need to specify the data we want to drag. In our case its the data
of the ListViewItem we dragged. We find the ListViewItem in the OriginalSource of
the mouse event args. By calling ItemContainerGenerator.ItemFromContainer we get
the data behind the ListViewItem.

Create a DataObject to transport the data to the drop location. The constructor takes two
arguments. A string that describes the format and the data we want to drag.

<ListView x:Name="DragList"

PreviewMouseLeftButtonDown="List_PreviewMouseLeftButtonDown"

PreviewMouseMove="List_MouseMove"/>

87
private void List_PreviewMouseLeftButtonDown(object sender,
MouseButtonEventArgs e)

// Store the mouse position

startPoint = e.GetPosition(null);

private void List_MouseMove(object sender, MouseEventArgs e)

// Get the current mouse position

Point mousePos = e.GetPosition(null);

Vector diff = startPoint - mousePos;

if (e.LeftButton == MouseButtonState.Pressed &&

Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance &&

Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance )

// Get the dragged ListViewItem

ListView listView = sender as ListView;

ListViewItem listViewItem =

FindAnchestor<ListViewItem>((DependencyObject)e.OriginalSource);

// Find the data behind the ListViewItem

Contact contact = (Contact)listView.ItemContainerGenerator.

ItemFromContainer(listViewItem);

88
// Initialize the drag & drop operation

DataObject dragData = new DataObject("myFormat", contact );

DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Move);

// Helper to search up the VisualTree

private static T FindAnchestor<T>(DependencyObject current)

where T : DependencyObject

do

if( current is T )

return (T)current;

current = VisualTreeHelper.GetParent(current);

while (current != null);

return null;

Drop
To make an element be a drop location, set the AllowDrop property to true. When the user
drags an item over the element, the DragEnter event is called. In this event you can analyze the
data and decide if a drop is allowed or not.

89
When the user releases the mouse button the Drop event is called. The data is available in the
DataObject provided in the DragEventArgs.

<ListView x:Name="DropList"

Drop="DropList_Drop"

DragEnter="DropList_DragEnter"

AllowDrop="True" />

private void List_DragEnter(object sender, DragEventArgs e)

if (!e.Data.GetDataPresent("contact") ||

sender == e.Source)

e.Effects = DragDropEffects.None;

private void List_Drop(object sender, DragEventArgs e)

if (e.Data.GetDataPresent("myFormat"))

Contact contact = e.Data.GetData("myFormat") as Contact;

ListView listView = sender as ListView;

listView.Items.Add(contact);

90
}

91
Resource

Improve the performance of merged ResourceDictionaries


Each time a control references a ResourceDictionary XAML creates a new instance of it. So
if you have a custom control library with 30 controls in it and each control references a common
dictionary you create 30 identical resource dictionaries!

<ResourceDictionary.MergedDictionaries>

<SharedResourceDictionary
Source="/MyControlLibrary;component/Themes/Brushes.xaml" />

</ResourceDictionary.MergedDictionaries>

To get rid of this problem, I created the SharedResourceDictionary. You can use it the
same way as a conventional ResourceDictionary. The only suptile difference is, that if it is
instanced multiple times, the resources are loaded only once.

[assembly:
XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation",

"WPFTutorial.Utils")]

/// <summary>

/// The shared resource dictionary is a specialized resource dictionary

/// that loads it content only once. If a second instance with the same source

/// is created, it only merges the resources from the cache.

/// </summary>

public class SharedResourceDictionary : ResourceDictionary

92
/// <summary>

/// Internal cache of loaded dictionaries

/// </summary>

public static Dictionary<Uri, ResourceDictionary> _sharedDictionaries =

new Dictionary<Uri, ResourceDictionary>();

/// <summary>

/// Local member of the source uri

/// </summary>

private Uri _sourceUri;

/// <summary>

/// Gets or sets the uniform resource identifier (URI) to load resources
from.

/// </summary>

public new Uri Source

get { return _sourceUri; }

set

_sourceUri = value;

if (!_sharedDictionaries.ContainsKey(value))

// If the dictionary is not yet loaded, load it by setting

// the source of the base class

base.Source = value;

93
// add it to the cache

_sharedDictionaries.Add(value, this);

else

// If the dictionary is already loaded, get it from the cache

MergedDictionaries.Add(_sharedDictionaries[value]);

How to read WPF ResourceDictionaries from WinForms


When you add resources dictionaries to an WPF project the build action is automatically set to
Page. This means that the compiler generates a BAML stream and adds it to the resources of the
assembly.

Since WPF has the built-in functionality to read a BAML stream but its API is not public, we have
to write a little helper class that access the internal method by using reflection.

public static class BamlReader

public static object Load(Stream stream)

ParserContext pc = new ParserContext();

MethodInfo loadBamlMethod = typeof(XamlReader).GetMethod("LoadBaml",

BindingFlags.NonPublic | BindingFlags.Static)

94
return loadBamlMethod.Invoke(null, new object[] { stream, pc, null,
false });

StreamResourceInfo sri = System.Windows.Application.GetResourceStream(

new Uri("/MyAssemblyName;component/MyResourceDict.xaml",
UriKind.Relative));

ResourceDictionary resources =
(ResourceDictionary)BamlReader.Load(sri.Stream);

95
2D Graphics
Draw lines excactly on physical device pixels
Why do my lines appear so blurry?
When you draw a line in WPF you will experience that they often appear blurry. The reason for
this is the antialiasing system that spreads the line over multiple pixels if it doesn't align with
physical device pixels.

The following example shows a usercontrol that overrides the OnRender method for custom
drawing a rectange to the drawingContext. Even if all points are integer values and my screen
has a resolution of 96dpi the lines appear blurry. Why?

protected override void OnRender(DrawingContext drawingContext)

Pen pen = new Pen(Brushes.Black, 1);

Rect rect = new Rect(20,20, 50, 60);

drawingContext.DrawRectangle(null, pen, rect);

Resolution independence
WPF is resoultion independent. This means you specify the size of an user interface element in
inches, not in pixels. A logical unit in WPF is 1/96 of an inch. This scale is chosen, because most

96
screens have a resolution of 96dpi. So in most cases 1 logical unit maches to 1 physical pixel. But
if the screen resolution changes, this rule is no longer valid.

Align the edges not the center points


The reason why the lines appear blurry, is that our points are center points of the lines not
edges. With a pen width of 1 the edges are drawn excactly between two pixels.

A first approach is to round each point to an integer value (snap to a logical pixel) an give it an
offset of half the pen width. This ensures, that the edges of the line align with logical pixels. But
this assumes, that logical and physical device pixels are the same. This is only true if the screen
resolution is 96dpi, no scale transform is applied and our origin lays on a logical pixel.

Using SnapToDevicePixels for controls


All WPF controls provide a property SnapToDevicePixels. If set to true, the control ensures
the all edges are drawn excactly on physical device pixels. But unfortunately this feature is only
available on control level.

Using GuidelineSets for custom drawing


Our first approach to snap all points to logical pixels is easy but it has a lot of assumptions that
must be true to get the expected result. Fortunately the developers of the milcore (MIL stands
for media integration layer, that's WPFs rendering engine) give us a way to guide the rendering
engine to align a logical coordinate excatly on a physical device pixels. To achieve this, we need
to create a GuidelineSet. The GuidelineSet contains a list of logical X and Y coordinates
that we want the engine to align them to physical device pixels.
If we look at the implementation of SnapToDevicePixels we see that it does excatly the
same.

protected override void OnRender(DrawingContext drawingContext)

Pen pen = new Pen(Brushes.Black, 1);

Rect rect = new Rect(20,20, 50, 60);

double halfPenWidth = pen.Thickness / 2;

// Create a guidelines set

97
GuidelineSet guidelines = new GuidelineSet();

guidelines.GuidelinesX.Add(rect.Left + halfPenWidth);

guidelines.GuidelinesX.Add(rect.Right + halfPenWidth);

guidelines.GuidelinesY.Add(rect.Top + halfPenWidth);

guidelines.GuidelinesY.Add(rect.Bottom + halfPenWidth);

drawingContext.PushGuidelineSet(guidelines);

drawingContext.DrawRectangle(null, pen, rect);

drawingContext.Pop();

The example above is the same as at the beginning of the article. But now we create a
GuidelinesSet. To the set we add a horizontal or vertical guidelines for each logical
coordinate that we want to have aligned with physical pixels. And that is not the center point,
but the edge of our lines. Therefore we add half the penwidth to each point.
Before we draw the rectange on the DrawingContext we push the guidelines to the stack. The
result are lines that perfecly match to our physical device pixels

Adjust the penwidth to the screen resolution


The last thing we need to consider is that the width of the pen is still defined in logical units. If
we want to keep the pen width to one pixel (think a moment if you really want to have this) you
can scale the pen width with the ration between your screen resolution and WPF's logical units
which is 1/96. The following sample shows you how to do this.

Matrix m = PresentationSource.FromVisual(this)

.CompositionTarget.TransformToDevice;

double dpiFactor = 1/m.M11;

98
Pen scaledPen = new Pen( Brushes.Black, 1 * dpiFactor );

How to get a Bitmap from a Visual


 

public void SaveImage(Visual visual, int width, int height, string filePath)

RenderTargetBitmap bitmap = new RenderTargetBitmap(width, height, 96, 96,

PixelFormats.Pbgra32);

bitmap.Render(visual);

PngBitmapEncoder image = new PngBitmapEncoder();

image.Frames.Add(BitmapFrame.Create(bitmap));

using (Stream fs = File.Create(filePath))

image.Save(fs);

WPF Geometry Transformation Tool


The geometry transformer is a simple tool I wrote to scale-, translate- and rotate-transform a
geometry in the path mini language.

Simply paste the geometry string into the input textbox and specify the transform parameters.
After pressing "Transform" the output textbox shows the translated geometry string. This is very
useful to transform simple geometries like an expanded/collapsed chevron used in an expander
template.
Click here to download the Geometry Transformer

99
Images in WPF
How to create a Thumbnail of an Image
 

private ImageSource GetThumbnail( string fileName )

byte[] buffer = File.ReadAllBytes(fileName);

MemoryStream memoryStream = new MemoryStream(buffer);

BitmapImage bitmap = new BitmapImage();

bitmap.BeginInit();

bitmap.DecodePixelWidth = 80;

bitmap.DecodePixelHeight = 60;

100
bitmap.StreamSource = memoryStream;

bitmap.EndInit();

bitmap.Freeze();

return bitmap;

How to automatically crop an image


The following method allows you to automatically crop an image to it's content.

public static ImageSource AutoCropBitmap(BitmapSource source)

if (source == null)

throw new ArgumentException("source");

if (source.Format != PixelFormats.Bgra32)

source = new FormatConvertedBitmap(source,

PixelFormats.Bgra32, null, 0);

int width = source.PixelWidth;

int height = source.PixelHeight;

int bytesPerPixel = source.Format.BitsPerPixel / 8;

int stride = width * bytesPerPixel;

var pixelBuffer = new byte[height * stride];

source.CopyPixels(pixelBuffer, stride, 0);

101
 

int cropTop = height, cropBottom = 0, cropLeft = width, cropRight = 0;

for (int y = 0; y < height; y++)

for (int x = 0; x < width; x++)

int offset = (y * stride + x * bytesPerPixel);

byte blue = pixelBuffer[offset];

byte green = pixelBuffer[offset + 1];

byte red = pixelBuffer[offset + 2];

byte alpha = pixelBuffer[offset + 3];

//TODO: Define a threshold when a pixel has a content

bool hasContent = alpha > 10;

if (hasContent)

cropLeft = Math.Min(x, cropLeft);

cropRight = Math.Max(x, cropRight);

cropTop = Math.Min(y, cropTop);

cropBottom = Math.Max(y, cropBottom);

return new CroppedBitmap(source,

new Int32Rect(cropLeft, cropTop, cropRight - cropLeft,

102
cropBottom - cropTop));

103
3D Graphics
Introduction to WPF 3D
3D Graphic Basics
The basic idea of creating 3D graphics is to have a three dimensional model of an object.
Because our screen is only two dimensional, we define a camera that takes a picture of the
object. The picture is a projection of the object to a planar surface. This projection is rendered
into an bitmap by the 3D rendering engine. The engine determines the color for every pixel by
calculating the amount of light that is reflected by any light sources to the projection surface by
the objects in the 3D space.
All surfaces of objects have a material and a brush. The material defines how much light is
reflected for a specific angle and the brush defines the color. A brush can either be a simple
color or a gradient or even an image called texture.

A world of triangles
In the world of 3D graphics, all objects are described by a set of triangles. But why triangles? The
reason for this is that a triangle is the most granular geometry to describe a planar surface. The
rendering engine can calculate the color of each triangle depending on its material and angle to
the lights in the scene. If we would build our world on rectangles, the points don't need to be
plane. The surface will be a lot more complex to calculate and render.

A surface of a 3D object is called a mesh. A mesh is defined by a number of 3D points. These


points are called vertices. The vertices are joined together by a winding pattern to define the
triangles. Every triangle has a front and a back side. Only the front side is rendered. The front
side is defined by the winding order of the points. WPF uses a counter clockwise winding
pattern. You can remember this with a simple mnemonic called the "right hand rule". This means
if you close your right hand to a thumb-up gesture, your finger make a counter clockwise move

104
while the thumb shows up. The fingers show the winding order, while the thumb indicates the
upper-side of the triangle.

A right handed coordinate system


WPF uses a right-handed coordinate system. This means that if you hold the fingers of your
right hand as shown on the picture, the fingers indicate the positive direction of the tree axes.

Elements of a 3D scene

 Viewport3D
The viewport is the control that builds the gate between the 2D and the 3D world.
 Camera
Every 3D scene has excactly one camera. The camera defines the Position and the
LookDirection and the UpDirection of the viewer. WPF supports orthographical and
perspective cameras.
 3D Models
A 3D model defines an object in the scene. It has a Geometry that is the mesh and a

105
Material that can be a diffuse, specular or emmisive material. The material itself has a
brush.
 Lights
Without any lights you see nothing. So we need to place at least one light in our scene
to illuminate our models. WPF supports different kind of lights, like:
o AmbientLight
o DirectionalLight
o PointLight
o SpotLight

Hello 3D-World - A Simple Cube


The following example shows how to create a basic cube mesh with 8 vertices that are wired up
in 12 triangles that form the shape of the cube.

<Viewport3D>

<Viewport3D.Camera>

<PerspectiveCamera Position="-40,40,40" LookDirection="40,-40,-40 "

UpDirection="0,0,1" />

</Viewport3D.Camera>

<ModelVisual3D>

<ModelVisual3D.Content>

<Model3DGroup>

<DirectionalLight Color="White" Direction="-1,-1,-3" />

106
<GeometryModel3D>

<GeometryModel3D.Geometry>

<MeshGeometry3D Positions="0,0,0 10,0,0 10,10,0 0,10,0


0,0,10

10,0,10 10,10,10 0,10,10"

TriangleIndices="0 1 3 1 2 3 0 4 3 4 7 3 4 6 7 4 5 6

0 4 1 1 4 5 1 2 6 6 5 1 2 3 7 7 6
2"/>

</GeometryModel3D.Geometry>

<GeometryModel3D.Material>

<DiffuseMaterial Brush="Red"/>

</GeometryModel3D.Material>

</GeometryModel3D>

</Model3DGroup>

</ModelVisual3D.Content>

</ModelVisual3D>

</Viewport3D>

107
Animation
Debugging style and template Errors
Common Errors
If you get the following error: Cannot animate '(0).(1)' on an immutable object
instance. it could be that you are run into one of the following limitations:

 You are animating a dependency property without setting a local value


 You are animating a dependency property who's current value is defined in another
assembly that is not merged into the resource dictionary.
 You are animating a value that is currently databound

How to control the frame rate for WPF animations


Animations are very cool, but they can cause a high CPU load. One reason could be a missing
hardware acceleration due to a old graphics adapter or a software rendering constraint. Another
reason could be the the high frame rate of animations that is set to 60 fps by default.

You can easily lower the framerate for all animations by overriding the DesiredFrameRate
property of the timeline. Just add the following code to your project and play around with the
setting to find a good tradeoff between performance and aesthetic.

Timeline.DesiredFrameRateProperty.OverrideMetadata(typeof(Timeline),

new FrameworkPropertyMetadata { DefaultValue = 30 });

Or you can set the framerate individually for each animation in XAML, using the following code:

<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:0.5"

From="1.0" To="0.5" Timeline.DesiredFrameRate="30" />

108
Multimedia
How to use the Speech Synthesizer in WPF
Microsoft provides a new speech API (SAPI) for Windows Vista and later. It allows developers to
build speech enabled applications. Simply add a reference to System.Speech and include the
following code to your project.

using System.Speech.Synthesis;

SpeechSynthesizer synthesizer = new SpeechSynthesizer();

synthesizer.Volume = 50; // 0...100

synthesizer.Rate = 3; // -10...10

// Synchronous

synthesizer.Speak("Welcome to the WPF Tutorial.");

// Asynchronous

synthesizer.SpeakAsync("Welcome to the WPF Tutorial.");

109
Windows 7
How to extend the Aero Glass into the Client area

Introduction
Windows Vista has a new default theme called Aero glass. In Aero glass, the title bar of a
window and the frame is drawn transculent. This gives the UI a clean and lightweight look. This
nice feaure is provided by a service that is called the desktop window manager (DWM).

Extending the Glass


By default the blurry glass effect is only on the title bar and the frame, but the client area is
drawn opaque. But there is a simple way to extend the glass into the client area by using the
DWM's API.

First thing you need to do is to include some Win32 functions from the dwmapi.dll library.

using System.Runtime.InteropServices;

using System.Windows.Interop;

using System.Windows.Media;

using System.Windows;

110
[StructLayout(LayoutKind.Sequential)]

struct MARGINS

public int cxLeftWidth;

public int cxRightWidth;

public int cyTopHeight;

public int cyBottomHeight;

[DllImport("dwmapi.dll")]

static extern int

DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);

[DllImport("dwmapi.dll")]

extern static int DwmIsCompositionEnabled(ref int en);

I have written a helper method that does all the stuff to extend the glass by the specified
amount of pixels on each border of the window.

/// <summary>

/// Extends the glass area into the client area of the window

/// </summary>

/// <param name="window"></param>

/// <param name="top"></param>

public static void ExtendGlass(Window window, Thickness thikness)

111
{

try

int isGlassEnabled = 0;

DwmIsCompositionEnabled(ref isGlassEnabled);

if (Environment.OSVersion.Version.Major > 5 && isGlassEnabled > 0)

// Get the window handle

WindowInteropHelper helper = new WindowInteropHelper(window);

HwndSource mainWindowSrc = (HwndSource)HwndSource.

FromHwnd(helper.Handle);

mainWindowSrc.CompositionTarget.BackgroundColor =

Colors.Transparent;

// Get the dpi of the screen

System.Drawing.Graphics desktop =

System.Drawing.Graphics.FromHwnd(mainWindowSrc.Handle);

float dpiX = desktop.DpiX / 96;

float dpiY = desktop.DpiY / 96;

// Set Margins

MARGINS margins = new MARGINS();

margins.cxLeftWidth = (int)(thikness.Left * dpiX);

margins.cxRightWidth = (int)(thikness.Right * dpiX);

margins.cyBottomHeight = (int)(thikness.Bottom * dpiY);

margins.cyTopHeight = (int)(thikness.Top * dpiY);

window.Background = Brushes.Transparent;

112
 

int hr = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle,

ref margins);

else

window.Background = SystemColors.WindowBrush;

catch (DllNotFoundException)

Next thing you need to do is calling the ExtendGlass in the OnSourceInitialized


callback. Because that is the time the window handle has been created.

protected override void OnSourceInitialized(EventArgs e)

base.OnSourceInitialized(e);

GlassHelper.ExtendGlass(this, LayoutRoot.Margin);

113
Since the user (or the system) can enable or disable the glass effect while the application is
running, we need to hook up a callback in the WndProc to undo or initialize the glass extension
dynamically.

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam,

IntPtr lParam, ref bool handled)

if (msg == GlassHelper.WM_DWMCOMPOSITIONCHANGED)

GlassHelper.ExtendGlass(this, LayoutRoot.Margin);

handled = true;

return IntPtr.Zero;

How to use the Windows Vista TaskDialog in WPF

114
Introduction
Windows Vista comes with an new standard dialog box called task dialog. The TaskDialog was
developed as part of Windows Vista's "clarity" offensive to improve the user experience. It
provides a lot more features than the original message box.

The TaskDialog is part of the comctrl32.dll library and only available on Windows Vista or
later, its not part of WPF or the .NET framework. To use it from managed code, we need to write
a interop wrapper.

This article is not finished yet... :-(

How to add Tasks to Jumplists in .NET 4.0 and Windows 7

Introduction

115
Windows 7 provides a new taskbar feature for applications called jumplists. They appear, when
you right-click on a application icon in the taskbar. By default you see a list of recent files
opened and two entries to launch and detach the application.

.NET 4.0 provides a managed API that allows you to easily manipulate the entries in the jumplist.

How to add a Task to the Jumplist


A jumplist is nothing more than a categorizes list of links to files that can be launched by the
user. The links are called JumpTasks. They can be parametrized with a title, description, icon,
filepath and command line arguments.

In the following sample I create a new JumpList and add a task to the list that launches the
sample application, but with a command line argument. If the application is launched with an
argument, it shows a MessageBox instead.

public partial class App : Application

protected override void OnStartup(StartupEventArgs e)

if (e.Args.Count() > 0)

MessageBox.Show("You have the latest version.");

Shutdown();

JumpTask task = new JumpTask

Title = "Check for Updates",

Arguments = "/update",

Description = "Cheks for Software Updates",

CustomCategory = "Actions",

IconResourcePath = Assembly.GetEntryAssembly().CodeBase,

ApplicationPath = Assembly.GetEntryAssembly().CodeBase

116
};

JumpList jumpList = new JumpList();

jumpList.JumpItems.Add(task);

jumpList.ShowFrequentCategory = false;

jumpList.ShowRecentCategory = false;

JumpList.SetJumpList(Application.Current, jumpList);

117
Interoperability

How to get the Handle of a WPF Window


 

IntPtr windowHandle = new WindowInteropHelper(

Application.Current.MainWindow).Handle;

118
Performance
50 WPF Performance Tips
Application Startup

1. Disable Assembly localization if you don't need it. By using the


[NeutralResourcesLanguageAttribute]

119
Expression Blend
Prototyping with Expression Blend 3 + SketchFlow

Introduction
Software is getting even more complex, interactive and dynamic. It's nearly impossible, for a
developer to find the best solution at first time. If you start writing code without testing the
concept, you can throw away a lot of valuable time by following a suboptimal approach.

The idea of SketchFlow


The idea of SketchFlow is to combine the simpleness and informality of sketching with paper
and pencil with the dynamic of interactive prototypes. Most prototyping tools focus on creating
high quality assets, but the main purpose of most prototypes is to proove the interaction design
of your software and not to impress your management.

To address this point the Team of SketchFlow has created special styles for controls that look as
if they where drawn by pencil. This focus the discussion on real interaction problems instead of
discussing about details like colors or fonts and suggests that the screen design is still
changeable with a small effort.

120
Workspace setup
Expression Blend 3 includes a workspace management feature that allows you to hide all panels
you don't need to sketch your prototype. You can save your settings by choosing "Save as new
Workspace" from the "Windows" menu.

Create a new SketchFlow project


In Blend 3.0 you find two new project types to create prototypes for WPF or Silverlight.

Create and connect screens

121
Drop sketchy controls onto screens
In the asset library you will find a new category "SketchFlow". It contains a section called "Sketch
Styles". It contains special styles for most WPF or Silverlight controls that look like they are
drawn by hand.

122
Extract common parts to component screens
If you have a part that is used on multiple screens, like a navigation or a login box, you can
extract it to a component screen. This screen can be referenced on multiple screens. If you
modify the component screen, the changes are reflected to all screens.

123
Wire-up navigation

124
Add sample data
A prototype needs to provide sample data to make it understandable. In flash prototypes,
sample data is often just a bunch of textblocks and images. In SketchFlow we have a sample
data generator, that creates real data sources that can be bound to lists and elements as real
data. Selection, scrolling and sorting all works.

In the Data panel you find a database icon. It allows you to create a new sample data source.

Give the sample data source a name and specify the scope of visibility. This can be only on this
screen or within the whole prototype. This can be useful, if you want to use the same demo data
on multiple screens.

125
After creating the demo data source, you can define how a data record should look like. You can
add properties or most popular types and choose from a variety of sample data types. There are
URL's, e-mail adresses, bild text (lorem ipsum), images, and much mure...

126
Add assets from Photoshop, Illustrator or PowerPoint

127
Test prototype and get feedback

128
129
Generate prototype documentation
When you have finished your prototype, you can generate a design documentation by a single
click. It includes the a table of content, the flow map and screenshots of all screens and
components. It's not meant to use it as a complete documentation, but it's a good start to build
on.

130
131
How to Import Photoshop Files into WPF
Introduction
In a WPF project you often have to deal with assets that are created by a designer. They are
often part of Adobe Illustrator or Photoshop files. There are two ways to achieve this goal. You
can

 Directly Import Photoshop Files in Expression Blend


This is the most simple approach if you have Expression Blend 3. Drawbacks are, that you
can only import vector shapes as Path elements. If you want to add these shapes into
the resources, you have to manually extract the geometries.
 Import Photoshop Files in Expression Design and Export to XAML
This approach requires Expression Design to be installed but works already with Version
2.0. The workflow is a bit more complex, but you can choose if you want to export your
shapes as Paths or Geometries.

132
Preparing the Photoshop File
If you create graphical assets that should be integrated to a WPF project you should think of the
following rules to make the import easier.

 Combine multiple vector shapes to one shape


 Don't use layer effects, because they are mostly ignored by the converter
 Set the color dept to 8Bit. Higher color depts cause errors on import

Directly Import Photoshop Files in Expression Blend


The following tutorial explains how to directly import an Adobe Photoshop file into WPF.

 1. Start Expression Blend and open an empty WPF project


 2. Choose "Import Adobe Photoshop File..." from the "File" menu.

 3. Select the file you want to import to Blend


 4. Check or uncheck the layers you want to import and click [OK].

133
 5. Blend imports the file now. Each layer will create a new Image or Path element. The
images will automatically be added to a separate folder in your project.

How to convert Path to Resources


To convert imported Path objects to Geometry objects that can be consumes as resources you
have to do the following steps:

 1. Copy the content of the "Data" attribute to the clipboard

 2. Create a StreamGeometry object and paste the content between the opening and
closing tag. Give the geometry a unique key.

Import Photoshop Files in Expression Design and Export to XAML


The following tutorial explains how to import Adobe Photoshop Files in Expression Design and
Export to XAML to use it in Expression Blend.

 1. Start Expression Blend and open the desired Photoshop File


 2. Check or uncheck the layers you want to import and click [OK].

134
 3. Open the Options Dialog in "Edit->Options->Clipboard(XAML)" and choose if you
want to export shapes as Canvas or Resource Dictionaries.

 4. Select the objects you want to export and choose "Copy XAML" in the Edit menu.

 5. Go back to Expression Blend andpPaste the XAML snippet from the clipboard.

135
Expression Blend 2 AddIns

Introduction
Expression Blend has an add-in model that allows developers to write add-ins to extend its
functionality. Unfortunately this is mainly unknown to most users of blend. A prominent
example is the intellisense addin for blend.

Popular Addins

 Unify - AddIn Manager for Expression Blend


 PluginManager - Loads all addins from a directory
 Colorful - Access color palettes from Adobe Kuler
 Blendsense - Brings IntelliSense to Expression Blend

How to Load and Run an AddIn


To load and run an addin into expression, just pass a command parameter -addin followed the
name of the add-in dll. You don't need any registration of plug-ins, but you can load only one
addin on the same time. To get over this limitation you can use an add-in manager that
dynamically loads multiple plugins even without restarting the tool.

C:\Program Files\Microsoft Expression\Blend 2\Blend.exe


/addin:NameOfTheAddin.dll

136
Tools
XAML Converters
The following list shows converters developed by the WPF community to convert different
formats to XAML or vice versa.

 Adobe Illustrator XAML Export Plugin


 Adobe Photoshop to XAML Converter
 Blender XAML Export Plugin
 Lightwave XAML Export Plugin
 Visio XAML Export
 3D Studio Max to XAML Converter
 Maya to XAML Converter
 Flash to XAML  Converter
 SVG to XAML Converter
 WMF/EMF to XAML Converter

Debugging and Development Utilities

 XAML  Power Toys


 Mole for Visual Studio
 Snoop - A collection of visual debugging helpers
 StyleSnooper - View styles of controls
 Show me the template
 ProtoXAML - A stencil UI skin for WPF paper prototypes
 Crack.NET - A runtime debugging and scripting tool to access internals of .NET applications

XAML Editors

 XAML Pad
 XAML  PadX (extended)
 XAML Hack

137
 KaXaml

Graphical WPF Designers

 Mobiform Aurora XAML Designer


 ZAM 3D (3D XAML Tool by Electric Rain)

138

You might also like