Learn WPF in One Week
Learn WPF in One Week
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
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
LOCALIZATION.................................................................................................................................................. 77
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
2D GRAPHICS.................................................................................................................................................... 98
3D GRAPHICS.................................................................................................................................................. 106
ANIMATION.................................................................................................................................................... 110
MULTIMEDIA.................................................................................................................................................. 111
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
PERFORMANCE............................................................................................................................................... 121
TOOLS............................................................................................................................................................. 139
XAML CONVERTERS.................................................................................................................................................139
DEBUGGING AND DEVELOPMENT UTILITIES....................................................................................................................139
XAML EDITORS....................................................................................................................................................... 139
GRAPHICAL WPF DESIGNERS......................................................................................................................................140
5
Day 1 - Getting Started
6
Day 4 - DataBinding and UI Architecture
Introduction to WPF DataBinding
7
Microsoft provides a free Express Edition of Visual Studio that also includes the WPF designer.
You can download it from the following URL
In the latest Version it also includes a powerful prototyping tool called SketchFlow. Expression
Blend can open solution files created by visual studio.
8
WPF Performance Suite
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
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:
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.
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!
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.
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.
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.
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.
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
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:
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:
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>
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>
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>
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.
21
The logical tree describes the relations between elements of the user interface. The logical tree
is responsible for:
The visual tree contains all logical elements including all visual elements of the template of
each element.<BR
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
Readonly DependencyProperties
Attached DependencyProperties
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
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.
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.
24
How to create a DependencyProperty
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 );
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...
}
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.
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);
}
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()
28
}
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.
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
Best Practices
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.
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.
The Margin and Padding properties can be used to reserve some space around of within the
control.
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
Grid Panel
Introduction
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 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.
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>
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>
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"/>
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.
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.
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.ColumnDefinitions.Add(col1);
grid.ColumnDefinitions.Add(col2);
37
More on this topic
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>
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>
Fixed
Auto
Star (*)
Auto sized
Star sized
new GridLength(1,GridUnitType.Star)
39
Fixed size
new GridLength(100,GridUnitType.Pixel)
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).
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>
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>
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>
</StackPanel.Resources>
<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.
CultureInfo culture)
if (value is Boolean)
return value;
CultureInfo culture)
}
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.
Navigation
Filtering
Sorting
Grouping
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
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">
</Window>
public CustomerView()
44
public class CustomerViewModel
public CustomerViewModel()
_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.
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.
ICollectionView _customerView =
CollectionViewSource.GetDefaultView(customers);
_customerView.CurrentChanged = CustomerSelectionChanged;
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
}
If you change the filter criteria and you want to refresh the view, you have to call Refresh() on
the collection view
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;
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.GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</ListBox.GroupStyle>
</ListBox>
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<CollectionViewSource.GroupDescriptions>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
48
</Window>
Model-View-ViewModel Pattern
This article is not yet finished...
Introduction
WPF brings up a very flexible and powerful databinding framework and this favors a new pattern
how to bind presentation and logic together.
49
Model-View-ViewModel Example
Model
ViewModel
View
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>
/// </summary>
set
_pattern = value;
public RegexValidationRule()
51
else
}
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>
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:
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:
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))]
52
public override object ProvideValue(IServiceProvider
serviceProvider)
CultureInfo culture)
ReadOnlyObservableCollection<ValidationError> errors =
value as ReadOnlyObservableCollection<ValidationError>;
if (errors == null)
return string.Empty;
select e.ErrorContent as
string).ToArray());
CultureInfo culture)
}
53
Next thing is to create an error template for the text box.
Source="{StaticResource ErrorImage}"
ToolTip="{Binding ElementName=adornedElement,
Path=AdornedElement.(Validation.Errors),
Converter={k:ValidationErrorsToStringConverter}}"/>
</Border>
</Grid>
</ControlTemplate>
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.Text>
<Binding.ValidationRules>
<local:RegexValidationRule Pattern="{StaticResource
emailRegex}"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
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.
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).
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.
55
// Do the conversion from bool to visibility
}
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>
</Window.Resources>
<Grid>
</Grid>
</Window>
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!
return this;
}
StringFormat Converter
[ValueConversion(typeof(object), typeof(string))]
System.Globalization.CultureInfo culture)
if (!string.IsNullOrEmpty(format))
else
return value.ToString();
57
public object ConvertBack(object value, Type targetType, object
parameter,
System.Globalization.CultureInfo culture)
return null;
}
Behaviors
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.
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.
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.
<e:Interaction.Behaviors>
<b:DragBehavior/>
</e:Interaction.Behaviors>
</Border>
The following example shows the implementation of the drag behavior we used above. Just
derive from Behavior<T;gt; and override the OnAttached() method.
AssociatedObject.RenderTransform = transform;
mouseStartPosition = e.GetPosition(parent);
AssociatedObject.CaptureMouse();
};
60
AssociatedObject.ReleaseMouseCapture();
};
if (AssociatedObject.IsMouseCaptured)
transform.X = diff.X;
transform.Y = diff.Y;
};
}
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
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.
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.
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.
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.
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
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.
Padding="8,4" Margin="4">Styles</Button>
Padding="8,4" Margin="4">are</Button>
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>
</Window.Resources>
</StackPanel>
</Window>
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">
</Style>
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.
<Setter Property="Template">
<Setter.Value>
68
<Grid>
Stroke="{TemplateBinding BorderBrush}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
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
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
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 -->
Grid.IsSharedSizeScope="True"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
SharedSizeGroup="Key" />
</Grid.ColumnDefinitions>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
71
</ListBox>
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 following exmple shows an DataTemplateSelector that decides between tree data
templates:
DependencyObject container)
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>
<DataTemplate x:Key="DefaultDataTemplate">
...
</DataTemplate>
<DataTemplate x:Key="BooleanDataTemplate">
...
</DataTemplate>
<DataTemplate x:Key="EnumDataTemplate">
...
</DataTemplate>
<l:PropertyDataTemplateSelector x:Key="templateSelector"
DefaultnDataTemplate="{StaticResource
DefaultDataTemplate}"
BooleanDataTemplate="{StaticResource
BooleanDataTemplate}"
EnumDataTemplate="{StaticResource EnumDataTemplate}"/>
</Window.Resources>
73
<Grid>
HorizontalContentAlignment="Stretch"
ItemTemplateSelector="{StaticResource
templateSelector}"/>
</Grid>
</Window>
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>
<DataTemplate.Triggers>
</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.
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.
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}.
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.
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.
_key = key;
[ConstructorArgument("key")]
};
return binding.ProvideValue(serviceProvider);
77
}
INotifyPropertyChanged, IDisposable
_key = key;
LanguageChangedEventManager.AddListener(
TranslationManager.Instance, this);
~TranslationData()
Dispose(false);
Dispose(true);
GC.SuppressFinalize(this);
78
if (disposing)
LanguageChangedEventManager.RemoveListener(
TranslationManager.Instance, this);
get
return TranslationManager.Instance.Translate(_key);
if (managerType == typeof(LanguageChangedEventManager))
OnLanguageChanged(sender, e);
return true;
return false;
79
}
set
80
Thread.CurrentThread.CurrentUICulture = value;
OnLanguageChanged();
get
return TranslationProvider.Languages;
return Enumerable.Empty<CultureInfo>();
get
if (_translationManager == null)
return _translationManager;
81
public ITranslationProvider TranslationProvider { get; set; }
if (LanguageChanged != null)
LanguageChanged(this, EventArgs.Empty);
return translatedValue;
82
Interaction
Behaviors
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.
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.
<e:Interaction.Behaviors>
<b:DragBehavior/>
</e:Interaction.Behaviors>
84
<TextBlock Text="Drag me around!" />
</Border>
AssociatedObject.RenderTransform = transform;
mouseStartPosition = e.GetPosition(parent);
AssociatedObject.CaptureMouse();
};
85
AssociatedObject.ReleaseMouseCapture();
};
if (AssociatedObject.IsMouseCaptured)
transform.X = diff.X;
transform.Y = diff.Y;
};
Zoom Behavior
Glass Behavior
Shake Behavior
Transparency Behavior
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
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)
startPoint = e.GetPosition(null);
ListViewItem listViewItem =
FindAnchestor<ListViewItem>((DependencyObject)e.OriginalSource);
ItemFromContainer(listViewItem);
88
// Initialize the drag & drop operation
where T : DependencyObject
do
if( current is T )
return (T)current;
current = VisualTreeHelper.GetParent(current);
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" />
if (!e.Data.GetDataPresent("contact") ||
sender == e.Source)
e.Effects = DragDropEffects.None;
if (e.Data.GetDataPresent("myFormat"))
listView.Items.Add(contact);
90
}
91
Resource
<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>
/// that loads it content only once. If a second instance with the same source
/// </summary>
92
/// <summary>
/// </summary>
/// <summary>
/// </summary>
/// <summary>
/// Gets or sets the uniform resource identifier (URI) to load resources
from.
/// </summary>
set
_sourceUri = value;
if (!_sharedDictionaries.ContainsKey(value))
base.Source = value;
93
// add it to the cache
_sharedDictionaries.Add(value, this);
else
MergedDictionaries.Add(_sharedDictionaries[value]);
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.
BindingFlags.NonPublic | BindingFlags.Static)
94
return loadBamlMethod.Invoke(null, new object[] { stream, pc, null,
false });
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?
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.
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.
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.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
Matrix m = PresentationSource.FromVisual(this)
.CompositionTarget.TransformToDevice;
98
Pen scaledPen = new Pen( Brushes.Black, 1 * dpiFactor );
public void SaveImage(Visual visual, int width, int height, string filePath)
PixelFormats.Pbgra32);
bitmap.Render(visual);
image.Frames.Add(BitmapFrame.Create(bitmap));
image.Save(fs);
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
bitmap.BeginInit();
bitmap.DecodePixelWidth = 80;
bitmap.DecodePixelHeight = 60;
100
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
bitmap.Freeze();
return bitmap;
if (source == null)
if (source.Format != PixelFormats.Bgra32)
101
if (hasContent)
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.
104
while the thumb shows up. The fingers show the winding order, while the thumb indicates the
upper-side of the triangle.
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
<Viewport3D>
<Viewport3D.Camera>
UpDirection="0,0,1" />
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
106
<GeometryModel3D>
<GeometryModel3D.Geometry>
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 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),
Or you can set the framerate individually for each animation in XAML, using the following code:
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;
synthesizer.Rate = 3; // -10...10
// Synchronous
// Asynchronous
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).
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
[DllImport("dwmapi.dll")]
[DllImport("dwmapi.dll")]
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>
111
{
try
int isGlassEnabled = 0;
DwmIsCompositionEnabled(ref isGlassEnabled);
FromHwnd(helper.Handle);
mainWindowSrc.CompositionTarget.BackgroundColor =
Colors.Transparent;
System.Drawing.Graphics desktop =
System.Drawing.Graphics.FromHwnd(mainWindowSrc.Handle);
// Set Margins
window.Background = Brushes.Transparent;
112
int hr = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle,
ref margins);
else
window.Background = SystemColors.WindowBrush;
catch (DllNotFoundException)
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.
if (msg == GlassHelper.WM_DWMCOMPOSITIONCHANGED)
GlassHelper.ExtendGlass(this, LayoutRoot.Margin);
handled = true;
return IntPtr.Zero;
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.
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.
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.
if (e.Args.Count() > 0)
Shutdown();
Arguments = "/update",
CustomCategory = "Actions",
IconResourcePath = Assembly.GetEntryAssembly().CodeBase,
ApplicationPath = Assembly.GetEntryAssembly().CodeBase
116
};
jumpList.JumpItems.Add(task);
jumpList.ShowFrequentCategory = false;
jumpList.ShowRecentCategory = false;
JumpList.SetJumpList(Application.Current, jumpList);
117
Interoperability
Application.Current.MainWindow).Handle;
118
Performance
50 WPF Performance Tips
Application Startup
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.
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.
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
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.
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.
2. Create a StreamGeometry object and paste the content between the opening and
closing tag. Give the geometry a unique key.
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
136
Tools
XAML Converters
The following list shows converters developed by the WPF community to convert different
formats to XAML or vice versa.
XAML Editors
XAML Pad
XAML PadX (extended)
XAML Hack
137
KaXaml
138