Beruflich Dokumente
Kultur Dokumente
Foundation
Overview
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:
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.
How to create a simple WPF application
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
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.
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.
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:
<StackPanel>
<TextBlock Margin="20">Welcome to the World of XAML</TextBlock>
<Button Margin="10" HorizontalAlignment="Right">OK</Button>
</StackPanel>
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 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.
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.
• 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.
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.
WPF uses a right-handed coordinate system. This means that if you hold the fingers of your
right hand as shown on the picture, the fingers indicate the positive direction of the tree
axes.
Elements of a 3D scene
• Viewport3D
The viewport is the control that builds the gate between the 2D and the 3D world.
• Camera
Every 3D scene has excactly one camera. The camera defines the Position and
the LookDirection and 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
The following example shows how to create a basic cube mesh with 8 vertices that are wired
up in 12 triangles that form the shape of the cube.
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera Position="-40,40,40" LookDirection="40,-40,-40 "
UpDirection="0,0,1" />
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<DirectionalLight Color="White" Direction="-1,-1,-3" />
<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
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
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>
ItemsControl
if (itemsControl != null)
{
itemsControl.ItemContainerGenerator.StatusChanged +=
(s,a) => OnItemsChanged(itemsControl,s,a);
}
}
Introduction
Since WPF 4.0, Microsoft provides a full featured calendar control. It provides the following
features:
The calendar displays by default the current date. But you can specify any other date to be
displayed by setting theDisplayDate property.
Selection Modes
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 Modes
The calendar supports three modes to display ranges of dates: Year, Month and Decade. You
can control the mode by setting the DisplayMode property.
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.
How to use the LivePreviewComboBox Control
<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>
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"
Introduction
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.
<StackPanel>
<Label Content="Password:" />
<PasswordBox x:Name="passwordBox" Width="130" />
</StackPanel>
Change the password character
To replace the asteriks character by another character, set the PasswordChar property to
the character you desire.
To limit the length of the password a user can enter set the MaxLength property to the
amount of characters you allow.
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>
if (!(bool)GetIsUpdating(passwordBox))
{
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += PasswordChanged;
}
if (passwordBox == null)
return;
if ((bool)e.OldValue)
{
passwordBox.PasswordChanged -= PasswordChanged;
}
if ((bool)e.NewValue)
{
passwordBox.PasswordChanged += PasswordChanged;
}
}
<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>
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.
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>
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
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
<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>
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>
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...
Just set the StaysOpen property to False. Unfortunately this is not the default behavior
<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>
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>
The static class ToolTipService allows you to modify the show duration of the tooltip
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.
<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>
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>
return null;
}
}
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>
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:
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.
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.
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...
• RangeBase - is the base class for controls that display a value range like Sliders or
ProgressBars. It adds an Value,Minimum and Maximum property.
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)));
}
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">
</ResourceDictionary>
5. Add DependencyProperties
/// <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
Content follows...
Introduction
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
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.
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
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!.