Introduction to Windows Presentation Foundation

43
Introduction to Windows Presentation Foundation Overview The Windows Presentation Foundation is Microsofts next generation UI framework to create applications with a rich user experience. It is part of the .NET framework 3.0 and higher. WPF combines application UIs, 2D graphics, 3D graphics, documents and multimedia into one single framework. Its vector based rendering engine uses hardware acceleration of modern graphic cards. This makes the UI faster, scalable and resolution independent. The followinig illustration gives you an overview of the main new features of WPF Separation of Appearance and Behavior WPF separates the appearance of an user interface from its behavior. The appearance is generally specified in the Extensible Application Markup Language (XAML), the behavior is implemented in a managed programming language like C# or Visual Basic. The two parts are tied together by databinding, events and commands. The separation of appearance and behavior brings the following benefits:

Transcript of Introduction to Windows Presentation Foundation

Page 1: Introduction to Windows Presentation Foundation

Introduction to Windows Presentation Foundation

Overview

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

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

WPF combines application UIs, 2D graphics, 3D graphics, documents and multimedia into

one single framework. Its vector based rendering engine uses hardware acceleration of

modern graphic cards. This makes the UI faster, scalable and resolution independent.

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

Separation of Appearance and Behavior

WPF separates the appearance of an user interface from its behavior. The appearance is

generally specified in the Extensible Application Markup Language (XAML), the behavior is

implemented in a managed programming language like C# or Visual Basic. The two parts

are tied together by databinding, events and commands. The separation of appearance and

behavior brings the following benefits:

Appearance and behaviour are loosely coupled

Designers and developers can work on separate models.

Graphical design tools can work on simple XML documents instead of parsing code.

Page 2: Introduction to Windows Presentation Foundation

Rich composition

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 ofstyles 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.

Page 3: Introduction to Windows Presentation Foundation

How to create a simple WPF application

In Visual Studio 2008

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

Page 4: Introduction to Windows Presentation Foundation

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.

Page 5: Introduction to Windows Presentation Foundation

Isn't this cool!

Introduction to XAML

XAML stands for Extensible Application Markup Language. Its a simple language based on

XML to create and initialize .NET objects with hierarchical relations. Altough it was originally

invented for WPF it can by used to create any kind of object trees.

Today XAML is used to create user interfaces in WPF, Silverlight, declare workflows in WF

and for electronic paper in the XPS standard.

All classes in WPF have parameterless constructors and make excessive usage of properties.

That is done to make it perfectly fit for XML languages like XAML.

Advantages of XAML

All you can do in XAML can also be done in code. XAML ist just another way to create and

initialize objects. You can use WPF without using XAML. It's up to you if you want to declare

it in XAML or write it in code. Declare your UI in XAML has some advantages:

XAML code is short and clear to read

Separation of designer code and logic

Graphical design tools like Expression Blend require XAML as source.

The separation of XAML and UI logic allows it to clearly separate the roles of designer

and developer.

XAML vs. Code

Page 6: Introduction to Windows Presentation Foundation

As an example we build a simple StackPanel with a textblock and a button in XAML and

compare it to the same code in C#.

 <StackPanel> <TextBlock Margin="20">Welcome to the World of XAML</TextBlock> <Button Margin="10" HorizontalAlignment="Right">OK</Button></StackPanel>  

The same expressed in C# will look like this:

 // Create the StackPanelStackPanel stackPanel = new StackPanel();this.Content = stackPanel; // Create the TextBlockTextBlock textBlock = new TextBlock();textBlock.Margin = new Thickness(10);textBlock.Text = "Welcome to the World of XAML";stackPanel.Children.Add(textBlock); // Create the ButtonButton 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>

Page 7: Introduction to Windows Presentation Foundation

</Button>  

Implicit Type conversion

A very powerful construct of WPF are implicit type converters. They do their work silently in

the background. When you declare a BorderBrush, the word "Blue" is only a string. The

implicit BrushConverter makes aSystem.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 fromMarkupExtension.

These are the built-in markup extensions:

Binding

To bind the values of two properties together.

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.

Page 8: Introduction to Windows Presentation Foundation

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 inSystem.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>  

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.

Page 9: Introduction to Windows Presentation Foundation

All surfaces of objects have a material and a brush. The material defines how much light is

reflected for a specific angle and the brush defines the color. A brush can either be a simple

color or a gradient or even an image called texture.

A world of triangles

In the world of 3D graphics, all objects are described by a set of triangles. But why triangles?

The reason for this is that a triangle is the most granular geometry to describe a planar

surface. The rendering engine can calculate the color of each triangle depending on its

material and angle to the lights in the scene. If we would build our world on rectangles, the

points don't need to be plane. The surface will be a lot more complex to calculate and

render.

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

These points are called vertices. The vertices are joined together by a winding pattern to

define the triangles. Every triangle has a front and a back side. Only the front side is

rendered. The front side is defined by the winding order of the points. WPF uses a counter

clockwise winding pattern. You can remember this with a simple mnemonic called the "right

hand rule". This means if you close your right hand to a thumb-up gesture, your finger make

a counter clockwise move while the thumb shows up. The fingers show the winding order,

while the thumb indicates the upper-side of the triangle.

Page 10: Introduction to Windows Presentation Foundation

A right handed coordinate system

WPF uses a right-handed coordinate system. This means that if you hold the fingers of your

right hand as shown on the picture, the fingers indicate the positive direction of the tree

axes.

Elements of a 3D scene

Viewport3D

The viewport is the control that builds the gate between the 2D and the 3D world.

Camera

Every 3D scene has excactly one camera. The camera defines the Position and

Page 11: Introduction to Windows Presentation Foundation

the LookDirection and theUpDirection 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 Material that can be a diffuse, specular or emmisive material. The material itself

has a brush.

Lights

Without any lights you see nothing. So we need to place at least one light in our

scene to illuminate our models. WPF supports different kind of lights, like:

o AmbientLight

o DirectionalLight

o PointLight

o SpotLight

Hello 3D-World - A Simple Cube

The following example shows how to create a basic cube mesh with 8 vertices that are wired

up in 12 triangles that form the shape of the cube.

<Viewport3D>

Page 12: Introduction to Windows Presentation Foundation

<Viewport3D.Camera> <PerspectiveCamera Position="-40,40,40" LookDirection="40,-40,-40 " UpDirection="0,0,1" /> </Viewport3D.Camera> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <DirectionalLight Color="White" Direction="-1,-1,-3" /> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions="0,0,0 10,0,0 10,10,0 0,10,0 0,0,10 10,0,10 10,10,10 0,10,10" TriangleIndices="0 1 3 1 2 3 0 4 3 4 7 3 4 6 7 4 5 6 0 4 1 1 4 5 1 2 6 6 5 1 2 3 7 7 6 2"/> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial Brush="Red"/> </GeometryModel3D.Material> </GeometryModel3D> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D></Viewport3D> 

CONTROLS IN WPF

Dialogs in WPF

OK and Cancel Buttons in a Dialog

You have a modal dialog with several buttons on it and you want to automatically close it,

when the user presses on some of them. To do this you have to set IsCancel="true" on all

buttons that should close the dialog and return false. On one button you

set IsDefault="true" this will be executed when you press [Enter]. It closes the dialog and

Page 13: Introduction to Windows Presentation Foundation

returns... alsofalse. To return true here you have to register a callback that sets the

DialogResult to true

 <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <StackPanel> <Button Content="Cancel" IsCancel="True" /> <Button Click="OkClick" Content="Ok" IsDefault="true" /> </StackPanel></Window>  

 private void OkClick(object sender, RoutedEventArgs e){ this.DialogResult = true;}  

ItemsControl

How to automatically scroll to the last item

 <ListBox l:ItemsControlHelper.ScrollToLastItem="true" />  

 public static class ItemsControlHelper{ public static readonly DependencyProperty ScrollToLastItemProperty = DependencyProperty.RegisterAttached("ScrollToLastItem", typeof(bool), typeof(ItemsControlHelper), new FrameworkPropertyMetadata(false, OnScrollToLastItemChanged));  public static void SetScrollToLastItem(UIElement sender, bool value) { sender.SetValue(ScrollToLastItemProperty, value); }  public static bool GetScrollToLastItem(UIElement sender)

Page 14: Introduction to Windows Presentation Foundation

{ return (bool)sender.GetValue(ScrollToLastItemProperty); }  private static void OnScrollToLastItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var itemsControl = sender as ItemsControl;  if (itemsControl != null) { itemsControl.ItemContainerGenerator.StatusChanged += (s,a) => OnItemsChanged(itemsControl,s,a); } }  static void OnItemsChanged(ItemsControl itemsControl, object sender, EventArgs e) { var generator = sender as ItemContainerGenerator; if( generator.Status == GeneratorStatus.ContainersGenerated ) { if (itemsControl.Items.Count > 0) { ScrollIntoView(itemsControl, itemsControl.Items[itemsControl.Items.Count - 1]); } } }  private static void ScrollIntoView(ItemsControl itemsControl, object item) { if (itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) { OnBringItemIntoView(itemsControl, item); } else { Func<object, object> onBringIntoView = (o) => OnBringItemIntoView(itemsControl, item); itemsControl.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(onBringIntoView)); } } 

Page 15: Introduction to Windows Presentation Foundation

private static object OnBringItemIntoView(ItemsControl itemsControl, object item) { var element = itemsControl.ItemContainerGenerator. ContainerFromItem(item) as FrameworkElement; if (element != null) { element.BringIntoView(); } return null; }}  

WPF Calendar Control

Introduction

Since WPF 4.0, Microsoft provides a full featured calendar control. It provides the following

features:

Set the displayed date

Multiple selection modes

Blackout dates

Calendar Modes

Set the displayed date

The calendar displays by default the current date. But you can specify any other date to be

displayed by setting theDisplayDate property.

 <Calendar DisplayDate="01.01.2010" />  

Selection Modes

Page 16: Introduction to Windows Presentation Foundation

The calendar control provides multiple modes for selection. You can set

the SelectionMode property toSingleDateSingleRange, MultipleRanges or None.

 <Calendar SelectionMode="MultipleRange" />  

Blackout dates

The calendar control provides a feature to black out dates that are not valid for selection.

You can define multiple ranges by setting the BlackoutDates property to one or

multiple CalendarDateRange.

 <Calendar SelectionMode="{Binding SelectedItem, ElementName=selectionmode}" > <Calendar.BlackoutDates> <CalendarDateRange Start="01/01/2010" End="01/06/2010" /> <CalendarDateRange Start="05/01/2010" End="05/03/2010" /> </Calendar.BlackoutDates></Calendar>  

Calendar Modes

Page 17: Introduction to Windows Presentation Foundation

The calendar supports three modes to display ranges of dates: Year, Month and Decade. You

can control the mode by setting the DisplayMode property.

 <Calendar DisplayMode="Year" />  

ComboBox with Live Preview

The Live Preview Pattern

If you are using Microsoft Office 2007 or later, you are familiar with the "live preview"

concept. They are using it for all kind of selections like color, fonttype or fontsize. The idea

behind this pattern is to give the user an immediate feedback, how the object would look

like, if he does the selection, without actually doing it. So he can leave the combo and

nothing has changed.

Page 18: Introduction to Windows Presentation Foundation

How to use the LivePreviewComboBox Control

I encapsulated this functionality into a custom control called LivePreviewComboBox that

provides an additional dependency property LivePreviewItem where you can bind to. The

following code snipped explains how to use it:

 <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:LivePreviewComboBox">  <StackPanel> <TextBlock Text="Preview Value:" /> <TextBlock Text="{Binding LivePreviewItem, ElementName=liveBox}" /> <l:LivePreviewComboBox x:Name="liveBox"/> </StackPanel> </Window>  

Download the LivePreviewCombo Control

WPF Slider Control

How to Make a Slider Snap to Integer Values

If you just set the Minimum and Maximum of a slider and choose a value the result is

determined by the pixel position of the thumb. The value is typically a high-precision value

with many decimal places. To allow only integer values you have to set

the IsSnapToTickEnabled property to True.

<Slider Minimum="0" Maximum="20" IsSnapToTickEnabled="True" TickFrequency="2" 

WPF Expander Control

Introduction

Page 19: Introduction to Windows Presentation Foundation

The Expander control is like a GroupBox but with the additional feature to collapse and

expand its content. It derives from HeaderedContentControlso it has a Header property to

set the header content, and a Content property for the expandable content.

It has a IsExpanded property to get and set if the expander is in expanded or collapsed

state.

In collapsed state the expander takes only the space needed by the header. In expanded

state it takes the size of header and content together.

 <Expander Header="More Options"> <StackPanel Margin="10,4,0,0"> <CheckBox Margin="4" Content="Option 1" /> <CheckBox Margin="4" Content="Option 2" /> <CheckBox Margin="4" Content="Option 3" /> </StackPanel></Expander>  

WPF PasswordBox Control

The password box control is a special type of TextBox designed to enter passwords. The

typed in characters are replaced by asterisks. Since the password box contains a sensible

password it does not allow cut, copy, undo and redo commands.

 <StackPanel> <Label Content="Password:" /> <PasswordBox x:Name="passwordBox" Width="130" /></StackPanel>  

Page 20: Introduction to Windows Presentation Foundation

Change the password character

To replace the asteriks character by another character, set the PasswordChar property to

the character you desire.

 <PasswordBox x:Name="passwordBox" PasswordChar="*" />  

Limit the length of the password

To limit the length of the password a user can enter set the MaxLength property to the

amount of characters you allow.

 <PasswordBox x:Name="passwordBox" MaxLength="8" />  

Databind the Password Property of a WPF PasswordBox

When you try to databind the password property of a PasswordBox you will recognize that

you cannot do data binding on it. The reason for this is, that the password property is not

backed by a DependencyProperty.

The reason is databinding passwords is not a good design for security reasons and should be

avoided. But sometimes this security is not necessary, then it's only cumbersome that you

cannot bind to the password property. In this special cases you can take advantage of the

following PasswortBoxHelper.

 <StackPanel> <PasswordBox w:PasswordHelper.Attach="True" w:PasswordHelper.Password="{Binding Text, ElementName=plain, Mode=TwoWay}" Width="130"/> <TextBlock Padding="10,0" x:Name="plain" /></StackPanel>  

The PasswordHelper is attached to the password box by calling

the PasswordHelper.Attach property. The attached

Page 21: Introduction to Windows Presentation Foundation

property PasswordHelper.Password provides a bindable copy of the original password

property of the PasswordBox control.

 public static class PasswordHelper{ public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached("Password", typeof(string), typeof(PasswordHelper), new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));  public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached("Attach", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, Attach));  private static readonly DependencyProperty IsUpdatingProperty = DependencyProperty.RegisterAttached("IsUpdating", typeof(bool), typeof(PasswordHelper));   public static void SetAttach(DependencyObject dp, bool value) { dp.SetValue(AttachProperty, value); }  public static bool GetAttach(DependencyObject dp) { return (bool)dp.GetValue(AttachProperty); }  public static string GetPassword(DependencyObject dp) { return (string)dp.GetValue(PasswordProperty); }  public static void SetPassword(DependencyObject dp, string value) { dp.SetValue(PasswordProperty, value); }  private static bool GetIsUpdating(DependencyObject dp) { return (bool)dp.GetValue(IsUpdatingProperty); }  private static void SetIsUpdating(DependencyObject dp, bool value)

Page 22: Introduction to Windows Presentation Foundation

{ dp.SetValue(IsUpdatingProperty, value); }  private static void OnPasswordPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = sender as PasswordBox; passwordBox.PasswordChanged -= PasswordChanged;  if (!(bool)GetIsUpdating(passwordBox)) { passwordBox.Password = (string)e.NewValue; } passwordBox.PasswordChanged += PasswordChanged; }  private static void Attach(DependencyObject sender, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = sender as PasswordBox;  if (passwordBox == null) return;  if ((bool)e.OldValue) { passwordBox.PasswordChanged -= PasswordChanged; }  if ((bool)e.NewValue) { passwordBox.PasswordChanged += PasswordChanged; } }  private static void PasswordChanged(object sender, RoutedEventArgs e) { PasswordBox passwordBox = sender as PasswordBox; SetIsUpdating(passwordBox, true); SetPassword(passwordBox, passwordBox.Password); SetIsUpdating(passwordBox, false); }}  

Page 23: Introduction to Windows Presentation Foundation

Context Menus in WPF

Context Menus can be defined on any WPF controls by setting the ContextMenu property to

an instance of aContextMenu. The items of a context menu are normal MenuItems.

 <RichTextBox> <RichTextBox.ContextMenu> <ContextMenu> <MenuItem Command="Cut"> <MenuItem.Icon> <Image Source="Images/cut.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Command="Copy"> <MenuItem.Icon> <Image Source="Images/copy.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Command="Paste"> <MenuItem.Icon> <Image Source="Images/paste.png" /> </MenuItem.Icon> </MenuItem> </ContextMenu> </RichTextBox.ContextMenu></RichTextBox>  

Show ContextMenus on a disabled controls

If you rightclick on a disabled control, no context menu is shown by default. To enable the

context menu for disabled controls you can set the ShowOnDisabled attached property of

the ContextMenuService to True.

 <RichTextBox IsEnabled="False" ContextMenuService.ShowOnDisabled="True"> <RichTextBox.ContextMenu> <ContextMenu>

Page 24: Introduction to Windows Presentation Foundation

... </ContextMenu> </RichTextBox.ContextMenu></RichTextBox>  

Merge ContextMenus

If you want to fill a menu with items coming from multiple sources, you can use

the CompositeCollection to merge multiple collection into one.

 <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib"> <Grid Background="Transparent"> <Grid.Resources> <x:Array Type="{x:Type sys:Object}" x:Key="extensions"> <Separator /> <MenuItem Header="Extension MenuItem 1" /> <MenuItem Header="Extension MenuItem 2" /> <MenuItem Header="Extension MenuItem 3" /> </x:Array> </Grid.Resources> <Grid.ContextMenu> <ContextMenu> <ContextMenu.ItemsSource> <CompositeCollection> <MenuItem Header="Standard MenuItem 1" /> <MenuItem Header="Standard MenuItem 2" /> <MenuItem Header="Standard MenuItem 3" /> <CollectionContainer Collection="{StaticResource extensions}" /> </CompositeCollection> </ContextMenu.ItemsSource> </ContextMenu> </Grid.ContextMenu> </Grid></Window>  

How to open a context menu from code

Page 25: Introduction to Windows Presentation Foundation

The following sample shows you how to open a context menu of a control programmatically:

 private void OpenContextMenu(FrameworkElement element){ if( element.ContextMenu != null ) { element.ContextMenu.PlacementTarget = element; element.ContextMenu.IsOpen = true; }}  

WPF TextBox

How to enable spell checking

TextBox and RichTextBox provide an out-of-the-box spell checking functionality. It is

available for the following languages: English, Spanish, German and French. It can be

enabled by setting the attached property SpellCheck.IsEnabled to true.

  <TextBox SpellCheck.IsEnabled="True" Language="en-US" />  

How to validate input

Page 26: Introduction to Windows Presentation Foundation

By using a regular expression, you can easily limit and validate the input of the user. The

following code snippet shows how to do it:

 protected override void OnTextInput(TextCompositionEventArgs e){ string fullText = Text.Remove(SelectionStart, SelectionLength) + e.Text; if (_regex != null && !_regex.IsMatch(fullText)) { e.Handled = true; } else { base.OnTextInput(e); }}  

Menus in WPF

Menu

The Menu control derives from HeaderedItemsControl. It stacks it items horizontally and

draws the typical gray background. The only property that the Menu adds

to ItemsControl is the IsMainMenu property. This controls if the menu grabs the focus if the

user presses F10 or the ALT key.

 <Menu IsMainMenu="True"> <MenuItem Header="_File" /> <MenuItem Header="_Edit" /> <MenuItem Header="_View" /> <MenuItem Header="_Window" /> <MenuItem Header="_Help" /></Menu>  

MenuItem

The MenuItem is a HeaderedItemsControl. The content of the Header property is the

caption of the menu. The Itemsof a MenuItems are its sub menus. The Icon property

Page 27: Introduction to Windows Presentation Foundation

renders a second content on the left of the caption. This is typically used to draw a little

image. But it can be used for type of content.

You can define a keyboard shortcut by adding an underscore in front of a character.

 <MenuItem Header="_Edit"> <MenuItem Header="_Cut" Command="Cut"> <MenuItem.Icon> <Image Source="Images/cut.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Header="_Copy" Command="Copy"> <MenuItem.Icon> <Image Source="Images/copy.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Header="_Paste" Command="Paste"> <MenuItem.Icon> <Image Source="Images/paste.png" /> </MenuItem.Icon> </MenuItem></MenuItem>  

Checkable MenuItems

You can make a menu item checkable by setting the IsCheckable property to true. The

check state can be queried by theIsChecked property. To get notified when the check state

changes you can add a handler to the Checked andUnchecked property.

 <MenuItem Header="_Debug"> <MenuItem Header="Enable Debugging" IsCheckable="True" /></MenuItem>  

Page 28: Introduction to Windows Presentation Foundation

Separators

Separator is a simple control to group menu items. It's rendered as a horizontal line. It can

also be used in ToolBar andStatusBar.

 <Menu> <MenuItem Header="_File"> <MenuItem Header="_New..." /> <Separator /> <MenuItem Header="_Open..." /> <Separator /> <MenuItem Header="_Save" /> <MenuItem Header="_Save As..." /> <Separator /> <MenuItem Header="_Exit" /> </MenuItem></Menu>  

Callbacks

You can register a callback to any menu item by adding a callback to the Click event.

 <Menu> <MenuItem Header="_File"> <MenuItem Header="_New..." Click="New_Click"/> </MenuItem></Menu>  

 private void New_Click(object sender, RoutedEventArgs e)

Page 29: Introduction to Windows Presentation Foundation

{ MessageBox.Show("You clicked 'New...'");}  

How to bind MenuItems dynamically using MVVM

If you are using the model-view-viewmodel pattern, you probably want to define the

available menu command dynamically in your code and then bind them to

a MenuItem control. The following sample shows you how to do this:

 <Menu> <Menu.Resources> <Style x:Key="ThemeMenuItemStyle" TargetType="MenuItem"> <Setter Property="Header" Value="{Binding Name}"></Setter> <Setter Property="Command" Value="{Binding ActivateCommand}"/> <Setter Property="IsChecked" Value="{Binding IsActive}" /> <Setter Property="IsCheckable" Value="True"/> </Style> </Menu.Resources> <MenuItem Header="Themes" ItemsSource="{Binding Themes}" ItemContainerStyle="{StaticResource ThemeMenuItemStyle}" /></Menu>  

Keyboard Shortcuts

To add a keyboard shortcut to a menu item, add a underscode "_" in front of the caracter

you want to use as your hot key. This automatically sets the InputGestureText to an

appropriate value. But you can also override the proposed text by setting this property to a

text of your choice.

Popup Control

Introduction follows...

How to make the popup close, when it loses focus

Just set the StaysOpen property to False. Unfortunately this is not the default behavior

<Popup StaysOpen="False" />

Page 30: Introduction to Windows Presentation Foundation

 

ToolTips in WPF

 <Button Content="Submit"> <Button.ToolTip> <ToolTip> <StackPanel> <TextBlock FontWeight="Bold">Submit Request</TextBlock> <TextBlock>Submits the request to the server.</TextBlock> </StackPanel> </ToolTip> </Button.ToolTip></Button>  

How to show ToolTips on disabled controls

When you disable a control with IsEnabled=False the tooltip does not show anymore. If you

want to have the tooltip appear anyway you have to set the attaached

property ToolTipService.ShowOnDisabled to True.

 <Button IsEnabled="False" ToolTip="Saves the current document" ToolTipService.ShowOnDisabled="True" Content="Save"></Button>  

How to change the show duration of a ToolTip

The static class ToolTipService allows you to modify the show duration of the tooltip

 <Button ToolTip="Saves the current document"

Page 31: Introduction to Windows Presentation Foundation

ToolTipService.ShowDuration="20" Content="Save"></Button>  

dio Button

Introduction

The RadioButton control has its name from old analog radios which had a number of

programmable station buttons. When you pushed one in, the previosly selected poped out.

So only one station can be selected at a time.

The RadioButton control has the same behavior. It lets the user choose one option out of

a few. It the list of options gets longer, you should prefer a combo or list box instead.

To define which RadioButtons belong togehter, you have to set the GroupName to the same

name.

To preselect one option set the IsChecked property to True.

<StackPanel> <RadioButton GroupName="Os" Content="Windows XP" IsChecked="True"/> <RadioButton GroupName="Os" Content="Windows Vista" /> <RadioButton GroupName="Os" Content="Windows 7" /> <RadioButton GroupName="Office" Content="Microsoft Office 2007" IsChecked="True"/> <RadioButton GroupName="Office" Content="Microsoft Office 2003"/> <RadioButton GroupName="Office" Content="Open Office"/></StackPanel> 

Page 32: Introduction to Windows Presentation Foundation

How to DataBind Radio Buttons in WPF

The radio button control has a known issue with data binding. If you bind

the IsChecked property to a boolean and check the RadioButton, the value gets True. But

when you check another RadioButton, the databound value still remains true.

The reason for this is, that the Binding gets lost during the unchecking, because the controls

internally calls ClearValue()on the dependency property.

 <Window.Resources> <EnumMatchToBooleanConverter x:Key="enumConverter" /></Window.Resources>  <RadioButton Content="Option 1" GroupName="Options1" IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, Converter={StaticResource enumConverter}, ConverterParameter=Option1}" /><RadioButton Content="Option 2" GroupName="Options2" IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, Converter={StaticResource enumConverter}, ConverterParameter=Option2}" /><RadioButton Content="Option 3" GroupName="Options3" IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, Converter={StaticResource enumConverter}, ConverterParameter=Option3}" />  

 public class EnumMatchToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || parameter == null) return false;  string checkValue = value.ToString(); string targetValue = parameter.ToString(); return checkValue.Equals(targetValue, StringComparison.InvariantCultureIgnoreCase); }  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

Page 33: Introduction to Windows Presentation Foundation

{ if (value == null || parameter == null) return null;  bool useValue = (bool)value; string targetValue = parameter.ToString(); if (useValue) return Enum.Parse(targetType, targetValue);  return null; } }   

WPF ListView Control

How to Hide the Header of a ListView

To hide the header of a ListView you can modify the Visibility property of the

ColumnHeaderContainer by overriding the style locally.

<ListView> <ListView.View> <GridView> <GridView.ColumnHeaderContainerStyle> <Style> <Setter Property="FrameworkElement.Visibility" Value="Collapsed"/> </Style> </GridView.ColumnHeaderContainerStyle> <GridView.Columns> ... </GridView.Columns> </GridView> </ListView.View></ListView> 

Page 34: Introduction to Windows Presentation Foundation

How to Create a WPF Custom Control

This article gives you a step by step walktrough how to create a custom control in WPF. If

you don't know the differences between a user control and a custom control, I recommend

to read the article Custom Control vs. User Control first.

1. Define Requirements

Creating a custom control is quite simple in WPF. But the challenge is to do it the right way.

So before you start creating a control try to answer the following questions:

What problem should my control solve?

Who will use this control? In which context and environment?

Can I extend or compose existing controls? Have a look at Existing Controls?

Should it be possible to style or template my control?

What design-time support should it have? In Expression Blend and Visual Studio?

Is it used in a single project, or part of a reusable library?

2. Create Project Structures

Create a new solution in VisualStudio and start with a WPF Custom Control Library and give

it the name PopupControlLib. This is the place where our custom control comes in. Next we

create an WPF Application and call it PopupControlTest. This is place where we test our

control in a simple application.

Page 35: Introduction to Windows Presentation Foundation

1. Create a new solution and start with a WPF Custom Control Library. Call it

"PopupControlLib".

2. Add a second project of type WPF Application to the solution and call it

"PopupControlTest".

3. Add a reference to the custom control library by using the "Add Reference" context

menu entry on the "PopupControlTest" project item in the solution explorer.

4. Rename the CustomControl1 to PopupControl.

3. Choose the right base class

Choosing the right base class is crucial and can save a lot of time! Compare the features of

your control with existing controls and start with one that matches close. The following list

should give you a good overview from the most leightweight to more heavyweight base

types:

UIElement - The most lightweight base class to start from. It has support for LIFE -

Layout, Input, Focus and Events.

FrameworkElement - Derives from UIElement and adds support for styling, tooltips

and context menus. It is first base class that takes part in the logical tree and so it

supports data binding and resource lookup.

Control - is the most common base class for controls (its name speaks for itself). It

supports templates and adds some basic properties

as Foreground, Background or FontSize.

ContentControl - is a control that has an additional Content property. This is often

used for simple containers.

HeaderedContentControl - is a control that has an Content and a Header property.

This is used for controls with a header like Expander, TabControl, GroupBox,...

ItemsControl - a control that has an additional Items collection. This is a good

choice for controls that display a dynamic list of items without selection.

Selector - an ItemsControl whose items can be indexed and selected. This is used

for ListBox, ComboBox, ListView, TabControl...

Page 36: Introduction to Windows Presentation Foundation

RangeBase - is the base class for controls that display a value range like Sliders or

ProgressBars. It adds an Value,Minimum and Maximum property.

4. Override the Default Style

Controls in WPF separate behavior and appearance. The behavior is defined in code. The

template is defined in XAML. The default template is by convention wrapped into a style that

has an implicit key. That is is not a string - as usually - but aType object of our control.

And that is excactly what we are doing in the static constructor. We are overriding the

default value of theDefaultStyleKey property and set it to the Type object of our control.

 static PopupControl(){ DefaultStyleKeyProperty.OverrideMetadata(typeof(PopupControl), new FrameworkPropertyMetadata(typeof(PopupControl)));}  

5. Create a default Style

The style must be located by convention in a folder called "Themes" that must be located in

the root of the control library project. In these folder we can provide different templates for

each Windows theme. The name of these ResourceDictionaries must match the name of the

windows theme. If we do not provide any theme-specific styles, we need to provide the

fallback style located in the "Generic.xaml" file.

As we set the default value of the DefaultStylekey property to the Type object of our

control, we must give our default style the same key to be found. This is done by leaving

the x:Key attribute out. In this case WPF uses the type object from the TargetType property

as key.

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">  <Style TargetType="{x:Type local:PopupControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:PopupControl}"> ...

Page 37: Introduction to Windows Presentation Foundation

</ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>  

5. Add DependencyProperties

 #region DependencyProperty Content /// <summary>/// Registers a dependency property as backing store for the Content property/// </summary>public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(PopupControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsParentMeasure)); /// <summary>/// Gets or sets the Content./// </summary>/// <value>The Content.</value>public object Content{ get { return (object)GetValue(ContentProperty); } set { SetValue(ContentProperty, value); }} #endregion  

6. Map XML Namespace

Content follows...

7. Logical and Visual Children

Page 38: Introduction to Windows Presentation Foundation

Calling AddLogicalChild() creates the connection to navigate up the logical tree

(bubbling).

Overriding GetLogicalChildren creates the connection to navigate down the

logical tree (tunneling).

Themes in WPF

Introduction

This article will follow soon...

How to use specific Windows theme in a WPF application

WPF includes all common Windows themes. By default WPF loads the current Windows

theme as your default style-set. But you can override these styles by loading a specific

theme. To do this you first have to add an reference to the style assembly you like to use

and second you need to merge the theme resource dictionary into your app resources. This

overrides the default style-set that has been loaded by WPF.

The following exmple shows how to load the Windows Vista Aero theme.

<App.Resources> <ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" /></App.Resources> 

Control Templates

Page 39: Introduction to Windows Presentation Foundation

Introduction

Controls in WPF are separated into logic, that defines the states, events and properties

and template, that defines the visual appearance of the control. The wireup between the

logic and the template is done by DataBinding.

Each control has a default template. This gives the control a basic appearance. The default

template is typically shipped together with the control and available for all common windows

themes. It is by convention wrapped into a style, that is identified by value of

the DefaultStyleKey property that every control has.

The template is defined by a dependency property called Template. By setting this property

to another instance of a control template, you can completely replace the appearance

(visual tree) of a control.

 

The control template is often included in a style that contains other property settings. The

following code sample shows a simple control template for a button with an ellipse shape.

 <Style x:Key="DialogButtonStyle" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Grid> <Ellipse Fill="{TemplateBinding Background}"

Page 40: Introduction to Windows Presentation Foundation

Stroke="{TemplateBinding BorderBrush}"/> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </ControlTemplate> </Setter.Value> </Setter></Style>   <Button Style="{StaticResource DialogButtonStyle}" />  

A Button without and with a custom control template

ContentPresenter

When you create a custom control template and you want to define a placeholder that

renders the content, you can use theContentPresenter. 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

Page 41: Introduction to Windows Presentation Foundation

{RelativeSource TemplatedParent} not working in DataTriggers of a ControlTemplate

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, thatTemplatedParent 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!.