Dotnet Desktop WPF Controls Netframeworkdesktop 4.8
Dotnet Desktop WPF Controls Netframeworkdesktop 4.8
Controls
Article • 02/06/2023
WPF SDK continues to use the term "control" to loosely mean any class that represents a
visible object in an application, it is important to note that a class does not need to
inherit from the Control class to have a visible presence. Classes that inherit from the
Control class contain a ControlTemplate, which allows the consumer of a control to
radically change the control's appearance without having to create a new subclass. This
topic discusses how controls (both those that do inherit from the Control class and
those that do not) are commonly used in WPF.
XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label>
Enter your first name:
</Label>
<TextBox Grid.Row="0" Grid.Column="1"
Name="firstName" Margin="0,5,10,5"/>
The following example creates the same application in code. For brevity, the creation of
the Grid, grid1 , has been excluded from the sample. grid1 has the same column and
row definitions as shown in the preceding XAML example.
C#
Label firstNameLabel;
Label lastNameLabel;
TextBox firstName;
TextBox lastName;
Button submit;
Button clear;
void CreateControls()
{
firstNameLabel = new Label();
firstNameLabel.Content = "Enter your first name:";
grid1.Children.Add(firstNameLabel);
XAML
</Button.Background>
View message
</Button>
C#
submit.Background = buttonBrush;
submit.FontSize = 14;
submit.FontWeight = FontWeights.Bold;
XAML
<Style TargetType="Button">
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="Green" Offset="0.0" />
<GradientStop Color="White" Offset="0.9" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
You can also apply a style to only certain controls of a specific type by assigning a key to
the style and specifying that key in the Style property of your control. For more
information about styles, see Styling and Templating.
Creating a ControlTemplate
A Style allows you to set properties on multiple controls at a time, but sometimes you
might want to customize the appearance of a Control beyond what you can do by
creating a Style. Classes that inherit from the Control class have a ControlTemplate,
which defines the structure and appearance of a Control. The Template property of a
Control is public, so you can give a Control a ControlTemplate that is different than its
default. You can often specify a new ControlTemplate for a Control instead of inheriting
from a control to customize the appearance of a Control.
Consider the very common control, Button. The primary behavior of a Button is to
enable an application to take some action when the user clicks it. By default, the Button
in WPF appears as a raised rectangle. While developing an application, you might want
to take advantage of the behavior of a Button--that is, by handling the button's click
event--but you might change the button's appearance beyond what you can do by
changing the button's properties. In this case, you can create a new ControlTemplate.
XAML
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
7 Note
The Background property of the Button must be set to a SolidColorBrush for the
example to work properly.
Subscribing to Events
You can subscribe to a control's event by using either XAML or code, but you can only
handle an event in code. The following example shows how to subscribe to the Click
event of a Button.
XAML
C#
C#
void submit_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text);
}
ContentControl-- Some examples of classes that inherit from this class are Label,
Button, and ToolTip.
ItemsControl-- Some examples of classes that inherit from this class are ListBox,
Menu, and StatusBar.
For more information about these base classes, see WPF Content Model.
See also
Styling and Templating
Controls by Category
Control Library
Data Templating Overview
Data Binding Overview
Input
Enable a Command
Walkthroughs: Create a Custom Animated Button
Control Customization
Controls by Category
Article • 02/06/2023
Windows Presentation Foundation (WPF) controls can be logically grouped into several
categories. These categories can be used to select the appropriate control for your
scenario by helping you see which controls have similar usage patterns or functionality.
Layout
Layout controls are used to manage the size, dimensions, position, and arrangement of
child elements.
Border
BulletDecorator
Canvas
DockPanel
Expander
Grid
GridSplitter
GroupBox
Panel
ResizeGrip
Separator
ScrollBar
ScrollViewer
StackPanel
Thumb
Viewbox
VirtualizingStackPanel
Window
WrapPanel
Buttons
Buttons are one of the most basic user interface controls. Applications typically perform
some task in the Click event when a user clicks on them.
Button
RepeatButton
Data Display
Data display controls are used to show information from a data source.
DataGrid
ListView
TreeView
Calendar
DatePicker
Menus
Menus are used to group related actions or to provide contextual assistance.
ContextMenu
Menu
ToolBar
Selection
Selection controls are used to enable a user to select one or more options.
CheckBox
ComboBox
ListBox
RadioButton
Slider
Navigation
Navigation controls enhance or extend the application navigation experience by
creating targeting frames or tabbed application appearance.
Frame
Hyperlink
Page
NavigationWindow
TabControl
Dialog Boxes
Dialog boxes provide targeted support for common user-interaction scenarios such as
printing.
OpenFileDialog
PrintDialog
SaveFileDialog
User Information
User information controls provide contextual feedback or clarify an application's user
interface. The user typically cannot interact with these controls.
AccessText
Label
Popup
ProgressBar
StatusBar
TextBlock
ToolTip
Documents
WPF includes several specialized controls for viewing documents. These controls
optimize the reading experience, based on the targeted user scenario.
DocumentViewer
FlowDocumentPageViewer
FlowDocumentReader
FlowDocumentScrollViewer
StickyNoteControl
Input
Input controls enable the user to input text and other content.
TextBox
RichTextBox
PasswordBox
Media
WPF includes integrated support for hosting both audio and video content, as well as
[codecs] for most popular image formats.
Image
MediaElement
SoundPlayerAction
Digital Ink
Digital ink controls provide integrated support for Tablet PC features, such as ink
viewing and ink input.
InkCanvas
InkPresenter
See also
Control Library
WPF Content Model
Article • 02/06/2023
This topic summarizes the content model for WPF control and control-like types. The
content model describes what content can be used in a control. This topic also lists the
content properties for each content model. A content property is a property that is used
to store the content of the object.
WPF has four classes that can contain arbitrary content. The following table lists the
classes, which inherit from Control.
Controls that inherit from these classes can contain the same type of content and treat
the content in the same way. The following illustration shows one control from each
content model that contains an image and some text:
Controls That Contain a Single Arbitrary Object
The ContentControl class contains a single piece of arbitrary content. Its content
property is Content. The following controls inherit from ContentControl and use its
content model:
Button
ButtonBase
CheckBox
ComboBoxItem
ContentControl
Frame
GridViewColumnHeader
GroupItem
Label
ListBoxItem
ListViewItem
NavigationWindow
RadioButton
RepeatButton
ScrollViewer
StatusBarItem
ToggleButton
ToolTip
UserControl
Window
The following illustration shows four buttons whose Content is set to a string, a
DateTime object, a Rectangle, and a Panel that contains an Ellipse and a TextBlock:
The following controls inherit from HeaderedContentControl and use its content model:
Expander
GroupBox
TabItem
The following illustration shows two TabItem objects. The first TabItem has UIElement
objects as the Header and the Content. The Header is set to a StackPanel that contains
an Ellipse and a TextBlock. The Content is set to a StackPanel that contains a TextBlock
and a Label. The second TabItem has a string in the Header and a TextBlock in the
Content.
For an example of how to create TabItem objects, see HeaderedContentControl.
The following controls inherit from ItemsControl and use its content model:
Menu
MenuBase
ContextMenu
ComboBox
ItemsControl
ListBox
ListView
TabControl
TreeView
Selector
StatusBar
The following illustration shows a ListBox that contains these types of items:
A string.
A DateTime object.
A UIElement.
The following controls inherit from HeaderedItemsControl and use its content model:
MenuItem
ToolBar
TreeViewItem
The following classes inherit from the Panel class and use its content model:
Canvas
DockPanel
Grid
TabPanel
ToolBarOverflowPanel
ToolBarPanel
UniformGrid
StackPanel
VirtualizingPanel
VirtualizingStackPanel
WrapPanel
AdornerDecorator
Border
BulletDecorator
ButtonChrome
ClassicBorderDecorator
InkPresenter
ListBoxChrome
SystemDropShadowChrome
Viewbox
The following illustration shows a TextBox that has (is decorated with) a Border around
it.
TextBlock that has a Border
The TextBlock has two content properties: Text and Inlines. When you want to display
text that uses consistent formatting, the Text property is often your best choice. If you
plan to use different formatting throughout the text, use the Inlines property. The Inlines
property is a collection of Inline objects, which specify how to format text.
The following table lists the content property for FlowDocumentReader,
FlowDocumentPageViewer, and FlowDocumentScrollViewer classes.
See also
Advanced
Control Library
Article • 02/06/2023
The Windows Presentation Foundation (WPF) control library contains information on the
controls provided by Windows Presentation Foundation (WPF), listed alphabetically.
In This Section
Border
BulletDecorator
Button
Calendar
Canvas
CheckBox
ComboBox
ContextMenu
DataGrid
DatePicker
DockPanel
DocumentViewer
Expander
FlowDocumentPageViewer
FlowDocumentReader
FlowDocumentScrollViewer
Frame
Grid
GridSplitter
GroupBox
Image
Label
ListBox
ListView
Menu
Panel
PasswordBox
Popup
ProgressBar
PrintDialog
RadioButton
RepeatButton
RichTextBox
ScrollBar
ScrollViewer
Separator
Slider
StackPanel
StatusBar
TabControl
TextBlock
TextBox
ToolBar
ToolTip
TreeView
WrapPanel
Viewbox
Reference
System.Windows.Controls
System.Windows.Controls.Primitives
Related Sections
Control Customization
Controls by Category
The following sample demonstrates how to dynamically change properties of the Border
element.
In This Section
Animate a BorderThickness Value
Reference
Decorator
Border
Related Sections
Panels Overview
This example shows how to animate changes to the thickness of a border by using the
ThicknessAnimation class.
Example
The following example animates the thickness of a border by using ThicknessAnimation.
The example uses the BorderThickness property of Border.
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media;
namespace SDKSamples
{
public class ThicknessAnimationExample : Page
{
public ThicknessAnimationExample()
{
Content = myStackPanel;
}
}
}
See also
ThicknessAnimation
BorderThickness
Border
Animation Overview
Animation and Timing How-to Topics
Animate the Thickness of a Border by Using Key Frames
BulletDecorator
Article • 02/06/2023
BulletDecorator has two content properties: Bullet and Child. The Bullet property defines
the UIElement to use as a bullet. The Child property defines a UIElement that visually
aligns with the bullet.
Reference
BulletDecorator
Button
Article • 02/06/2023
A Button control reacts to user input from a mouse, keyboard, stylus, or other input
device and raises a Click event. A Button is a basic user interface (UI) component that
can contain simple content, such as text, and can also contain complex content, such as
images and Panel controls.
In This Section
Create a Button That Has an Image
Reference
Button
ButtonBase
RadioButton
RepeatButton
How to: Create a Button That Has an
Image
Article • 02/06/2023
Example
The following example creates two Button controls. One Button contains text and the
other contains an image. The image is in a folder called data, which is a subfolder of the
example’s project folder. When a user clicks the Button that has the image, the
background and the text of the other Button change.
This example creates Button controls by using markup but uses code to write the Click
event handlers.
XAML
C#
See also
Controls
Control Library
Calendar
Article • 02/06/2023
The following illustration shows two Calendar controls, one with selections and blackout
dates and one without.
Calendar controls
The following table provides information about tasks that are typically associated with
the Calendar.
Task Implementation
Have the Calendar display a Set the DisplayMode property to Month, Year, or Decade.
month, an entire year, or a
decade.
Specify the range of dates Use the DisplayDateStart and DisplayDateEnd properties.
that the Calendar displays.
Change the size of the Use a Viewbox or set the LayoutTransform property to a
Calendar. ScaleTransform. Note that if you set the Width and Height
properties of a Calendar, the actual calendar does not change its
size.
The Calendar control provides basic navigation using either the mouse or keyboard. The
following table summarizes keyboard navigation.
ARROW Year Changes the month of the DisplayDate property. Note that the
SelectedDate does not change.
ARROW Decade Changes the year of the DisplayDate. Note that the
SelectedDate does not change.
HOME Month Changes the SelectedDate to the first day of the current month.
HOME Year Changes the month of the DisplayDate to the first month of the
year. The SelectedDate does not change.
HOME Decade Changes the year of the DisplayDate to the first year of the
decade. The SelectedDate does not change.
END Month Changes the SelectedDate to the last day of the current month.
END Year Changes the month of the DisplayDate to the last month of the
year. The SelectedDate does not change.
END Decade Changes the year of the DisplayDate to the last year of the
decade. The SelectedDate does not change.
In This Section
How-to Topics
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
Canvas How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the Canvas element to absolutely position
child elements.
In This Section
Wrap a Border Around the Content of a Canvas
Get or Set Canvas Positioning Properties
Create and Use a Canvas
Use the Attached Properties of Canvas to Position Child Elements
Resize a Canvas by Using a Thumb
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
How to: Wrap a Border Around the
Content of a Canvas
Article • 02/06/2023
Example
The following example shows how to display Hello World! inside a Canvas element. The
Canvas element is wrapped by a Border element so that a border outlines the element.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Border
BorderThickness="2"
BorderBrush="Black"
Background="LightGray"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="100"
Height="100">
<Canvas>
<TextBlock Canvas.Top="10" Canvas.Left="20">Hello World!</TextBlock>
</Canvas>
</Border>
</Page>
See also
Canvas
Border
Panels Overview
How to: Get or Set Canvas Positioning
Properties
Article • 02/06/2023
This example shows how to use the positioning methods of the Canvas element to
position child content. This example uses content in a ListBoxItem to represent
positioning values and converts the values into instances of Double, which is a required
argument for positioning. The values are then converted back into strings and displayed
as text in a TextBlock element by using the GetLeft method.
Example
The following example creates a ListBox element that has eleven selectable ListBoxItem
elements. The SelectionChanged event triggers the ChangeLeft custom method, which
the subsequent code block defines.
Each ListBoxItem represents a Double value, which is one of the arguments that the
SetLeft method of Canvas accepts. In order to use a ListBoxItem to represent an instance
of Double, you must first convert the ListBoxItem to the correct data type.
XAML
When a user changes the ListBox selection, it invokes the ChangeLeft custom method.
This method passes the ListBoxItem to a LengthConverter object, which converts the
Content of a ListBoxItem to an instance of Double (notice that this value has already
been converted to a String by using the ToString method). This value is then passed
back to the SetLeft and GetLeft methods of Canvas in order to change the position of
the text1 object.
C#
See also
Canvas
ListBoxItem
LengthConverter
Panels Overview
How to: Create and Use a Canvas
Article • 02/06/2023
Example
The following example explicitly positions two TextBlock elements by using the SetTop
and SetLeft methods of Canvas. The example also assigns a Background color of
LightSteelBlue to the Canvas.
7 Note
C#
See also
Canvas
TextBlock
SetTop
SetLeft
Top
Left
Panels Overview
How-to Topics
How to: Use the Attached Properties of
Canvas to Position Child Elements
Article • 02/06/2023
This example shows how to use the attached properties of Canvas to position child
elements.
Example
The following example adds four Button elements as child elements of a parent Canvas.
Each element is represented by a Bottom, Left, Right, and Top. Each Button is positioned
relative to the parent Canvas and according to its assigned property value.
C#
// Add a Border
Border myBorder = new Border();
myBorder.HorizontalAlignment = HorizontalAlignment.Left;
myBorder.VerticalAlignment = VerticalAlignment.Top;
myBorder.BorderBrush = Brushes.Black;
myBorder.BorderThickness = new Thickness(2);
See also
Canvas
Bottom
Left
Right
Top
Button
Panels Overview
How-to Topics
Attached Properties Overview
How to: Resize a Canvas by Using a
Thumb
Article • 02/06/2023
This example shows how to use a Thumb control to resize a Canvas control.
Example
The Thumb control provides drag functionality that can be used to move or resize
controls by monitoring the DragStarted, DragDelta and DragCompleted events of the
Thumb.
The user begins a drag operation by pressing the left mouse button when the mouse
pointer is paused on the Thumb control. The drag operation continues as long as the
left mouse button remains pressed. During the drag operation, the DragDelta can occur
more than once. Each time it occurs, the DragDeltaEventArgs class provides the change
in position that corresponds to the change in mouse position. When the user releases
the left mouse button, the drag operation is finished. The drag operation only provides
new coordinates; it does not automatically reposition the Thumb.
The following example shows a Thumb control that is the child element of a Canvas
control. The event handler for its DragDelta event provides the logic to move the Thumb
and resize the Canvas. The event handlers for the DragStarted and DragCompleted
event change the color of the Thumb during a drag operation. The following example
defines the Thumb.
XAML
The following example shows the DragDelta event handler that moves the Thumb and
resizes the Canvas in response to a mouse movement.
C#
C#
C#
See also
Thumb
DragStarted
DragDelta
DragCompleted
CheckBox
Article • 02/06/2023
You can use a CheckBox in the user interface (UI) of your application to represent
options that a user can select or clear. You can use a single check box or you can group
two or more check boxes.
Reference
CheckBox
RadioButton
ButtonBase
RepeatButton
Related Sections
ComboBox
Article • 02/06/2023
The ComboBox control presents users with a list of options. The list is shown and hidden
as the control expands and collapses. In its default state, the list is collapsed, displaying
only one choice. The user clicks a button to see the complete list of options.
Reference
ComboBox
ContextMenu
Article • 02/06/2023
The ContextMenu allows a control to display a Menu that is specific to the context of
the control. Typically, the ContextMenu is exposed in the user interface (UI) through the
right mouse button or through the keyboard’s menu button.
The following figure illustrates a ContextMenu in two different states: the default state
and the open state. In the default state, the control is collapsed. When the right mouse
button is pressed over the parent of the menu, the control expands and displays the
menu items.
In This Section
ContextMenu Overview
Reference
ContextMenu
Related Sections
ContextMenu Overview
Article • 02/06/2023
The ContextMenu class represents the element that exposes functionality by using a
context-specific Menu. Typically, a user exposes the ContextMenu in the user interface
(UI) by right-clicking the mouse button. This topic introduces the ContextMenu element
and provides examples of how to use it in Extensible Application Markup Language
(XAML) and code.
ContextMenu Control
A ContextMenu is attached to a specific control. The ContextMenu element enables you
to present users with a list of items that specify commands or options that are
associated with a particular control, for example, a Button. Users right-click the control
to make the menu appear. Typically, clicking a MenuItem opens a submenu or causes an
application to carry out a command.
Creating ContextMenus
The following examples show how to create a ContextMenu with submenus. The
ContextMenu controls are attached to button controls.
XAML
C#
btn = new Button();
btn.Content = "Created with C#";
contextmenu = new ContextMenu();
btn.ContextMenu = contextmenu;
mi = new MenuItem();
mi.Header = "File";
mia = new MenuItem();
mia.Header = "New";
mi.Items.Add(mia);
mib = new MenuItem();
mib.Header = "Open";
mi.Items.Add(mib);
mib1 = new MenuItem();
mib1.Header = "Recently Opened";
mib.Items.Add(mib1);
mib1a = new MenuItem();
mib1a.Header = "Text.xaml";
mib1.Items.Add(mib1a);
contextmenu.Items.Add(mi);
cv2.Children.Add(btn);
The first example defines a style called SimpleSysResources , which shows how to use the
current system settings in your style. The example assigns MenuHighlightBrushKey as
the Background color and MenuTextBrushKey as the Foreground color of the
ContextMenu.
XAML
The following example uses the Trigger element to change the appearance of a Menu in
response to events that are raised on the ContextMenu. When a user moves the mouse
over the menu, the appearance of the ContextMenu items changes.
XAML
See also
ContextMenu
Style
Menu
MenuItem
ContextMenu
ContextMenu Styles and Templates
WPF Controls Gallery Sample
DataGrid
Article • 03/16/2023
The DataGrid control enables you to display and edit data from many different sources,
such as from a SQL database, LINQ query, or any other bindable data source. For more
information, see Binding Sources Overview.
Columns can display text, controls, such as a ComboBox, or any other WPF content, such
as images, buttons, or any content contained in a template. You can use a
DataGridTemplateColumn to display data defined in a template. The following table lists
the column types that are provided by default.
DataGridTextColumn String
DataGridCheckBoxColumn Boolean
DataGridComboBoxColumn Enum
DataGridHyperlinkColumn Uri
DataGrid can be customized in appearance, such as cell font, color, and size. DataGrid
supports all styling and templating functionality of other WPF controls. DataGrid also
includes default and customizable behaviors for editing, sorting, and validation.
The following table lists some of the common tasks for DataGrid and how to accomplish
them. By viewing the related API, you can find more information and sample code.
Scenario Approach
Alternating Set the AlternationCount property to 2 or more, and then assign a Brush to the
background RowBackground and AlternatingRowBackground properties.
colors
Set sizing Set the Height, MaxHeight, MinHeight, Width, MaxWidth, or MinWidth
options properties. For more information, see Sizing Options in the DataGrid Control.
Access Check the SelectedCells property to get the selected cells and the SelectedItems
selected items property to get the selected rows. For more information, see SelectedCells.
Freeze a Set the FrozenColumnCount property to 1 and move the column to the left-
column most position by setting the DisplayIndex property to 0.
Use XML data Bind the ItemsSource on the DataGrid to the XPath query that represents the
as the data collection of items. Create each column in the DataGrid. Bind each column by
source setting the XPath on the binding to the query that gets the property on the item
source. For an example, see DataGridTextColumn.
Related Topics
Title Description
Walkthrough: Display Data from a Describes how to set up a new WPF project, add an Entity
SQL Server Database in a DataGrid Framework Element, set the source, and display the data in
Control a DataGrid.
How to: Add Row Details to a Describes how to create row details for a DataGrid.
DataGrid Control
How to: Implement Validation with Describes how to validate values in DataGrid cells and rows,
the DataGrid Control and display validation feedback.
Default Keyboard and Mouse Describes how to interact with the DataGrid control by
Behavior in the DataGrid Control using the keyboard and mouse.
How to: Group, Sort, and Filter Describes how to view data in a DataGrid in different ways
Data in the DataGrid Control by grouping, sorting, and filtering the data.
Sizing Options in the DataGrid Describes how to control absolute and automatic sizing in
Control the DataGrid.
See also
DataGrid
Styling and Templating
Data Binding Overview
Data Templating Overview
Controls
WPF Content Model
Default Keyboard and Mouse Behavior
in the DataGrid Control
Article • 02/06/2023
This topic describes how users can interact with the DataGrid control by using the
keyboard and mouse.
Typical interactions with the DataGrid include navigation, selection, and editing.
Selection behavior is affected by the SelectionMode and SelectionUnit properties. The
default values that cause the behavior described in this topic are
DataGridSelectionMode.Extended and DataGridSelectionUnit.FullRow. Changing these
values might cause behavior that is different from that described. When a cell is in edit
mode, the editing control might override the standard keyboard behavior of the
DataGrid.
DOWN Moves the focus to the cell directly below the current cell. If the focus is in the
ARROW last row, pressing the DOWN ARROW does nothing.
UP ARROW Moves the focus to the cell directly above the current cell. If the focus is in the
first row, pressing the UP ARROW does nothing.
LEFT ARROW Moves the focus to the previous cell in the row. If the focus is in the first cell in
the row, pressing the LEFT ARROW does nothing.
RIGHT Moves the focus to the next cell in the row. If the focus is in the last cell in the
ARROW row, pressing the RIGHT ARROW does nothing.
HOME Moves the focus to the first cell in the current row.
END Moves the focus to the last cell in the current row.
PAGE DOWN If rows are not grouped, scrolls the control downward by the number of rows that
are fully displayed. Moves the focus to the last fully displayed row without
changing columns.
If rows are grouped, moves the focus to the last row in the DataGrid without
changing columns.
Key or key Description
combination
PAGE UP If rows are not grouped, scrolls the control upward by the number of rows that
are fully displayed. Moves focus to the first displayed row without changing
columns.
If rows are grouped, moves the focus to the first row in the DataGrid without
changing columns.
TAB Moves the focus to the next cell in the current row. If the focus is in the last cell of
the row, moves the focus to the first cell in the next row. If the focus is in the last
cell in the control, moves the focus to the next control in the tab order of the
parent container.
If the current cell is in edit mode and pressing TAB causes focus to move away
from the current row, any changes that were made to the row are committed
before focus is changed.
SHIFT+TAB Moves the focus to the previous cell in the current row. If the focus is already in
the first cell of the row, moves the focus to the last cell in the previous row. If the
focus is in the first cell in the control, moves the focus to the previous control in
the tab order of the parent container.
If the current cell is in edit mode and pressing TAB causes focus to move away
from the current row, any changes that were made to the row are committed
before focus is changed.
CTRL+DOWN Moves the focus to the last cell in the current column.
ARROW
CTRL+UP Moves the focus to the first cell in the current column.
ARROW
CTRL+RIGHT Moves the focus to the last cell in the current row.
ARROW
CTRL+LEFT Moves the focus to the first cell in the current row.
ARROW
ENTER Commits any changes to the current cell and row and moves the focus to the cell
directly below the current cell. If the focus is in the last row, commits any changes
without moving the focus.
ESC If the control is in edit mode, cancels the edit and reverts any changes that were
made in the control. If the underlying data source implements IEditableObject,
pressing ESC a second time cancels edit mode for the entire row.
BACKSPACE Deletes the character before the cursor when editing a cell.
DELETE Deletes the character after the cursor when editing a cell.
CTRL+ENTER Commits any changes to the current cell without moving the focus.
Selection Keys
If the SelectionMode property is set to Extended, the navigation behavior does not
change, but navigating with the keyboard while pressing SHIFT (including CTRL+SHIFT)
will modify a multi-row selection. Before navigation starts, the control marks the current
row as an anchor row. When you navigate while pressing SHIFT, the selection includes
all rows between the anchor row and the current row.
SHIFT+DOWN ARROW
SHIFT+UP ARROW
SHIFT+PAGE DOWN
SHIFT+PAGE UP
CTRL+SHIFT+DOWN ARROW
CTRL+SHIFT+UP ARROW
CTRL+SHIFT+HOME
CTRL+SHIFT+END
Default Mouse Behavior
The following table lists the default mouse behavior for the DataGrid.
Click an unselected Makes the clicked row the current row, and the clicked cell the current
row cell.
Click the current cell Puts the current cell into edit mode.
Clicking the header of a column that is already sorted will reverse the sort
direction of that column.
Pressing the SHIFT key while clicking multiple column headers will sort by
multiple columns in the order clicked.
Click the Select All If SelectionMode is set to Extended, selects all rows in the DataGrid.
button at the top left
corner of the
DataGrid
Mouse Selection
If the SelectionMode property is set to Extended, clicking a row while pressing CTRL or
SHIFT will modify a multi-row selection.
When you click a row while pressing CTRL, the row will change its selection state while
all other rows retain their current selection state. Do this to select non-adjacent rows.
When you click a row while pressing SHIFT, the selection includes all rows between the
current row and an anchor row located at the position of the current row prior to the
click. Subsequent clicks while pressing SHIFT change the current row, but not the anchor
row. Do this to select a range of adjacent rows.
See also
DataGrid
SelectionMode
How to: Add Row Details to a DataGrid
Control
Article • 02/06/2023
When using the DataGrid control, you can customize the data presentation by adding a
row details section. Adding a row details section enables you to group some data in a
template that is optionally visible or collapsed. For example, you can add row details to
a DataGrid that presents only a summary of the data for each row in the DataGrid, but
presents more data fields when the user selects a row. You define the template for the
row details section in the RowDetailsTemplate property. The following illustration shows
an example of a row details section.
You define the row details template as either inline XAML or as a resource. Both
approaches are shown in the following procedures. A data template that is added as a
resource can be used throughout the project without re-creating the template. A data
template that is added as inline XAML is only accessible from the control where it is
defined.
3. Create a DataTemplate that defines the appearance of the row details section.
The following XAML shows the DataGrid and how to define the
RowDetailsTemplate inline. The DataGrid displays three values in each row and
three more values when the row is selected.
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Loaded="Window_Loaded">
<Grid>
<DataGrid Name="dataGrid1" IsReadOnly="True"
AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Company Name" Binding="
{Binding CompanyName}"></DataGridTextColumn>
<DataGridTextColumn Header="Contact First Name"
Binding="{Binding FirstName}"></DataGridTextColumn>
<DataGridTextColumn Header="Contact Last Name"
Binding="{Binding LastName}"></DataGridTextColumn>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border BorderThickness="0"
Background="BlanchedAlmond" Padding="10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Email: "
VerticalAlignment="Center" />
<TextBlock FontSize="16"
Foreground="MidnightBlue" Text="{Binding EmailAddress}"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Phone: "
VerticalAlignment="Center" />
<TextBlock FontSize="16"
Foreground="MidnightBlue" Text="{Binding Phone}"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Sales
Person: " VerticalAlignment="Center" />
<TextBlock FontSize="16"
Foreground="MidnightBlue" Text="{Binding SalesPerson}"
VerticalAlignment="Center" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Window>
The following code shows the query that is used to select the data that is displayed
in the DataGrid. In this example, the query selects data from an entity that contains
customer information.
C#
var query =
from customer in customers
orderby customer.CompanyName
select new
{
customer.LastName,
customer.FirstName,
customer.CompanyName,
customer.Title,
customer.EmailAddress,
customer.Phone,
customer.SalesPerson
};
dataGrid1.ItemsSource = query.ToList();
}
2. Add a Resources element to the root element, such as a Window control or a Page
control, or add a Resources element to the Application class in the App.xaml (or
Application.xaml) file.
XAML
<Application.Resources>
<DataTemplate x:Key="CustomerDetail">
<Border BorderThickness="0" Background="BlanchedAlmond"
Padding="10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Email: "
VerticalAlignment="Center" />
<TextBlock FontSize="16" Foreground="MidnightBlue"
Text="{Binding EmailAddress}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Phone: "
VerticalAlignment="Center" />
<TextBlock FontSize="16" Foreground="MidnightBlue"
Text="{Binding Phone}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Sales Person: "
VerticalAlignment="Center" />
<TextBlock FontSize="16" Foreground="MidnightBlue"
Text="{Binding SalesPerson}" VerticalAlignment="Center" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</Application.Resources>
4. On the DataTemplate, set the x:Key Directive to a value that uniquely identifies the
data template.
The following XAML shows the RowDetailsTemplate property set to the resource
from the previous example.
XAML
By default, the value is set to VisibleWhenSelected. You can set it to Visible to show
the details for all of the rows or Collapsed to hide the details for all rows.
2. If needed, set the AreRowDetailsFrozen property to true to prevent the row details
section from scrolling horizontally.
How to: Group, sort, and filter data in
the DataGrid control
Article • 08/12/2021
It is often useful to view data in a DataGrid in different ways by grouping, sorting, and
filtering the data. To group, sort, and filter the data in a DataGrid, you bind it to a
CollectionView that supports these functions. You can then work with the data in the
CollectionView without affecting the underlying source data. The changes in the
collection view are reflected in the DataGrid user interface (UI).
The CollectionView class provides grouping and sorting functionality for a data source
that implements the IEnumerable interface. The CollectionViewSource class enables you
to set the properties of a CollectionView from XAML.
Using a CollectionViewSource as an
ItemsSource
To group, sort, and filter data in a DataGrid control, you bind the DataGrid to a
CollectionView that supports these functions. In this example, the DataGrid is bound to
a CollectionViewSource that provides these functions for a List<T> of Task objects.
If you use List<T> to create your collection, you should create a new class that
inherits from List<T> instead of instantiating an instance of List<T>. This enables
you to data bind to the collection in XAML.
7 Note
The objects in the collection must implement the INotifyPropertyChanged
changed interface and the IEditableObject interface in order for the DataGrid
to respond correctly to property changes and edits. For more information, see
Implement Property Change Notification.
C#
2. In XAML, create an instance of the collection class and set the x:Key Directive.
XAML
<Window.Resources>
<local:Tasks x:Key="tasks" />
<CollectionViewSource x:Key="cvsTasks" Source="{StaticResource
tasks}"
Filter="CollectionViewSource_Filter">
</CollectionViewSource>
</Window.Resources>
4. Create an instance of the DataGrid class, and set the ItemsSource property to the
CollectionViewSource.
XAML
<DataGrid x:Name="dataGrid1"
ItemsSource="{Binding Source={StaticResource cvsTasks}}"
CanUserAddRows="False">
C#
ICollectionView cvTasks =
CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
Grouping items in a DataGrid
To specify how items are grouped in a DataGrid, you use the PropertyGroupDescription
type to group the items in the source view.
a. In XAML, set the PropertyName to the name of the property to group by.
XAML
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ProjectName"/>
<PropertyGroupDescription PropertyName="Complete"/>
</CollectionViewSource.GroupDescriptions>
C#
ICollectionView cvTasks =
CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
if (cvTasks != null && cvTasks.CanGroup == true)
{
cvTasks.GroupDescriptions.Clear();
cvTasks.GroupDescriptions.Add(new
PropertyGroupDescription("ProjectName"));
cvTasks.GroupDescriptions.Add(new
PropertyGroupDescription("Complete"));
}
5. To remove all groups, call the Clear method of the GroupDescriptions collection.
C#
ICollectionView cvTasks =
CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
if (cvTasks != null)
{
cvTasks.GroupDescriptions.Clear();
}
When items are grouped in the DataGrid, you can define a GroupStyle that specifies the
appearance of each group. You apply the GroupStyle by adding it to the GroupStyle
collection of the DataGrid. If you have multiple levels of grouping, you can apply
different styles to each group level. Styles are applied in the order in which they are
defined. For example, if you define two styles, the first will be applied to top level row
groups. The second style will be applied to all row groups at the second level and lower.
The DataContext of the GroupStyle is the CollectionViewGroup that the group
represents.
XAML
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type
GroupItem}">
<Expander IsExpanded="True"
Background="#FF112255" BorderBrush="#FF002255" Foreground="#FFEEEEEE"
BorderThickness="1,1,1,5">
<Expander.Header>
<DockPanel>
<TextBlock FontWeight="Bold"
Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100"/>
<TextBlock FontWeight="Bold"
Text="{Binding Path=ItemCount}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
<!-- Style for groups under the top level. -->
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<DockPanel Background="LightBlue">
<TextBlock Text="{Binding Path=Name, Converter=
{StaticResource completeConverter}}" Foreground="Blue"
Margin="30,0,0,0" Width="100"/>
<TextBlock Text="{Binding Path=ItemCount}"
Foreground="Blue"/>
</DockPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
a. In XAML, set the PropertyName to the name of the property to sort by.
b. In code, pass the name of the property to sort by and the ListSortDirection to
the constructor.
XAML
<CollectionViewSource.SortDescriptions>
<!-- Requires 'xmlns:scm="clr-
namespace:System.ComponentModel;assembly=WindowsBase"' declaration. -->
<scm:SortDescription PropertyName="ProjectName"/>
<scm:SortDescription PropertyName="Complete" />
<scm:SortDescription PropertyName="DueDate" />
</CollectionViewSource.SortDescriptions>
C#
XAML
C#
Alternatively, you can filter items in a DataGrid by creating a method that provides the
filtering logic and setting the CollectionView.Filter property to apply the filter. To see an
example of this method, see Filter Data in a View.
Example
The following example demonstrates grouping, sorting, and filtering Task data in a
CollectionViewSource and displaying the grouped, sorted, and filtered Task data in a
DataGrid. The CollectionViewSource is used as the ItemsSource for the DataGrid.
Grouping, sorting, and filtering are performed on the CollectionViewSource and are
displayed in the DataGrid UI.
To test this example, you will need to adjust the DGGroupSortFilterExample name to
match your project name. If you are using Visual Basic, you will need to change the class
name for Window to the following.
<Window x:Class="MainWindow"
XAML
<Window x:Class="DGGroupSortFilterExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DGGroupSortFilterExample"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
Title="Group, Sort, and Filter Example" Height="575" Width="525">
<Window.Resources>
<local:CompleteConverter x:Key="completeConverter" />
<local:Tasks x:Key="tasks" />
<CollectionViewSource x:Key="cvsTasks" Source="{StaticResource
tasks}"
Filter="CollectionViewSource_Filter">
<CollectionViewSource.SortDescriptions>
<!-- Requires 'xmlns:scm="clr-
namespace:System.ComponentModel;assembly=WindowsBase"' declaration. -->
<scm:SortDescription PropertyName="ProjectName"/>
<scm:SortDescription PropertyName="Complete" />
<scm:SortDescription PropertyName="DueDate" />
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ProjectName"/>
<PropertyGroupDescription PropertyName="Complete"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<DataGrid x:Name="dataGrid1"
ItemsSource="{Binding Source={StaticResource cvsTasks}}"
CanUserAddRows="False">
<DataGrid.GroupStyle>
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type
GroupItem}">
<Expander IsExpanded="True"
Background="#FF112255" BorderBrush="#FF002255" Foreground="#FFEEEEEE"
BorderThickness="1,1,1,5">
<Expander.Header>
<DockPanel>
<TextBlock
FontWeight="Bold" Text="{Binding Path=Name}" Margin="5,0,0,0" Width="100"/>
<TextBlock
FontWeight="Bold" Text="{Binding Path=ItemCount}"/>
</DockPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
<!-- Style for groups under the top level. -->
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<DockPanel Background="LightBlue">
<TextBlock Text="{Binding Path=Name,
Converter={StaticResource completeConverter}}" Foreground="Blue"
Margin="30,0,0,0" Width="100"/>
<TextBlock Text="{Binding Path=ItemCount}"
Foreground="Blue"/>
</DockPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Background" Value="White" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<TextBlock Text=" Filter completed items "
VerticalAlignment="Center" />
<CheckBox x:Name="cbCompleteFilter" VerticalAlignment="Center"
Checked="CompleteFilter_Changed"
Unchecked="CompleteFilter_Changed" />
<Button Content="Remove Groups" Margin="10,2,2,2"
Click="UngroupButton_Click" />
<Button Content="Group by Project/Status" Margin="2"
Click="GroupButton_Click" />
</StackPanel>
</Grid>
</Window>
C#
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
namespace DGGroupSortFilterExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource).Refresh();
}
// Task Class
// Requires using System.ComponentModel;
public class Task : INotifyPropertyChanged, IEditableObject
{
// The Task class implements INotifyPropertyChanged and
IEditableObject
// so that the datagrid can properly respond to changes to the
// data collection and edits made in the DataGrid.
// Public properties.
public string ProjectName
{
get { return this.m_ProjectName; }
set
{
if (value != this.m_ProjectName)
{
this.m_ProjectName = value;
NotifyPropertyChanged("ProjectName");
}
}
}
See also
Data Binding Overview
Create and Bind to an ObservableCollection
Filter Data in a View
Sort Data in a View
Sort and Group Data Using a View in XAML
How to: Implement Validation with the
DataGrid Control
Article • 02/06/2023
The DataGrid control enables you to perform validation at both the cell and row level.
With cell-level validation, you validate individual properties of a bound data object when
a user updates a value. With row-level validation, you validate entire data objects when
a user commits changes to a row. You can also provide customized visual feedback for
validation errors, or use the default visual feedback that the DataGrid control provides.
The following procedures describe how to apply validation rules to DataGrid bindings
and customize the visual feedback.
The following example shows a DataGrid control with four columns bound to
different properties of a business object. Three of the columns specify the
ExceptionValidationRule by setting the ValidatesOnExceptions property to true .
XAML
<Grid>
<Grid.Resources>
<local:Courses x:Key="courses"/>
</Grid.Resources>
</Grid>
The following example updates the previous example by adding an error style
shared by the three columns with validation rules. When a user enters an invalid
value, the style changes the cell background color and adds a ToolTip. Note the
use of a trigger to determine whether there is a validation error. This is required
because there is currently no dedicated error template for cells.
XAML
<DataGrid.Resources>
<Style x:Key="errorStyle" TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Course Name"
Binding="{Binding Name, TargetNullValue=(enter a course name)}"/>
<DataGridTextColumn Header="Course ID"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding Id, ValidatesOnExceptions=True}"/>
<DataGridTextColumn Header="Start Date"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding StartDate, ValidatesOnExceptions=True,
StringFormat=d}"/>
<DataGridTextColumn Header="End Date"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding EndDate, ValidatesOnExceptions=True,
StringFormat=d}"/>
</DataGrid.Columns>
You can implement more extensive customization by replacing the CellStyle used
by the column.
value.
C#
<DataGrid.RowValidationRules>
<local:CourseValidationRule ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
When a user specifies an end date that is earlier than the start date, a red
exclamation mark (!) appears in the row header. You can change this default
validation feedback as described in the following procedure.
The following example replaces the default row validation feedback with a more
visible indicator. When a user enters an invalid value, a red circle with a white
exclamation mark appears in the row header. This occurs for both row and cell
validation errors. The associated error message is displayed in a ToolTip.
XAML
<DataGrid.RowValidationErrorTemplate>
<ControlTemplate>
<Grid Margin="0,-2,0,-2"
ToolTip="{Binding RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type DataGridRow}},
Path=(Validation.Errors)[0].ErrorContent}">
<Ellipse StrokeThickness="0" Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock Text="!" FontSize="{TemplateBinding FontSize}"
FontWeight="Bold" Foreground="White"
HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</DataGrid.RowValidationErrorTemplate>
Example
The following example provides a complete demonstration for cell and row validation.
The Course class provides a sample data object that implements IEditableObject to
support transactions. The DataGrid control interacts with IEditableObject to enable users
to revert changes by pressing ESC.
7 Note
If you are using Visual Basic, in the first line of MainWindow.xaml, replace
x:Class="DataGridValidation.MainWindow" with x:Class="MainWindow" .
In the End Date column, enter a date that is earlier than the Start Date.
To undo an invalid cell value, put the cursor back in the cell and press the ESC key.
To undo changes for an entire row when the current cell is in edit mode, press the
ESC key twice.
When a validation error occurs, move your mouse pointer over the indicator in the
row header to see the associated error message.
C#
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace DataGridValidation
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
dataGrid1.InitializingNewItem += (sender, e) =>
{
Course newCourse = e.NewItem as Course;
newCourse.StartDate = newCourse.EndDate = DateTime.Today;
};
}
}
#region IEditableObject
#endregion
#region INotifyPropertyChanged
#endregion
<Window x:Class="DataGridValidation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataGridValidation"
Title="DataGrid Validation Example" Height="240" Width="600">
<Grid>
<Grid.Resources>
<local:Courses x:Key="courses"/>
</Grid.Resources>
<DataGrid.Resources>
<Style x:Key="errorStyle" TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Course Name"
Binding="{Binding Name, TargetNullValue=(enter a course name)}"/>
<DataGridTextColumn Header="Course ID"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding Id, ValidatesOnExceptions=True}"/>
<DataGridTextColumn Header="Start Date"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding StartDate, ValidatesOnExceptions=True,
StringFormat=d}"/>
<DataGridTextColumn Header="End Date"
EditingElementStyle="{StaticResource errorStyle}"
Binding="{Binding EndDate, ValidatesOnExceptions=True,
StringFormat=d}"/>
</DataGrid.Columns>
<DataGrid.RowValidationRules>
<local:CourseValidationRule ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
<DataGrid.RowValidationErrorTemplate>
<ControlTemplate>
<Grid Margin="0,-2,0,-2"
ToolTip="{Binding RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type DataGridRow}},
Path=(Validation.Errors)[0].ErrorContent}">
<Ellipse StrokeThickness="0" Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock Text="!" FontSize="{TemplateBinding FontSize}"
FontWeight="Bold" Foreground="White"
HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</DataGrid.RowValidationErrorTemplate>
</DataGrid>
</Grid>
</Window>
See also
DataGrid
DataGrid
Data Binding
Implement Binding Validation
Implement Validation Logic on Custom Objects
Walkthrough: Display data from a SQL
Server database in a DataGrid control
Article • 11/06/2020
In this walkthrough, you retrieve data from a SQL Server database and display that data
in a DataGrid control. You use the ADO.NET Entity Framework to create the entity classes
that represent the data, and use LINQ to write a query that retrieves the specified data
from an entity class.
Prerequisites
You need the following components to complete this walkthrough:
Visual Studio.
Access to a running instance of SQL Server or SQL Server Express that has the
AdventureWorks sample database attached to it. You can download the
AdventureWorks database from the GitHub .
2. In Solution Explorer, right-click your project, point to Add, and then select New
Item.
3. In the Installed Templates pane, select Data and in the list of templates, select
ADO.NET Entity Data Model.
4. Name the file AdventureWorksModel.edmx and then click Add.
5. In the Choose Model Contents screen, select EF Designer from database and then
click Next.
6. In the Choose Your Data Connection screen, provide the connection to your
AdventureWorksLT2008 database. For more information, see Choose Your Data
Connection Dialog Box.
Make sure that the name is AdventureWorksLT2008Entities and that the Save entity
connection settings in App.Config as check box is selected, and then click Next.
7. In the Choose Your Database Objects screen, expand the Tables node, and select
the Product and ProductCategory tables.
You can generate entity classes for all of the tables; however, in this example you
only retrieve data from those two tables.
8. Click Finish.
The Product and ProductCategory entities are displayed in the Entity Designer.
Retrieve and present the data
1. Open the MainWindow.xaml file.
3. In the XAML editor, add the following DataGrid tag between the <Grid> and
</Grid> tags to add a DataGrid named dataGrid1 .
XAML
5. Using the Properties window or XAML editor, create an event handler for the
Window named Window_Loaded for the Loaded event. For more information, see
How to: Create a Simple Event Handler.
7 Note
If you are using Visual Basic, in the first line of MainWindow.xaml, replace
x:Class="DataGridSQLExample.MainWindow" with x:Class="MainWindow" .
XAML
<Window x:Class="DataGridSQLExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="450"
Loaded="Window_Loaded">
<Grid>
<DataGrid Name="dataGrid1" />
</Grid>
</Window>
7. Add the following code to retrieve only specific values from the joined tables and
set the ItemsSource property of the DataGrid to the results of the query.
C#
using System.Data.Entity.Core.Objects;
using System.Linq;
using System.Windows;
namespace DataGridSQLExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
AdventureWorksLT2008Entities dataEntities = new
AdventureWorksLT2008Entities();
public MainWindow()
{
InitializeComponent();
}
dataGrid1.ItemsSource = query.ToList();
}
}
}
8. Run the example.
See also
DataGrid
Sizing Options in the DataGrid Control
Article • 02/06/2023
Various options are available to control how the DataGrid sizes itself. The DataGrid, and
individual rows and columns in the DataGrid, can be set to size automatically to their
contents or can be set to specific values. By default, the DataGrid will grow and shrink to
fit the size of its contents.
When placed inside a container that does not restrict the size of its children, such as a
Canvas or StackPanel, the DataGrid will stretch beyond the visible bounds of the
container and scrollbars will not be shown. This condition has both usability and
performance implications.
When bound to a data set, if the Height of the DataGrid is not restricted, it will continue
to add a row for each data item in the bound data set. This can cause the DataGrid to
grow outside the visible bounds of your application as rows are added. The DataGrid will
not show scrollbars in this case because its Height will continue to grow to
accommodate the new rows.
An object is created for each row in the DataGrid. If you are working with a large data
set and you allow the DataGrid to automatically size itself, the creation of a large
number of objects may affect the performance of your application.
To avoid these issues when you work with large data sets, it is recommended that you
specifically set the Height of the DataGrid or place it in a container that will restrict its
Height, such as a Grid. When the Height is restricted, the DataGrid will only create the
rows that will fit within its specified Height, and will recycle those rows as needed to
display new data.
Property Description
MaxHeight Sets the upper bound for the height of the DataGrid. The DataGrid will grow
vertically until it reaches this height.
MinHeight Sets the lower bound for the height of the DataGrid. The DataGrid will shrink
vertically until it reaches this height.
MaxWidth Sets the upper bound for the width of the DataGrid. The DataGrid will grow
horizontally until it reaches this width.
MinWidth Sets the lower bound for the width of the DataGrid. The DataGrid will shrink
horizontally until it reaches this width.
DataGrid Rows
By default, a DataGrid row's Height property is set to Double.NaN (" Auto " in XAML), and
the row height will expand to the size of its contents. The height of all rows in the
DataGrid can be specified by setting the DataGrid.RowHeight property. Users can
change the row height by dragging the row header dividers.
DataGrid Columns
The DataGrid uses values of the DataGridLength and the DataGridLengthUnitType
structure to specify absolute or automatic sizing modes.
The following table shows the values provided by the DataGridLengthUnitType structure.
Name Description
Auto The default automatic sizing mode sizes DataGrid columns based on the contents
of both cells and column headers.
SizeToCells The cell-based automatic sizing mode sizes DataGrid columns based on the
contents of cells in the column, not including column headers.
SizeToHeader The header-based automatic sizing mode sizes DataGrid columns based on the
contents of column headers only.
Pixel The pixel-based sizing mode sizes DataGrid columns based on the numeric value
provided.
Star The star sizing mode is used to distribute available space by weighted
proportions.
Columns in the DataGrid can also be set to automatically size only within specified
boundaries, or columns can be set to a specific size. The following table shows the
properties that can be set to control column sizes.
Property Description
DataGrid.MaxColumnWidth Sets the upper bound for all columns in the DataGrid.
DataGrid.MinColumnWidth Sets the lower bound for all columns in the DataGrid.
Property Description
See also
DataGrid
DataGridColumn
DataGridLength
DataGridLengthConverter
DatePicker
Article • 02/06/2023
The DatePicker control allows the user to select a date by either typing it into a text field
or by using a drop-down Calendar control.
DatePicker Control
Many of a DatePicker control's properties are for managing its built-in Calendar, and
function identically to the equivalent property in Calendar. In particular, the
DatePicker.IsTodayHighlighted, DatePicker.FirstDayOfWeek, DatePicker.BlackoutDates,
DatePicker.DisplayDateStart, DatePicker.DisplayDateEnd, DatePicker.DisplayDate, and
DatePicker.SelectedDate properties function identically to their Calendar counterparts.
For more information, see Calendar.
Users can type a date directly into a text field, which sets the Text property. If the
DatePicker cannot convert the entered string to a valid date, the DateValidationError
event will be raised. By default, this causes an exception, but an event handler for
DateValidationError can set the ThrowException property to false and prevent an
exception from being raised.
See also
Controls
Styling and Templating
DockPanel
Article • 02/06/2023
The DockPanel element is used to position child content along the edge of a layout
container.
In This Section
How-to Topics
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
DockPanel How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the DockPanel element to position child
elements along the edge of a layout container.
In This Section
Get or Set a Dock Value
Create a DockPanel
Partition Space by Using the DockPanel Element
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
How to: Get or Set a Dock Value
Article • 02/06/2023
The following example shows how to assign a Dock value for an object. The example
uses the GetDock and SetDock methods of DockPanel.
Example
The example creates an instance of the TextBlock element, txt1 , and assigns a Dock
value of Top by using the SetDock method of DockPanel. It then appends the value of
the Dock property to the Text of the TextBlock element by using the GetDock method.
Finally, the example adds the TextBlock element to the parent DockPanel, dp1 .
C#
See also
DockPanel
GetDock
SetDock
Panels Overview
How to: Create a DockPanel
Article • 02/06/2023
Example
The following example creates and uses an instance of DockPanel by using code. The
example shows you how to partition space by creating five Rectangle elements and
positioning (docking) them inside a parent DockPanel. If you retain the default setting,
the final rectangle fills all the remaining unallocated space.
C#
// Create a DockPanel
DockPanel myDockPanel = new DockPanel();
// Add the DockPanel to the Window as Content and show the Window
mainWindow.Content = myDockPanel;
mainWindow.Title = "DockPanel Sample";
mainWindow.Show();
}
}
See also
DockPanel
Dock
Panels Overview
How to: Partition Space by Using the
DockPanel Element
Article • 02/06/2023
The following example creates a simple user interface (UI) framework using a DockPanel
element. The DockPanel partitions available space to its child elements.
Example
This example uses the Dock property, which is an attached property, to dock two
identical Border elements at the Top of the partitioned space. A third Border element is
docked to the Left, with its width set to 200 pixels. A fourth Border is docked to the
Bottom of the screen. The last Border element automatically fills the remaining space.
C#
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="DockPanel Sample">
<DockPanel LastChildFill="True">
<Border Height="25" Background="SkyBlue" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="SkyBlue" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="LemonChiffon" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Bottom">
<TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
</Border>
<Border Width="200" Background="PaleGreen" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Left">
<TextBlock Foreground="Black">Dock = "Left"</TextBlock>
</Border>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Black">This content will "Fill" the remaining
space</TextBlock>
</Border>
</DockPanel>
</Page>
7 Note
By default, the last child of a DockPanel element fills the remaining unallocated
space. If you do not want this behavior, set LastChildFill="False" .
See also
DockPanel
Panels Overview
DocumentViewer
Article • 02/06/2023
Reference
DocumentViewer
FixedDocument
See also
Documents
Document Serialization and Storage
Printing Overview
Expander
Article • 02/06/2023
An Expander allows a user to view a header and expand that header to see further
details, or to collapse a section up to a header.
The following illustration provides an example of this control in its expanded position.
In This Section
Expander Overview
How-to Topics
Reference
Expander
Related Sections
Expander Overview
Article • 02/06/2023
XAML
The Content and Header of an Expander can also contain complex content, such as
RadioButton and Image objects.
When you set a size dimension on an Expander control in the direction that the
expanded content is displayed, the Expander takes control of the area that is used by
the content and displays a border around it. The border shows even when the content is
collapsed. To set the size of the expanded content area, set size dimensions on the
content of the Expander, or if you want scrolling capability, on the ScrollViewer that
encloses the content.
Expander in a ScrollViewer
When you place an Expander control in a ScrollViewer, set the ScrollViewer dimension
property that corresponds to the direction in which the Expander content opens to the
size of the Expander content area. For example, if you set the ExpandDirection property
on the Expander to Down (the content area opens down), set the Height property on
the ScrollViewer control to the required height for the content area. If you instead set
the height dimension on the content itself, ScrollViewer does not recognize this setting
and therefore, does not provide scrollable content.
The following example shows how to create an Expander control that has complex
content and that contains a ScrollViewer control. This example creates an Expander that
is like the illustration at the beginning of this section.
C#
void MakeExpander()
{
//Create containing stack panel and assign to Grid row/col
StackPanel sp = new StackPanel();
Grid.SetRow(sp, 0);
Grid.SetColumn(sp, 1);
sp.Background = Brushes.LightSalmon;
spScroll.Children.Add(tbc);
ScrollViewer scr = new ScrollViewer();
scr.Content = spScroll;
scr.Height = 50;
exp.Content = scr;
exp.Width=200;
exp.HorizontalContentAlignment= HorizontalAlignment.Stretch;
//Insert Expander into the StackPanel and add it to the
//Grid
sp.Children.Add(exp);
myGrid.Children.Add(sp);
}
XAML
See also
Expander
ExpandDirection
How-to Topics
Expander How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the Expander control.
In This Section
Create an Expander with a ScrollViewer
Reference
Expander
Related Sections
Expander Overview
How to: Create an Expander with a
ScrollViewer
Article • 02/06/2023
This example shows how to create an Expander control that contains complex content,
such as an image and text. The example also encloses the content of the Expander in a
ScrollViewer control.
Example
The following example shows how to create an Expander. The example uses a
BulletDecorator control, which contains an image and text, in order to define the
Header. A ScrollViewer control provides a method for scrolling the expanded content.
Note that the example sets the Height property on the ScrollViewer instead of on the
content. If the Height is set on the content, the ScrollViewer does not allow the user to
scroll the content. The Width property is set on the Expander control and this setting
applies to the Header and the expanded content.
XAML
spScroll.Children.Add(tbc);
ScrollViewer scr = new ScrollViewer();
scr.Content = spScroll;
scr.Height = 50;
exp.Content = scr;
exp.Width=200;
exp.HorizontalContentAlignment= HorizontalAlignment.Stretch;
See also
Expander
Expander Overview
How-to Topics
FlowDocumentPageViewer
Article • 02/06/2023
See also
FlowDocument
Flow Document Overview
How-to Topics
Documents in WPF
FlowDocumentReader
Article • 02/06/2023
See also
FlowDocumentReader
FlowDocumentPageViewer
FlowDocumentScrollViewer
Documents in WPF
Flow Document Overview
FlowDocumentScrollViewer
Article • 02/06/2023
See also
FlowDocumentReader
FlowDocumentPageViewer
FlowDocumentScrollViewer
FlowDocument
Documents in WPF
Flow Document Overview
Frame
Article • 02/06/2023
The Frame control supports content navigation within content. Frame can be hosted by
a root element like Window, NavigationWindow, Page, UserControl, FlowDocument, or
as an island within a content tree that belongs to a root element.
Reference
Frame
Related Sections
Navigation Overview
Grid
Article • 02/06/2023
The Grid element is used to precisely position content in rows and columns.
In This Section
How-to Topics
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
Grid How-to Topics
Article • 02/06/2023
The topics in this section describe how to position elements using the Grid element.
In This Section
Build a Standard UI Dialog Box by Using Grid
Create a Complex Grid
Create a Grid Element
Create and Use a GridLengthConverter Object
Manipulate Columns and Rows by Using ColumnDefinitionsCollections and
RowDefinitionsCollections
Position the Child Elements of a Grid
Share Sizing Properties Between Grids
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
How to: Build a Standard UI Dialog Box
by Using Grid
Article • 02/06/2023
This example shows how to create a standard user interface (UI) dialog box by using the
Grid element.
Example
The following example creates a dialog box like the Run dialog box in the Windows
operating system.
The example creates a Grid and uses the ColumnDefinition and RowDefinition classes to
define five columns and four rows.
The example then adds and positions an Image, RunIcon.png , to represent the image
that is found in the dialog box. The image is placed in the first column and row of the
Grid (the upper-left corner).
Next, the example adds a TextBlock element to the first column, which spans the
remaining columns of the first row. It adds another TextBlock element to the second row
in the first column, to represent the Open text box. A TextBlock follows, which
represents the data entry area.
Finally, the example adds three Button elements to the final row, which represent the
OK, Cancel, and Browse events.
C#
grid1.Children.Add(img1);
grid1.Children.Add(txt1);
grid1.Children.Add(txt2);
grid1.Children.Add(tb1);
grid1.Children.Add(button1);
grid1.Children.Add(button2);
grid1.Children.Add(button3);
mainWindow.Content = grid1;
See also
Grid
GridUnitType
Panels Overview
How-to Topics
How to create a complex Grid
Article • 09/04/2020
This example shows how to use a Grid control to create a layout that looks like a
monthly calendar.
Example
The following example defines eight rows and eight columns by using the RowDefinition
and ColumnDefinition classes. It uses the Grid.ColumnSpan and Grid.RowSpan attached
properties, together with Rectangle elements, which fill the backgrounds of various
columns and rows. This design is possible because more than one element can exist in
each cell in a Grid, a principle difference between Grid and Table.
The example uses vertical gradients to Fill the columns and rows to improve the visual
presentation and readability of the calendar. Styled TextBlock elements represent the
dates and days of the week. TextBlock elements are absolutely positioned within their
cells by using the Margin property and alignment properties that are defined within the
style for the application.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Complex Grid Example">
<Border BorderBrush="Black">
See also
System.Windows.Controls.Grid
System.Windows.Documents.TableCell
Painting with Solid Colors and Gradients Overview
Panels Overview
Table Overview
How to: Create a Grid Element
Article • 02/06/2023
Example
The following example shows how to create and use an instance of Grid by using either
Extensible Application Markup Language (XAML) or code. This example uses three
ColumnDefinition objects and three RowDefinition objects to create a grid that has nine
cells, such as in a worksheet. Each cell contains a TextBlock element that represents data,
and the top row contains a TextBlock with the ColumnSpan property applied. To show
the boundaries of each cell, the ShowGridLines property is enabled.
C#
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Grid Sample">
<Grid VerticalAlignment="Top" HorizontalAlignment="Left"
ShowGridLines="True" Width="250" Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
Either approach will generate a user interface that looks much the same, like the one
below.
See also
Grid
Panels Overview
How to: Create and Use a
GridLengthConverter Object
Article • 02/06/2023
Example
The following example shows how to create and use an instance of
GridLengthConverter. The example defines a custom method called changeCol , which
passes the ListBoxItem to a GridLengthConverter that converts the Content of a
ListBoxItem to an instance of GridLength. The converted value is then passed back as
the value of the Width property of the ColumnDefinition element.
The example also defines a second custom method, called changeColVal . This custom
method converts the Value of a Slider to a String and then passes that value back to the
ColumnDefinition as the Width of the element.
Note that a separate Extensible Application Markup Language (XAML) file defines the
contents of a ListBoxItem.
C#
See also
GridLengthConverter
GridLength
How to: Manipulate Columns and Rows
by Using ColumnDefinitionsCollections
and RowDefinitionsCollections
Article • 02/06/2023
This example shows how to use the methods in the ColumnDefinitionCollection and
RowDefinitionCollection classes to perform actions like adding, clearing, or counting the
contents of rows or columns. For example, you can Add, Clear, or Count the items that
are included in a ColumnDefinition or RowDefinition.
Example
The following example creates a Grid element with a Name of grid1 . The Grid contains
a StackPanel that holds Button elements, each controlled by a different collection
method. When you click a Button, it activates a method call in the code-behind file.
XAML
<DockPanel Margin="10,0,0,0">
This example defines a series of custom methods, each corresponding to a Click event in
the Extensible Application Markup Language (XAML) file. You can change the number of
columns and rows in the Grid in several ways, which includes adding or removing rows
and columns; and counting the total number of rows and columns. To prevent
ArgumentOutOfRangeException and ArgumentException exceptions, you can use the
error-checking functionality that the RemoveRange method provides.
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace columndefinitions_grid
{
public partial class Window1 : Window
{
RowDefinition rowDef1;
ColumnDefinition colDef1;
See also
Grid
ColumnDefinitionCollection
RowDefinitionCollection
How to: Position the Child Elements of a
Grid
Article • 02/06/2023
This example shows how to use the get and set methods that are defined on Grid to
position child elements.
Example
The following example defines a parent Grid element ( grid1 ) that has three columns
and three rows. A child Rectangle element ( rect1 ) is added to the Grid in column
position zero, row position zero. Button elements represent methods that can be called
to reposition the Rectangle element within the Grid. When a user clicks a button, the
related method is activated.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="grid_getset_methods.Window1"
Title="Grid Methods Sample">
<Border BorderBrush="Black" Background="White" BorderThickness="2">
<DockPanel VerticalAlignment="Top" HorizontalAlignment="Left"
Margin="10">
<TextBlock FontSize="20" FontWeight="Bold" DockPanel.Dock="Top">Grid
Methods Sample</TextBlock>
<TextBlock DockPanel.Dock="Top">Click the buttons on the left to
reposition the Rectangle below using methods defined on Grid.</TextBlock>
<Grid Margin="0,10,15,0" DockPanel.Dock="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- <Snippet1> -->
<StackPanel Grid.Column="0" Grid.Row="0"
HorizontalAlignment="Left" Orientation="Vertical">
<Button Click="setCol0">Move Rectangle to Column 0</Button>
<Button Click="setCol1">Move Rectangle to Column 1</Button>
<Button Click="setCol2" Margin="0,0,0,10">Move Rectangle to
Column 2</Button>
<Button Click="setRow0">Move Rectangle to Row 0</Button>
<Button Click="setRow1">Move Rectangle to Row 1</Button>
<Button Click="setRow2" Margin="0,0,0,10">Move Rectangle to Row
2</Button>
<Button Click="setColspan">Span All Columns</Button>
<Button Click="setRowspan">Span All Rows</Button>
<Button Click="clearAll">Clear All</Button>
</StackPanel>
</Grid>
<Grid DockPanel.Dock="Top" Margin="0,10,15,0"
HorizontalAlignment="Left" Name="grid1" ShowGridLines="True" Width="400"
Height="400" Background="LightSteelBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
The following code-behind example handles the methods that the button Click events
raise. The example writes these method calls to TextBlock elements that use related get
methods to output the new property values as strings.
C#
See also
Grid
Panels Overview
How to: Share Sizing Properties
Between Grids
Article • 02/06/2023
This example shows how to share the sizing data of columns and rows between Grid
elements in order to keep sizing consistent.
Example
The following example introduces two Grid elements as child elements of a parent
DockPanel. The IsSharedSizeScope attached property of Grid is defined on the parent
DockPanel.
The example manipulates the property value by using two Button elements; each
element represents one of the Boolean property values. When the IsSharedSizeScope
property value is set to true , each column or row member of a SharedSizeGroup shares
sizing information, regardless of the content of a row or column.
XAML
...
XAML
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="FirstColumn"/>
<ColumnDefinition SharedSizeGroup="SecondColumn"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" SharedSizeGroup="FirstRow"/>
</Grid.RowDefinitions>
</StackPanel>
The following code-behind example handles the methods that the button Click event
raises. The example writes the results of these method calls to TextBlock elements that
use related get methods to output the new property values as strings.
C#
In This Section
How-to Topics
Reference
GridSplitter
Related Sections
GridSplitter How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the GridSplitter control.
In This Section
Resize Rows with a GridSplitter
Resize Columns with a GridSplitter
Make Sure That a GridSplitter Is Visible
Reference
GridSplitter
Grid
Related Sections
How to: Resize Rows with a GridSplitter
Article • 02/06/2023
This example shows how to use a horizontal GridSplitter to redistribute the space
between two rows in a Grid without changing the dimensions of the Grid.
Example
How to create a GridSplitter that overlays the edge of a row
To specify a GridSplitter that resizes adjacent rows in a Grid, set the Row attached
property to one of the rows that you want to resize. If your Grid has more than one
column, set the ColumnSpan attached property to specify the number of columns. Then
set the VerticalAlignment to Top or Bottom (which alignment you set depends on which
two rows you want to resize). Finally, set the HorizontalAlignment property to Stretch.
The following example shows how to define a horizontal GridSplitter that resizes
adjacent rows.
XAML
<GridSplitter Grid.Row="1"
Grid.ColumnSpan="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Background="Black"
ShowsPreview="true"
ResizeDirection="Rows"
Height="5"/>
A GridSplitter that does not occupy its own row may be obscured by other controls in
the Grid. For more information about how to prevent this issue, see Make Sure That a
GridSplitter Is Visible.
To specify a GridSplitter that occupies a row in a Grid, set the Row attached property to
one of the rows that you want to resize. If your Grid has more than one column, set the
ColumnSpan attached property to the number of columns. Then set the
VerticalAlignment to Center, set the HorizontalAlignment property to Stretch, and set
the Height of the row that contains the GridSplitter to Auto.
The following example shows how to define a horizontal GridSplitter that occupies a row
and resizes the rows on either side of it.
XAML
<Grid.RowDefinitions>
<RowDefinition Height="50*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="50*" />
</Grid.RowDefinitions>
XAML
See also
GridSplitter
How-to Topics
How to: Resize Columns with a
GridSplitter
Article • 02/06/2023
This example shows how to create a vertical GridSplitter in order to redistribute the
space between two columns in a Grid without changing the dimensions of the Grid.
Example
How to create a GridSplitter that overlays the edge of a column
To specify a GridSplitter that resizes adjacent columns in a Grid, set the Column attached
property to one of the columns that you want to resize. If your Grid has more than one
row, set the RowSpan attached property to the number of rows. Then set the
HorizontalAlignment property to Left or Right (which alignment you set depends on
which two columns you want to resize). Finally, set the VerticalAlignment property to
Stretch.
XAML
<GridSplitter Grid.Column="1"
Grid.RowSpan="3"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Background="Black"
ShowsPreview="true"
Width="5"/>
A GridSplitter that does not have its own column may be obscured by other controls in
the Grid. For more information about how to prevent this issue, see Make Sure That a
GridSplitter Is Visible.
To specify a GridSplitter that occupies a column in a Grid, set the Column attached
property to one of the columns that you want to resize. If your Grid has more than one
row, set the RowSpan attached property to the number of rows. Then set the
HorizontalAlignment to Center, set the VerticalAlignment property to Stretch, and set
the Width of the column that contains the GridSplitter to Auto.
The following example shows how to define a vertical GridSplitter that occupies a
column and resizes the columns on either side of it.
XAML
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
XAML
<GridSplitter Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
Background="Black"
ShowsPreview="True"
Width="5"
/>
See also
GridSplitter
How-to Topics
How to: Make Sure That a GridSplitter Is
Visible
Article • 02/06/2023
This example shows how to make sure a GridSplitter control is not hidden by the other
controls in a Grid.
Example
The Children of a Grid control are rendered in the order that they are defined in markup
or code. GridSplitter controls can be hidden by other controls if you do not define them
as the last elements in the Children collection or if you give other controls a higher
ZIndexProperty.
Make sure that GridSplitter controls are the last Children added to the Grid. The
following example shows the GridSplitter as the last element in the Children
collection of the Grid.
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0"/>
<GridSplitter Grid.Column ="0" Background="Blue"/>
</Grid>
Set the ZIndexProperty on the GridSplitter to be higher than a control that would
otherwise hide it. The following example gives the GridSplitter control a higher
ZIndexProperty than the Button control.
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="0" Background="Blue"
Panel.ZIndex="1"/>
<Button Grid.Column="0"/>
</Grid>
Set margins on the control that would otherwise hide the GridSplitter so that the
GridSplitter is exposed. The following example sets margins on a control that
would otherwise overlay and hide the GridSplitter.
XAML
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column ="0" Background="Blue"/>
<Button Grid.Column="0" Margin="0,0,5,0"/>
</Grid>
See also
GridSplitter
How-to Topics
GroupBox
Article • 02/06/2023
The following illustration shows a GroupBox that contains a TabControl and a Button
that are enclosed in a StackPanel.
In This Section
Define a GroupBox Template
Reference
GroupBox
Related Sections
How to: Define a GroupBox Template
Article • 08/18/2022
Example
The following example defines a GroupBox control template by using a Grid control for
layout. The template uses a BorderGapMaskConverter to define the border of the
GroupBox so that the border does not obscure the Header content.
XAML
<!--=================================================================
GroupBox Template Example
==================================================================-->
<BorderGapMaskConverter x:Key="BorderGapMaskConverter"/>
<Style x:Key="{x:Type GroupBox}"
TargetType="{x:Type GroupBox}">
<Setter Property="BorderBrush"
Value="Gray"/>
<Setter Property="Foreground"
Value="White"/>
<Setter Property="BorderThickness"
Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="4"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="4"/>
</Grid.RowDefinitions>
<Border CornerRadius="4"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="0"
Grid.ColumnSpan="4"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="Transparent"
Background="{TemplateBinding Background}"/>
<!-- ContentPresenter for the header -->
<Border x:Name="Header"
Padding="6,0,6,0"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1">
<ContentPresenter ContentSource="Header"
RecognizesAccessKey="True" />
</Border>
<!-- Primary content for GroupBox -->
<ContentPresenter Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="{TemplateBinding Padding}"/>
<Border CornerRadius="0"
Grid.Row="1"
Grid.RowSpan="3"
Grid.ColumnSpan="4"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Border.OpacityMask>
<MultiBinding Converter=
"{StaticResource BorderGapMaskConverter}"
ConverterParameter="6">
<Binding ElementName="Header"
Path="ActualWidth"/>
<Binding RelativeSource="{RelativeSource Self}"
Path="ActualWidth"/>
<Binding RelativeSource="{RelativeSource Self}"
Path="ActualHeight"/>
</MultiBinding>
</Border.OpacityMask>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
See also
GroupBox
How to: Create a GroupBox
Image
Article • 02/06/2023
In This Section
How-to Topics
Reference
Image
BitmapImage
BitmapSource
See also
Imaging Overview
How-to Topics
Image How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the Image element.
In This Section
Use the Image Element
Convert an Image to Greyscale
Crop an Image
Rotate an Image
Reference
Image
BitmapImage
BitmapSource
See also
Imaging Overview
How-to Topics
How to: Use the Image Element
Article • 02/06/2023
This example shows how to include images in an application by using the Image
element.
Define an image
The following example shows how to render an image 200 pixels wide. In this Extensible
Application Markup Language (XAML) example, both attribute syntax and property tag
syntax are used to define the image. For more information on attribute syntax and
property syntax, see Dependency Properties Overview. A BitmapImage is used to define
the image's source data and is explicitly defined for the property tag syntax example. In
addition, the DecodePixelWidth of the BitmapImage is set to the same width as the
Width of the Image. This is done to ensure that the minimum amount of memory is
used rendering the image.
7 Note
In general, if you want to specify the size of a rendered image, specify only the
Width or the Height but not both. If you only specify one, the image's aspect ratio
is preserved. Otherwise, the image may unexpectedly appear stretched or warped.
To control the image's stretching behavior, use the Stretch and StretchDirection
properties.
7 Note
When you specify the size of an image with either Width or Height, you should
also set either DecodePixelWidth or DecodePixelHeight to the same respective
size.
The Stretch property determines how the image source is stretched to fill the image
element. For more information, see the Stretch enumeration.
XAML
<!-- Simple image rendering. However, rendering an image this way may not
result in the best use of application memory. See markup below which
creates the same end result but using less memory. -->
<Image Width="200"
Source="C:\Documents and Settings\All Users\Documents\My Pictures\Sample
Pictures\Water Lilies.jpg"/>
<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the
desired
height and width of the rendered image. If you don't do this, the
application will
cache the image as though it were rendered as its normal size rather
than just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either
DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My
Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>
Render an image
The following example shows how to render an image 200 pixels wide using code.
7 Note
C#
// Create source
BitmapImage myBitmapImage = new BitmapImage();
See also
Imaging Overview
How to: Convert an Image to Greyscale
Article • 02/06/2023
Example
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
</Page.Resources>
<StackPanel>
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace SDKSample
{
public partial class FormatConvertedBitmapExample : Page
{
public FormatConvertedBitmapExample()
{
See also
Use the Image Element
Crop an Image
Rotate an Image
How to: Crop an Image
Article • 08/18/2022
Example
The following Extensible Application Markup Language (XAML) defines resources used
within the samples below.
XAML
<Page.Resources>
<!-- Define some image resources, for use as the image element source. --
>
<BitmapImage x:Key="masterImage" UriSource="/sampleImages/gecko.jpg" />
<CroppedBitmap x:Key="croppedImage"
Source="{StaticResource masterImage}" SourceRect="30 20 105 50"/>
</Page.Resources>
XAML
<!-- Use the cropped image resource as the images source -->
<Image Width="200" Source="{StaticResource croppedImage}"
Margin="5" Grid.Column="0" Grid.Row="1" />
C#
XAML
<!-- Chain a cropped bitmap off a previosly defined cropped image -->
<Image Width="200" Grid.Column="0" Grid.Row="3" Margin="5">
<Image.Source>
<CroppedBitmap Source="{StaticResource croppedImage}"
SourceRect="30 0 75 50"/>
</Image.Source>
</Image>
C#
See also
How to: Create a Clip Region
How to: Rotate an Image
Article • 02/06/2023
This example shows how to rotate an image 90 degrees by using a Rotation property of
a BitmapImage.
Example
XAML
C#
//Create source
BitmapImage bi = new BitmapImage();
//BitmapImage properties must be in a BeginInit/EndInit block
bi.BeginInit();
bi.UriSource = new
Uri(@"pack://application:,,/sampleImages/watermelon.jpg");
//Set image rotation
bi.Rotation = Rotation.Rotate270;
bi.EndInit();
//set image source
rotated270.Source = bi;
Label
Article • 08/04/2022
Label controls usually provide information in the user interface (UI). Historically, a Label
has contained only text, but because the Label that ships with Windows Presentation
Foundation (WPF) is a ContentControl, it can contain either text or a UIElement.
A Label provides both functional and visual support for access keys. It is frequently used
to enable quick keyboard access to controls such as a TextBox. To assign a Label to a
Control, set the Label.Target property to the control that should get focus when the user
presses the access key.
The following image shows a Label "Theme" that targets a ComboBox. When the user
presses T , the ComboBox receives focus. For more information, see How to: Set the
Target Property of a Label.
In This Section
How to: Create a Control That Has an Access Key and Text Wrapping
Reference
Label
How to: Create a Control That Has an
Access Key and Text Wrapping
Article • 08/18/2022
This example shows how to create a control that has an access key and supports text
wrapping. The example uses a Label control to illustrate these concepts.
Example
Add Text Wrapping to Your Label
The Label control does not support text wrapping. If you need a label that wraps across
multiple lines, you can nest another element that does support text wrapping and put
the element inside the label. The following example shows how to use a TextBlock to
make a label that wraps several lines of text.
XAML
If you need a Label that has an access key (mnemonic), use the AccessText element that
is inside the Label.
The following example shows how to create a Label that has an access key and supports
text wrapping. To enable text wrapping, the example sets the TextWrapping property
and uses an underline character to specify the access key. (The character that
immediately follows the underline character is the access key.)
XAML
<TextBox Name="textBox1" Width="50" Height="20"/>
<Label Width="200" HorizontalAlignment="Left"
Target="{Binding ElementName=textBox1}">
<AccessText TextWrapping="WrapWithOverflow">
_Another long piece of text that requires text wrapping
goes here.
</AccessText>
</Label>
See also
How to: Set the Target Property of a Label
ListBox
Article • 02/06/2023
Typical ListBox
In This Section
How-to Topics
Reference
ListBox
ListBoxItem
Related Sections
ListBox How-to Topics
Article • 08/04/2022
The topics in this section describe how to use the ListBox control to display selectable
lists of items.
In This Section
Bind a ListBox to Data
Get a ListBoxItem
How to: Add Data to an ItemsControl
Improve the Scrolling Performance of a ListBox
Reference
ListBox
ListBoxItem
Related Sections
How to: Bind a ListBox to Data
Article • 02/06/2023
An application developer can create ListBox controls without specifying the contents of
each ListBoxItem separately. You can use data binding to bind data to the individual
items.
The following example shows how to create a ListBox that populates the ListBoxItem
elements by data binding to a data source called Colors. In this case it is not necessary
to use ListBoxItem tags to specify the content of each item.
Example
XAML
<Canvas.Resources>
<src:myColors x:Key="Colors"/>
</Canvas.Resources>
XAML
See also
ListBox
ListBoxItem
Controls
How to: Get a ListBoxItem
Article • 02/06/2023
If you need to get a specific ListBoxItem at a particular index in a ListBox, you can use an
ItemContainerGenerator.
Example
The following example shows a ListBox and its items.
XAML
The following example shows how to retrieve the item by specifying the index of the
item in the ContainerFromIndex property of the ItemContainerGenerator.
C#
After you have retrieved the list box item, you can display the contents of the item, as
shown in the following example.
C#
If a ListBox contains many items, the user interface response can be slow when a user
scrolls the ListBox by using the mouse wheel or dragging the thumb of a scrollbar. You
can improve the performance of the ListBox when the user scrolls by setting the
VirtualizingStackPanel.VirtualizationMode attached property to
VirtualizationMode.Recycling.
Example
Description
The following example creates a ListBox and sets the
VirtualizingStackPanel.VirtualizationMode attached property to
Code
XAML
<StackPanel>
<StackPanel.Resources>
<src:LotsOfItems x:Key="data"/>
</StackPanel.Resources>
</StackPanel>
The following example shows the data that the previous example uses.
C#
The ListView control provides the infrastructure to display a set of data items in different
layouts or views.
In This Section
Overviews
How-to Topics
Reference
ListView
ListViewItem
GridView
Related Sections
Data Binding Overview
Data Templating Overview
ListView Overviews
Article • 02/06/2023
The topics in this section show you how to use a ListView control.
In This Section
ListView Overview
GridView Overview
GridView Column Header Styles and Templates Overview
Reference
ListView
GridView
Related Sections
How-to Topics
ListView Overview
Article • 02/06/2023
The ListView control provides the infrastructure to display a set of data items in different
layouts or views. For example, a user may want to display data items in a table and also
to sort its columns.
7 Note
The types referenced in this article are available in the Code reference section.
What Is a ListView?
The ListView control is an ItemsControl that is derived from ListBox. Typically, its items
are members of a data collection and are represented as ListViewItem objects. A
ListViewItem is a ContentControl and can contain only a single child element. However,
that child element can be any visual element.
The following example shows how to define a GridView for a ListView control that
displays employee information.
XAML
<ListView.View>
<GridViewColumn DisplayMemberBinding="{Binding
Path=EmployeeNumber}" Header="Employee No." Width="100"/>
</GridView>
</ListView.View>
</ListView>
The following illustration shows how the data appears for the previous example.
You can create a custom view mode by defining a class that inherits from the ViewBase
class. The ViewBase class provides the infrastructure that you need to create a custom
view. For more information about how to create a custom view, see Create a Custom
View Mode for a ListView.
XAML
C#
GridViewColumn gvc1 = new GridViewColumn();
gvc1.DisplayMemberBinding = new Binding("FirstName");
gvc1.Header = "FirstName";
gvc1.Width = 100;
XAML
You can also specify a Binding as part of a DataTemplate definition that you use to style
the cells in a column. In the following example, the DataTemplate that is identified with a
ResourceKey sets the Binding for a GridViewColumn. Note that this example does not
define the DisplayMemberBinding because doing so overrides the binding that is
specified by DataTemplate.
XAML
<DataTemplate x:Key="myCellTemplateMonth">
<DockPanel>
<TextBlock Foreground="DarkBlue" HorizontalAlignment="Center">
<TextBlock.Text>
<Binding Path="Month"/>
</TextBlock.Text>
</TextBlock>
</DockPanel>
</DataTemplate>
XAML
For more information about how to use GridView and its supporting classes, see
GridView Overview.
To specify a view mode that can be simultaneously used by more than one ListView, use
templates or styles.
Code reference
The following objects are referenced in this article:
Window element is declared slightly different from what you see in the example
code:
XAML
<Window x:Class="SDKSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="OnLoad"
xmlns:ds="clr-namespace:SDKSample">
<Window.Resources>
<ObjectDataProvider x:Key="EmployeeInfoDataSource" ObjectType="
{x:Type ds:myEmployees}" />
</Window.Resources>
EmployeeInfo class, which is used as the type for the EmployeeInfoDataSource data
collection.
C#
GridView view mode is one of the view modes for a ListView control. The GridView class
and its supporting classes enable you and your users to view item collections in a table
that typically uses buttons as interactive column headers. This topic introduces the
GridView class and outlines its use.
7 Note
The button controls that GridView uses for column headers are derived from
ButtonBase.
The following example shows how to define a GridView that displays employee data. In
this example, ListView defines the EmployeeInfoDataSource as the ItemsSource. The
property definitions of DisplayMemberBinding bind GridViewColumn content to
EmployeeInfoDataSource data categories.
XAML
<ListView.View>
<GridViewColumn DisplayMemberBinding="{Binding
Path=EmployeeNumber}" Header="Employee No." Width="100"/>
</GridView>
</ListView.View>
</ListView>
The following illustration shows the table that the previous example creates. The
GridView control displays data from an ItemsSource object:
Related data content displays in horizontal rows. For example, in the previous
illustration, each employee's last name, first name, and ID number are displayed as a set
because they appear in a horizontal row.
To specify template and style properties for column headers, use the GridView,
GridViewColumn, and GridViewColumnHeader classes. For more information, see
GridView Column Header Styles and Templates Overview.
If you explicitly define a visual element as a data item, it can appear only one time in a
GridView. This limitation exists because an element can have only one parent and
therefore, can appear only one time in the visual tree.
For example, to add a CheckBox to the rows in GridView view mode, add the CheckBox
to a DataTemplate, and then set the CellTemplate property to that DataTemplate.
The following list discusses in more detail the capabilities of using GridView for user
interaction:
Users can reorder columns in a GridView by pressing the left mouse button while it
is over a column header and then dragging that column to a new position. While
the user drags the column header, a floating version of the header is displayed as
well as a solid black line that shows where to insert the column.
If you want to modify the default style for the floating version of a header, specify
a ControlTemplate for a GridViewColumnHeader type that is triggered when the
Role property is set to Floating. For more information, see Create a Style for a
Dragged GridView Column Header.
Users can double-click the gripper to the right of a column header in order to
resize a column to fit its content.
7 Note
You can set the Width property to Double.NaN to produce the same effect.
If the size of the GridView is not large enough to display all the items, users can
scroll horizontally or vertically by using scrollbars, which are provided by a
ScrollViewer control. A ScrollBar is hidden if all the content is visible in a specific
direction. Column headers do not scroll with a vertical scroll bar, but do scroll
horizontally.
When users click a column header button, they can sort the data that is displayed
in the column if you have provided a sorting algorithm.
You can handle the Click event for column header buttons in order to provide
functionality like a sorting algorithm. To handle the Click event for a single column
header, set an event handler on the GridViewColumnHeader. To set an event
handler that handles the Click event for all column headers, set the handler on the
ListView control.
GridViewColumn
GridViewColumnHeader
GridViewRowPresenter
GridViewHeaderRowPresenter
GridViewColumnCollection
GridViewColumnHeaderRole
See also
ListView
ListViewItem
GridViewColumn
GridViewColumnHeader
GridViewRowPresenter
GridViewHeaderRowPresenter
ViewBase
ListView Overview
Sort a GridView Column When a Header Is Clicked
How-to Topics
GridView Column Header Styles and
Templates Overview
Article • 02/06/2023
This overview discusses the order of precedence for properties that you use to
customize a column header in the GridView view mode of a ListView control.
The rows in the following table show groups of properties that perform the same
function. You can use these properties to customize the column headers in a GridView.
The order of precedence for related properties is from right to left where the property in
the farthest right column has the highest precedence. For example, if a ContentTemplate
is set on the GridViewColumnHeader object and the HeaderTemplateSelector is set on
the associated GridViewColumn, the ContentTemplate takes precedence. In this
scenario, the HeaderTemplateSelector has no effect.
Properties
1For Header Template Properties, if you set both the template and template selector
properties, the template property takes precedence. For example, if you set both the
ContentTemplate and ContentTemplateSelector properties, the ContentTemplate
property takes precedence.
See also
How-to Topics
ListView Overview
GridView Overview
ListView How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the ListView control to display a set of
data items.
In This Section
Sort a GridView Column When a Header Is Clicked
Create a Custom View Mode for a ListView
Use Templates to Style a ListView That Uses GridView
Create a Style for a Dragged GridView Column Header
Display ListView Contents by Using a GridView
Use Triggers to Style Selected Items in a ListView
Create ListViewItems with a CheckBox
Display Data by Using GridViewRowPresenter
Group Items in a ListView That Implements a GridView
Style a Row in a ListView That Implements a GridView
Change the Horizontal Alignment of a Column in a ListView
Handle the MouseDoubleClick Event for Each Item in a ListView
Reference
ListView
ListViewItem
GridView
Related Sections
ListView Overview
How to: Sort a GridView Column When
a Header Is Clicked
Article • 08/18/2022
This example shows how to create a ListView control that implements a GridView view
mode and sorts the data content when a user clicks a column header.
Example
The following example defines a GridView with three columns that bind to the Year,
Month, and Day, properties of the DateTime structure.
XAML
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=Year}"
Header="Year"
Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Month}"
Header="Month"
Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Day}"
Header="Day"
Width="100"/>
</GridView>
The following example shows the data items that are defined as an ArrayList of
DateTime objects. The ArrayList is defined as the ItemsSource for the ListView control.
XAML
<ListView.ItemsSource>
<s:ArrayList>
<p:DateTime>1993/1/1 12:22:02</p:DateTime>
<p:DateTime>1993/1/2 13:2:01</p:DateTime>
<p:DateTime>1997/1/3 2:1:6</p:DateTime>
<p:DateTime>1997/1/4 13:6:55</p:DateTime>
<p:DateTime>1999/2/1 12:22:02</p:DateTime>
<p:DateTime>1998/2/2 13:2:01</p:DateTime>
<p:DateTime>2000/2/3 2:1:6</p:DateTime>
<p:DateTime>2002/2/4 13:6:55</p:DateTime>
<p:DateTime>2001/3/1 12:22:02</p:DateTime>
<p:DateTime>2006/3/2 13:2:01</p:DateTime>
<p:DateTime>2004/3/3 2:1:6</p:DateTime>
<p:DateTime>2004/3/4 13:6:55</p:DateTime>
</s:ArrayList>
</ListView.ItemsSource>
The s and p identifiers in the XAML tags refer to namespace mappings that are defined
in the metadata of the XAML page. The following example shows the metadata
definition.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ListViewSort.Window1"
xmlns:s="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:p="clr-namespace:System;assembly=mscorlib">
To sort the data according to the contents of a column, the example defines an event
handler to handle the Click event that occurs when you press the column header button.
The following example shows how to specify an event handler for the
GridViewColumnHeader control.
XAML
The example defines the event handler so that the sort direction changes between
ascending order and descending order each time you press the column header button.
The following example shows the event handler.
C#
if (headerClicked != null)
{
if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
{
if (headerClicked != _lastHeaderClicked)
{
direction = ListSortDirection.Ascending;
}
else
{
if (_lastDirection == ListSortDirection.Ascending)
{
direction = ListSortDirection.Descending;
}
else
{
direction = ListSortDirection.Ascending;
}
}
var columnBinding =
headerClicked.Column.DisplayMemberBinding as Binding;
var sortBy = columnBinding?.Path.Path ??
headerClicked.Column.Header as string;
Sort(sortBy, direction);
if (direction == ListSortDirection.Ascending)
{
headerClicked.Column.HeaderTemplate =
Resources["HeaderTemplateArrowUp"] as DataTemplate;
}
else
{
headerClicked.Column.HeaderTemplate =
Resources["HeaderTemplateArrowDown"] as DataTemplate;
}
_lastHeaderClicked = headerClicked;
_lastDirection = direction;
}
}
}
}
The following example shows the sorting algorithm that is called by the event handler to
sort the data. The sort is performed by creating a new SortDescription structure.
C#
dataView.SortDescriptions.Clear();
SortDescription sd = new SortDescription(sortBy, direction);
dataView.SortDescriptions.Add(sd);
dataView.Refresh();
}
See also
ListView
GridView
ListView Overview
GridView Overview
How-to Topics
How to: Create a custom view mode for
a ListView
Article • 02/06/2023
This example shows how to create a custom View mode for a ListView control.
Example
You must use the ViewBase class when you create a custom view for the ListView
control. The following example shows a view mode called PlainView that's derived from
the ViewBase class.
C#
To apply a style to the custom view, use the Style class. The following example defines a
Style for the PlainView view mode. In the previous example, this style is set as the value
of the DefaultStyleKey property that's defined for PlainView .
XAML
<Style x:Key="{ComponentResourceKey
TypeInTargetAssembly={x:Type l:PlainView},
ResourceId=myPlainViewDSK}"
TargetType="{x:Type ListView}"
BasedOn="{StaticResource {x:Type ListBox}}"
>
<Setter Property="HorizontalContentAlignment"
Value="Center"/>
<Setter Property="ItemContainerStyle"
Value="{Binding (ListView.View).ItemContainerStyle,
RelativeSource={RelativeSource Self}}"/>
<Setter Property="ItemTemplate"
Value="{Binding (ListView.View).ItemTemplate,
RelativeSource={RelativeSource Self}}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource
AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
To define the layout of data in a custom view mode, define a DataTemplate object. The
following example defines a DataTemplate that can be used to display data in the
PlainView view mode.
XAML
<DataTemplate x:Key="centralTile">
<StackPanel Height="100" Width="90">
<Grid Width="70" Height="70" HorizontalAlignment="Center">
<Image Source="{Binding XPath=@Image}" Margin="6,6,6,9"/>
</Grid>
<TextBlock Text="{Binding XPath=@Name}" FontSize="13"
HorizontalAlignment="Center" Margin="0,0,0,1" />
<TextBlock Text="{Binding XPath=@Type}" FontSize="9"
HorizontalAlignment="Center" Margin="0,0,0,1" />
</StackPanel>
</DataTemplate>
The following example shows how to define a ResourceKey for the PlainView view
mode that uses the DataTemplate that is defined in the previous example.
XAML
<l:PlainView x:Key="tileView"
ItemTemplate="{StaticResource centralTile}"
ItemWidth="100"/>
A ListView control can use a custom view if you set the View property to the resource
key. The following example shows how to specify PlainView as the view mode for a
ListView.
C#
For the complete sample, see ListView with Multiple Views (C#) or ListView with
Multiple Views (Visual Basic) .
See also
ListView
GridView
How-to Topics
ListView Overview
GridView Overview
How to: Use Templates to Style a
ListView That Uses GridView
Article • 02/06/2023
This example shows how to use the DataTemplate and Style objects to specify the
appearance of a ListView control that uses a GridView view mode.
Example
The following examples show Style and DataTemplate objects that customize the
appearance of a column header for a GridViewColumn.
XAML
XAML
<DataTemplate x:Key="myHeaderTemplate">
<DockPanel>
<CheckBox/>
<TextBlock FontSize="16" Foreground="DarkBlue">
<TextBlock.Text>
<Binding/>
</TextBlock.Text>
</TextBlock>
</DockPanel>
</DataTemplate>
The following example shows how to use these Style and DataTemplate objects to set
the HeaderContainerStyle and HeaderTemplate properties of a GridViewColumn. The
DisplayMemberBinding property defines the content of the column cells.
XAML
The following example shows how to define a DataTemplate that customizes the
appearance of the cells in a GridViewColumn.
XAML
<DataTemplate x:Key="myCellTemplateMonth">
<DockPanel>
<TextBlock Foreground="DarkBlue" HorizontalAlignment="Center">
<TextBlock.Text>
<Binding Path="Month"/>
</TextBlock.Text>
</TextBlock>
</DockPanel>
</DataTemplate>
The following example shows how to use this DataTemplate to define the content of a
GridViewColumn cell. This template is used instead of the DisplayMemberBinding
property that is shown in the previous GridViewColumn example.
XAML
See also
ListView
GridView
GridView Overview
How-to Topics
ListView Overview
How to: Create a Style for a Dragged
GridView Column Header
Article • 02/06/2023
Example
When you drag a column header to another location in a ListView that uses GridView for
its view mode, the column moves to the new position. While you are dragging the
column header, a floating copy of the header appears in addition to the original header.
A column header in a GridView is represented by a GridViewColumnHeader object.
To customize the appearance of both the floating and original headers, you can set
Triggers to modify the GridViewColumnHeader Style. These Triggers are applied when
the IsPressed property value is true and the Role property value is Floating.
When the user presses the mouse button and holds it down while the mouse pauses on
the GridViewColumnHeader, the IsPressed property value changes to true . Likewise,
when the user begins the drag operation, the Role property changes to Floating.
The following example shows how to set Triggers to change the Foreground and
Background colors of the original and floating headers when the user drags a column to
a new position.
XAML
XAML
<ControlTemplate.Triggers>
XAML
<Trigger Property="IsPressed"
Value="true">
<Setter TargetName="HighlightBorder"
Property="Visibility"
Value="Hidden"/>
<Setter TargetName="PART_HeaderGripper"
Property="Visibility"
Value="Hidden"/>
<Setter Property="Background"
Value="SkyBlue"/>
<Setter Property="Foreground"
Value="Yellow"/>
</Trigger>
XAML
<Trigger Property="Role"
Value="Floating">
<Setter TargetName="PART_HeaderGripper"
Property="Visibility"
Value="Collapsed"/>
<Setter Property="Background"
Value="Yellow"/>
<Setter Property="Foreground"
Value="SkyBlue"/>
</Trigger>
XAML
</ControlTemplate.Triggers>
XAML
</ControlTemplate>
See also
GridViewColumnHeader
GridViewColumnHeaderRole
ListView
GridView
How-to Topics
ListView Overview
GridView Overview
How to: Display ListView Contents by
Using a GridView
Article • 02/06/2023
This example shows how to define a GridView view mode for a ListView control.
Example
You can define the view mode of a GridView by specifying GridViewColumn objects. The
following example shows how to define GridViewColumn objects that bind to the data
content that is specified for the ListView control. This GridView example specifies three
GridViewColumn objects that map to the FirstName , LastName , and EmployeeNumber
fields of the EmployeeInfoDataSource that is set as the ItemsSource of the ListView
control.
XAML
<ListView.View>
<GridViewColumn DisplayMemberBinding="{Binding
Path=EmployeeNumber}" Header="Employee No." Width="100"/>
</GridView>
</ListView.View>
</ListView>
See also
ListView
GridView
ListView Overview
GridView Overview
How-to Topics
How to: Use Triggers to Style Selected
Items in a ListView
Article • 02/06/2023
This example shows how to define Triggers for a ListViewItem control so that when a
property value of a ListViewItem changes, the Style of the ListViewItem changes in
response.
Example
If you want the Style of a ListViewItem to change in response to property changes,
define Triggers for the Style change.
The following example defines a Trigger that sets the Foreground property to Blue and
changes the Cursor to display a Hand when the IsMouseOver property changes to true .
XAML
<Style.Triggers>
XAML
XAML
</Style.Triggers>
</Style>
The following example defines a MultiTrigger that sets the Foreground property of a
ListViewItem to Yellow when the ListViewItem is the selected item and has keyboard
focus.
XAML
<Style x:Key="MyContainer" TargetType="{x:Type ListViewItem}">
<Style.Triggers>
XAML
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true" />
<Condition Property="Selector.IsSelectionActive" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="Foreground" Value="Yellow" />
</MultiTrigger>
XAML
</Style.Triggers>
</Style>
See also
Control
ListView
GridView
How-to Topics
ListView Overview
GridView Overview
How to: Create ListViewItems with a
CheckBox
Article • 02/06/2023
This example shows how to display a column of CheckBox controls in a ListView control
that uses a GridView.
Example
To create a column that contains CheckBox controls in a ListView, create a DataTemplate
that contains a CheckBox. Then set the CellTemplate of a GridViewColumn to the
DataTemplate.
The following example shows a DataTemplate that contains a CheckBox. The example
binds the IsChecked property of the CheckBox to the IsSelected property value of the
ListViewItem that contains it. Therefore, when the ListViewItem that contains the
CheckBox is selected, the CheckBox is checked.
XAML
<DataTemplate x:Key="FirstCell">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=IsSelected,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type
ListViewItem}}}"/>
</StackPanel>
</DataTemplate>
The following example shows how to create a column of CheckBox controls. To make
the column, the example sets the CellTemplate property of the GridViewColumn to the
DataTemplate.
XAML
See also
Control
ListView
GridView
ListView Overview
How-to Topics
GridView Overview
How to: Display Data by Using
GridViewRowPresenter
Article • 02/06/2023
Example
The following example shows how to specify a GridViewColumnCollection that displays
the DayOfWeek and Year of a DateTime object by using GridViewRowPresenter and
GridViewHeaderRowPresenter objects. The example also defines a Style for the Header
of a GridViewColumn.
XAML
<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">
<Window.Resources>
<GridViewColumnCollection x:Key="gvcc">
<GridViewColumn Header="Year"
DisplayMemberBinding="{Binding Year}"
Width="80"/>
<GridViewColumn Header="Day"
DisplayMemberBinding="{Binding DayOfWeek}"
Width="80" />
</GridViewColumnCollection>
</Window.Resources>
<StackPanel>
<GridViewHeaderRowPresenter Name="hrp" Columns="{StaticResource gvcc}"
ColumnHeaderContainerStyle=
"{StaticResource MyHeaderStyle}" />
</Window>
See also
GridViewHeaderRowPresenter
GridViewRowPresenter
GridViewColumnCollection
GridView Overview
How to: Group Items in a ListView That
Implements a GridView
Article • 02/06/2023
This example shows how to display groups of items in the GridView view mode of a
ListView control.
Example
To display groups of items in a ListView, define a CollectionViewSource. The following
example shows a CollectionViewSource that groups data items according to the value of
the Catalog data field.
XAML
<CollectionViewSource x:Key='src'
Source="{Binding Source={StaticResource MyData},
XPath=Item}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="@Catalog" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
The following example sets the ItemsSource for the ListView to the
CollectionViewSource that the previous example defines. The example also defines a
GroupStyle that implements an Expander control.
XAML
XAML
</ListView>
See also
ListView
GridView
How-to Topics
ListView Overview
GridView Overview
How to: Style a Row in a ListView That
Implements a GridView
Article • 02/06/2023
This example shows how to style a row in a ListView control that uses a GridView View
mode.
Example
You can style a row in a ListView control by setting an ItemContainerStyle on the
ListView control. Set the style for its items that are represented as ListViewItem objects.
The ItemContainerStyle references the ControlTemplate objects that are used to display
the row content.
The complete sample, which the following examples are extracted from, displays a
collection of song information that is stored in an XML database. Each song in the
database has a rating field and the value of this field specifies how to display a row of
song information.
The following example shows how to define ItemContainerStyle for the ListViewItem
objects that represent the songs in the song collection. The ItemContainerStyle
references ControlTemplate objects that specify how to display a row of song
information.
XAML
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="Template"
Value="{StaticResource Default}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding XPath=@Rating}" Value="5">
<Setter Property="Template"
Value="{StaticResource StronglyRecommended}"/>
</DataTrigger>
<DataTrigger Binding="{Binding XPath=@Rating}" Value="4">
<Setter Property="Template"
Value="{StaticResource Recommended}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
The following example shows a ControlTemplate that adds the text string "Strongly
Recommended" to the row. This template is referenced in the ItemContainerStyle and
displays when the song's rating has a value of 5 (five). The ControlTemplate includes a
GridViewRowPresenter object that lays out the contents of the row in columns as
defined by the GridView view mode.
XAML
<ControlTemplate x:Key="StronglyRecommended"
TargetType='{x:Type ListViewItem}'>
<StackPanel Background="Beige">
<GridViewRowPresenter Content="{TemplateBinding Content}"
Columns="{TemplateBinding GridView.ColumnCollection}"/>
<TextBlock Background="LightBlue" Text="Strongly Recommended" />
</StackPanel>
</ControlTemplate>
XAML
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource MyHeaderStyle}">
<GridViewColumn Header="Name"
DisplayMemberBinding="{Binding XPath=@Name}"
Width="100"/>
<GridViewColumn Header="Time"
DisplayMemberBinding="{Binding XPath=@Time}"
Width="80"/>
<GridViewColumn Header="Artist"
DisplayMemberBinding="{Binding XPath=@Artist}"
Width="80" />
<GridViewColumn Header="Disk"
DisplayMemberBinding="{Binding XPath=@Disk}"
Width="100"/>
</GridView>
</ListView.View>
See also
ListView
GridView
How-to Topics
ListView Overview
Styling and Templating
How to: Change the Horizontal
Alignment of a Column in a ListView
Article • 02/06/2023
By default, the content of each column in a ListViewItem is left-aligned. You can change
the alignment of each column by providing a DataTemplate and setting the
HorizontalAlignment property on the element within the DataTemplate. This topic shows
how a ListView aligns its content by default and how to change the alignment of one
column in a ListView.
Example
In the following example, the data in the Title and ISBN columns is left-aligned.
XAML
XAML
<ListView ItemsSource="{Binding Source={StaticResource InventoryData},
XPath=Book}">
<ListView.View>
<GridView>
<GridViewColumn Width="300" Header="Title"
DisplayMemberBinding="{Binding XPath=Title}"/>
<GridViewColumn Width="150" Header="ISBN"
DisplayMemberBinding="{Binding XPath=@ISBN}"/>
</GridView>
</ListView.View>
</ListView>
To change the alignment of the ISBN column, you need to specify that the
HorizontalContentAlignment property of each ListViewItem is Stretch, so that the
elements in each ListViewItem can span or be positioned along the entire width of each
column. Because the ListView is bound to a data source, you need to create a style that
sets the HorizontalContentAlignment. Next, you need to use a DataTemplate to display
the content instead of using the DisplayMemberBinding property. To display the ISBN of
each template, the DataTemplate can just contain a TextBlock that has its
HorizontalAlignment property set to Right.
The following example defines the style and DataTemplate necessary to make the ISBN
column right-aligned, and changes the GridViewColumn to reference the DataTemplate.
XAML
<DataTemplate x:Key="ISBNTemplate">
<TextBlock HorizontalAlignment="Right"
Text="{Binding XPath=@ISBN}"/>
</DataTemplate>
XAML
See also
Data Binding Overview
Data Templating Overview
Bind to XML Data Using an XMLDataProvider and XPath Queries
ListView Overview
How to: Handle the MouseDoubleClick
Event for Each Item in a ListView
Article • 02/06/2023
To handle an event for an item in a ListView, you need to add an event handler to each
ListViewItem. When a ListView is bound to a data source, you don't explicitly create a
ListViewItem, but you can handle the event for each item by adding an EventSetter to a
style of a ListViewItem.
Example
The following example creates a data-bound ListView and creates a Style to add an
event handler to each ListViewItem.
XAML
XAML
<!--The Style is defined in a ResourceDictionary,
such as Window.Resources-->
<Style TargetType="ListViewItem">
<EventSetter Event="MouseDoubleClick"
Handler="ListViewItem_MouseDoubleClick"/>
</Style>
XAML
C#
if (book == null)
{
return;
}
if (book.GetAttribute("Stock") == "out")
{
MessageBox.Show("Time to order more copies of " +
book["Title"].InnerText);
}
else
{
MessageBox.Show(book["Title"].InnerText + " is available.");
}
}
7 Note
Although it is most common to bind a ListView to a data source, you can use a
style to add an event handler to each ListViewItem in a non-data-bound ListView
regardless of whether you explicitly create a ListViewItem. For more information
about explicitly and implicitly created ListViewItem controls, see ItemsControl.
See also
XmlElement
Data Binding Overview
Styling and Templating
Bind to XML Data Using an XMLDataProvider and XPath Queries
ListView Overview
Menu
Article • 02/06/2023
The following illustration shows the three different states of a menu control. The default
state is when no device such as a mouse pointer is resting on the Menu. The focus state
occurs when the mouse pointer is hovering over the Menu and pressed state occurs
when a mouse button is clicked over the Menu.
In This Section
Menu Overview
Reference
Menu
MenuItem
MenuBase
ContextMenu
Related Sections
Menu Overview
Article • 02/06/2023
The Menu class enables you to organize elements associated with commands and event
handlers in a hierarchical order. Each Menu element contains a collection of MenuItem
elements.
Menu Control
The Menu control presents a list of items that specify commands or options for an
application. Typically, clicking a MenuItem opens a submenu or causes an application to
carry out a command.
Creating Menus
The following example creates a Menu to manipulate text in a TextBox. The Menu
contains MenuItem objects that use the Command, IsCheckable, and Header properties
and the Checked, Unchecked, and Click events.
XAML
<Menu>
<MenuItem Header="_Edit">
<MenuItem Command="ApplicationCommands.Copy"/>
<MenuItem Command="ApplicationCommands.Cut"/>
<MenuItem Command="ApplicationCommands.Paste"/>
</MenuItem>
<MenuItem Header="_Font">
<MenuItem Header="_Bold" IsCheckable="True"
Checked="Bold_Checked"
Unchecked="Bold_Unchecked"/>
<MenuItem Header="_Italic" IsCheckable="True"
Checked="Italic_Checked"
Unchecked="Italic_Unchecked"/>
<Separator/>
<MenuItem Header="I_ncrease Font Size"
Click="IncreaseFont_Click"/>
<MenuItem Header="_Decrease Font Size"
Click="DecreaseFont_Click"/>
</MenuItem>
</Menu>
<TextBox Name="textBox1" TextWrapping="Wrap"
Margin="2">
The quick brown fox jumps over the lazy dog.
</TextBox>
C#
VB
InputGestureText
The following example shows how to use the InputGestureText property to assign
keyboard shortcut text to MenuItem controls. This only places the keyboard shortcut in
the menu item. It does not associate the command with the MenuItem. The application
must handle the user's input to carry out the action.
XAML
Command
The following example shows how to use the Command property to associate the Open
and Save commands with MenuItem controls. Not only does the command property
associate a command with a MenuItem, but it also supplies the input gesture text to use
as a shortcut.
XAML
The MenuItem class also has a CommandTarget property, which specifies the element
where the command occurs. If CommandTarget is not set, the element that has
keyboard focus receives the command. For more information about commands, see
Commanding Overview.
Menu Styling
With control styling, you can dramatically change the appearance and behavior of Menu
controls without having to write a custom control. In addition to setting visual
properties, you can also apply a Style to individual parts of a control, change the
behavior of parts of the control through properties, or add additional parts or change
the layout of a control. The following examples demonstrate several ways to add a Style
to a Menu control.
The first code example defines a Style called Simple that shows how to use the current
system settings in your style. The code assigns the color of the MenuHighlightBrush as
the menu's background color and the MenuTextBrush as the menu's foreground color.
Notice that you use resource keys to assign the brushes.
XAML
The following sample uses Trigger elements that enable you to change the appearance
of a MenuItem in response to events that occur on the Menu. When you move the
mouse over the Menu, the foreground color and the font characteristics of the menu
items change.
XAML
See also
WPF Controls Gallery Sample
Panel
Article • 02/06/2023
Panel is the base class for all elements that support application layout in Windows
Presentation Foundation (WPF).
In This Section
Panels Overview
How-to Topics
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
Panels Overview
Article • 03/17/2022
Panel elements are components that control the rendering of elements—their size and
dimensions, their position, and the arrangement of their child content. The Windows
Presentation Foundation (WPF) provides a number of predefined Panel elements as well
as the ability to construct custom Panel elements.
Localization/Globalization Support
The WPF includes a comprehensive suite of derived panel implementations that enable
many complex layouts. These derived classes expose properties and methods that
enable most standard user interface (UI) scenarios. Developers who are unable to find a
child arrangement behavior that meets their needs can create new layouts by overriding
the ArrangeOverride and MeasureOverride methods. For more information on custom
layout behaviors, see Custom Panel Elements.
Panel exposes additional properties that are of critical importance in understanding and
using layout. The Background property is used to fill the area between the boundaries of
a derived panel element with a Brush. Children represents the child collection of
elements that the Panel is comprised of. InternalChildren represents the content of the
Children collection plus those members generated by data binding. Both consist of a
UIElementCollection of child elements hosted within the parent Panel.
Panel also exposes a Panel.ZIndex attached property that can be used to achieve layered
order in a derived Panel. Members of a panel's Children collection with a higher
Panel.ZIndex value appear in front of those with a lower Panel.ZIndex value. This is
particularly useful for panels such as Canvas and Grid which allow children to share the
same coordinate space.
Panel also defines the OnRender method, which can be used to override the default
presentation behavior of a Panel.
Attached Properties
Derived panel elements make extensive use of attached properties. An attached
property is a specialized form of dependency property that does not have the
conventional common language runtime (CLR) property "wrapper". Attached properties
have a specialized syntax in Extensible Application Markup Language (XAML), which can
be seen in several of the examples that follow.
One purpose of an attached property is to allow child elements to store unique values
of a property that is actually defined by a parent element. An application of this
functionality is having child elements inform the parent how they wish to be presented
in the user interface (UI), which is extremely useful for application layout. For more
information, see Attached Properties Overview.
Each panel element encapsulates its own special functionality, as seen in the following
table.
Element Name UI Description
Panel?
Canvas Yes Defines an area within which you can explicitly position child
elements by coordinates relative to the Canvas area.
DockPanel Yes Defines an area within which you can arrange child elements
either horizontally or vertically, relative to each other.
Grid Yes Defines a flexible grid area consisting of columns and rows.
Child elements of a Grid can be positioned precisely using the
Margin property.
StackPanel Yes Arranges child elements into a single line that can be oriented
horizontally or vertically.
VirtualizingPanel No Provides a base class for panels that can "virtualize" their
children collection.
Each derived Panel element treats sizing constraints differently. Understanding how a
Panel handles constraints in either the horizontal or vertical direction can make layout
more predictable.
More detailed descriptions and usage examples of each of these elements can be found
below.
Canvas
The Canvas element enables positioning of content according to absolute x- and y-
coordinates. Elements can be drawn in a unique location; or, if elements occupy the
same coordinates, the order in which they appear in markup determines the order in
which the elements are drawn.
Canvas provides the most flexible layout support of any Panel. Height and Width
properties are used to define the area of the canvas, and elements inside are assigned
absolute coordinates relative to the area of the parent Canvas. Four attached properties,
Canvas.Left, Canvas.Top, Canvas.Right and Canvas.Bottom, allow fine control of object
placement within a Canvas, allowing the developer to position and arrange elements
precisely on the screen.
Canvas can position child elements at any position on the screen, even at coordinates
that are outside of its own defined Height and Width. Furthermore, Canvas is not
affected by the size of its children. As a result, it is possible for a child element to
overdraw other elements outside the bounding rectangle of the parent Canvas. The
default behavior of a Canvas is to allow children to be drawn outside the bounds of the
parent Canvas. If this behavior is undesirable, the ClipToBounds property can be set to
true . This causes Canvas to clip to its own size. Canvas is the only layout element that
C#
XAML
DockPanel
The DockPanel element uses the DockPanel.Dock attached property as set in child
content elements to position content along the edges of a container. When
DockPanel.Dock is set to Top or Bottom, it positions child elements above or below each
other. When DockPanel.Dock is set to Left or Right, it positions child elements to the left
or right of each other. The LastChildFill property determines the position of the final
element added as a child of a DockPanel.
You can use DockPanel to position a group of related controls, such as a set of buttons.
Alternately, you can use it to create a "paned" UI, similar to that found in Microsoft
Outlook.
Sizing to Content
If its Height and Width properties are not specified, DockPanel sizes to its content. The
size can increase or decrease to accommodate the size of its child elements. However,
when these properties are specified and there is no longer room for the next specified
child element, DockPanel does not display that child element or subsequent child
elements and does not measure subsequent child elements.
LastChildFill
By default, the last child of a DockPanel element will "fill" the remaining, unallocated
space. If this behavior is not desired, set the LastChildFill property to false .
C#
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="DockPanel Sample">
<DockPanel LastChildFill="True">
<Border Height="25" Background="SkyBlue" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="SkyBlue" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="LemonChiffon" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Bottom">
<TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
</Border>
<Border Width="200" Background="PaleGreen" BorderBrush="Black"
BorderThickness="1" DockPanel.Dock="Left">
<TextBlock Foreground="Black">Dock = "Left"</TextBlock>
</Border>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Black">This content will "Fill" the remaining
space</TextBlock>
</Border>
</DockPanel>
</Page>
The following example demonstrates how to build a UI similar to that found on the Run
dialog available on the Windows Start menu.
C#
grid1.Children.Add(img1);
grid1.Children.Add(txt1);
grid1.Children.Add(txt2);
grid1.Children.Add(tb1);
grid1.Children.Add(button1);
grid1.Children.Add(button2);
grid1.Children.Add(button3);
mainWindow.Content = grid1;
StackPanel
A StackPanel enables you to "stack" elements in an assigned direction. The default stack
direction is vertical. The Orientation property can be used to control content flow.
Although DockPanel can also "stack" child elements, DockPanel and StackPanel do not
produce analogous results in some usage scenarios. For example, the order of child
elements can affect their size in a DockPanel but not in a StackPanel. This is because
StackPanel measures in the direction of stacking at PositiveInfinity, whereas DockPanel
measures only the available size.
C#
//Define a StackPanel
myStackPanel = new StackPanel();
myStackPanel.Orientation = Orientation.Horizontal;
Grid.SetRow(myStackPanel, 1);
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="StackPanel vs. DockPanel">
<Grid Width="175" Height="150">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
C#
VirtualizingStackPanel
WPF also provides a variation of the StackPanel element that automatically "virtualizes"
data-bound child content. In this context, the word virtualize refers to a technique by
which a subset of elements are generated from a larger number of data items based
upon which items are visible on-screen. It is intensive, both in terms of memory and
processor, to generate a large number of UI elements when only a few may be on the
screen at a given time. VirtualizingStackPanel (through functionality provided by
VirtualizingPanel) calculates visible items and works with the ItemContainerGenerator
from an ItemsControl (such as ListBox or ListView) to only create elements for visible
items.
The VirtualizingStackPanel element is automatically set as the items host for controls
such as the ListBox. When hosting a data bound collection, content is automatically
virtualized, as long as the content is within the bounds of a ScrollViewer. This greatly
improves performance when hosting many child items.
XAML
C#
// Define 3 button elements. The last three buttons are sized at width
// of 75, so the forth button wraps to the next line.
btn1 = new Button();
btn1.Content = "Button 1";
btn1.Width = 200;
btn2 = new Button();
btn2.Content = "Button 2";
btn2.Width = 75;
btn3 = new Button();
btn3.Content = "Button 3";
btn3.Width = 75;
btn4 = new Button();
btn4.Content = "Button 4";
btn4.Width = 75;
// Add the buttons to the parent WrapPanel using the Children.Add method.
myWrapPanel.Children.Add(btn1);
myWrapPanel.Children.Add(btn2);
myWrapPanel.Children.Add(btn3);
myWrapPanel.Children.Add(btn4);
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="WrapPanel Sample">
<Border HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="2">
<WrapPanel Background="LightBlue" Width="200" Height="100">
<Button Width="200">Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
<Button>Button 4</Button>
</WrapPanel>
</Border>
</Page>
There is no practical limit to the amount of nesting that your application can support,
however, it is generally best to limit your application to only use those panels that are
actually necessary for your desired layout. In many cases, a Grid element can be used
instead of nested panels due to its flexibility as a layout container. This can increase
performance in your application by keeping unnecessary elements out of the tree.
The following example demonstrates how to create a UI that takes advantage of nested
Panel elements in order to achieve a specific layout. In this particular case, a DockPanel
element is used to provide UI structure, and nested StackPanel elements, a Grid, and a
Canvas are used to position child elements precisely within the parent DockPanel.
C#
Similarly, custom layout behaviors based on derived classes (such as Canvas or Grid) can
be defined by overriding their ArrangeOverride and MeasureOverride methods.
The following markup demonstrates how to create a custom Panel element. This new
Panel, defined as PlotPanel , supports the positioning of child elements through the use
of hard-coded x- and y- coordinates. In this example, a Rectangle element (not shown)
is positioned at plot point 50 (x), and 50 (y).
C#
return panelDesiredSize ;
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in InternalChildren)
{
double x = 50;
double y = 50;
To view a more complex custom panel implementation, see Create a Custom Content-
Wrapping Panel Sample.
Localization/Globalization Support
UI.
All panel elements natively support the FlowDirection property, which can be used to
dynamically re-flow content based on a user's locale or language settings. For more
information, see FlowDirection.
DockPanel, Grid, and StackPanel are all good choices for localizable UI. Canvas is not a
good choice, however, because it positions content absolutely, making it difficult to
localize.
For additional information on creating WPF applications with localizable user interfaces
(UIs)s, see the Use Automatic Layout Overview.
See also
Walkthrough: My first WPF desktop application
WPF Layout Gallery Sample
Layout
WPF Controls Gallery Sample
Alignment, Margins, and Padding Overview
Create a Custom Content-Wrapping Panel Sample
Attached Properties Overview
Use Automatic Layout Overview
Layout and Design
Panel How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the Panel element and related APIs.
In This Section
Create a Custom Panel Element
Override the Panel OnRender Method
Set the Height Properties of an Element
Set the Width Properties of an Element
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
How to: Create a Custom Panel Element
Article • 02/06/2023
Example
This example shows how to override the default layout behavior of the Panel element
and create custom layout elements that are derived from Panel.
The example defines a simple custom Panel element called PlotPanel , which positions
child elements according to two hard-coded x- and y-coordinates. In this example, x
and y are both set to 50 ; therefore, all child elements are positioned at that location on
the x and y axes.
To implement custom Panel behaviors, the example uses the MeasureOverride and
ArrangeOverride methods. Each method returns the Size data that is necessary to
position and render child elements.
C#
return panelDesiredSize ;
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in InternalChildren)
{
double x = 50;
double y = 50;
See also
Panel
Panels Overview
How to: Override the Panel OnRender
Method
Article • 02/06/2023
This example shows how to override the OnRender method of Panel in order to add
custom graphical effects to a layout element.
Example
Use the OnRender method in order to add graphical effects to a rendered panel
element. For example, you can use this method to add custom border or background
effects. A DrawingContext object is passed as an argument, which provides methods for
drawing shapes, text, images, or videos. As a result, this method is useful for
customization of a panel object.
C#
See also
Panel
Panels Overview
How-to Topics
How to: Set the Height Properties of an
Element
Article • 02/06/2023
Example
This example visually shows the differences in rendering behavior among the four
height-related properties in Windows Presentation Foundation (WPF).
The FrameworkElement class exposes four properties that describe the height
characteristics of an element. These four properties can conflict, and when they do, the
value that takes precedence is determined as follows: the MinHeight value takes
precedence over the MaxHeight value, which in turn takes precedence over the Height
value. A fourth property, ActualHeight, is read-only, and reports the actual height as
determined by interactions with the layout process.
XAML
XAML
The following code-behind examples handle the events that the SelectionChanged
event raises. Each handler takes the input from the ListBox, parses the value as a Double,
and applies the value to the specified height-related property. The height values are also
converted to a string and written to various TextBlock elements (definition of those
elements is not shown in the selected XAML).
C#
See also
FrameworkElement
ListBox
ActualHeight
MaxHeight
MinHeight
Height
Set the Width Properties of an Element
Panels Overview
Height Properties Sample
How to: Set the Width Properties of an
Element
Article • 02/06/2023
Example
This example visually shows the differences in rendering behavior among the four
width-related properties in Windows Presentation Foundation (WPF).
The FrameworkElement class exposes four properties that describe the width
characteristics of an element. These four properties can conflict, and when they do, the
value that takes precedence is determined as follows: the MinWidth value takes
precedence over the MaxWidth value, which in turn takes precedence over the Width
value. A fourth property, ActualWidth, is read-only, and reports the actual width as
determined by interactions with the layout process.
XAML
XAML
The following code-behind examples handle the events that the SelectionChanged
event raises. Each custom method takes the input from the ListBox, parses the value as a
Double, and applies the value to the specified width-related property. The width values
are also converted to a string and written to various TextBlock elements (definition of
those elements is not shown in the selected XAML).
C#
See also
ListBox
FrameworkElement
ActualWidth
MaxWidth
MinWidth
Width
Panels Overview
Set the Height Properties of an Element
Width Properties Comparison Sample
PasswordBox
Article • 02/06/2023
See also
TextBox
RichTextBox
Control Library
Popup
Article • 02/06/2023
The Popup control displays content in a separate window that floats over the current
application window.
The following illustration shows a Popup control that is positioned with respect to a
Button that is its parent:
In This Section
Popup Overview
Popup Placement Behavior
How-to Topics
Reference
Popup
Related Sections
Popup Overview
Article • 02/06/2023
The Popup control provides a way to display content in a separate window that floats
over the current application window relative to a designated element or screen
coordinate. This topic introduces the Popup control and provides information about its
use.
What Is a Popup?
A Popup control displays content in a separate window relative to an element or point
on the screen. When the Popup is visible, the IsOpen property is set to true .
7 Note
A Popup does not automatically open when the mouse pointer moves over its
parent object. If you want a Popup to automatically open, use the ToolTip or
ToolTipService class. For more information, see ToolTip Overview.
Creating a Popup
The following example shows how to define a Popup control that is the child element of
a ToggleButton control. Because a ToggleButton can have only one child element, this
example places the text for the ToggleButton and the Popup controls in a StackPanel.
The content of the Popup is displayed in a separate window that floats over the
application window near the related ToggleButton control.
XAML
ToolTip. If you want to create a tooltip for an element, use the ToolTip and
ToolTipService classes. For more information, see ToolTip Overview.
ContextMenu. If you want to create a context menu for an element, use the
ContextMenu control. For more information, see ContextMenu Overview.
ComboBox. If you want to create a selection control that has a drop-down list box
that can be shown or hidden, use the ComboBox control.
Expander. If you want to create a control that displays a header with a collapsible
area that displays content, use the Expander control. For more information, see
Expander Overview.
Animation
The Popup control has built-in support for the animations that are typically associated
with behaviors like fade-in and slide-in. You can turn on these animations by setting the
PopupAnimation property to a PopupAnimation enumeration value. For Popup
animations to work correctly, you must set the AllowsTransparency property to true .
You can also apply animations like Storyboard to the Popup control.
Popup Size
By default, a Popup is automatically sized to its content. When auto-sizing occurs, some
bitmap effects may be hidden because the default size of the screen area that is defined
for the Popup content does not provide enough space for the bitmap effects to display.
Popup content can also be obscured when you set a RenderTransform on the content. In
this scenario, some content might be hidden if the content of the transformed Popup
extends beyond the area of the original Popup. If a bitmap effect or transform requires
more space, you can define a margin around the Popup content in order to provide
more area for the control.
The Popup control maintains a reference to its Child content as a logical child. When the
new window is created, the content of Popup becomes a visual child of the window and
remains the logical child of Popup. Conversely, Popup remains the logical parent of its
Child content.
See also
Popup
PopupPrimaryAxis
PlacementMode
CustomPopupPlacement
CustomPopupPlacementCallback
ToolTip
ToolTipService
How-to Topics
How-to Topics
Popup Placement Behavior
Article • 06/02/2023
A Popup control displays content in a separate window that floats over an application. You can specify the
position of a Popup relative to a control, the mouse, or the screen by using the PlacementTarget, Placement,
PlacementRectangle, HorizontalOffset, and VerticalOffset properties. These properties work together to give
you flexibility in specifying the position of the Popup.
7 Note
The ToolTip and ContextMenu classes also define these five properties and behave similarly.
XAML
</Popup>
<Popup IsOpen="True" PlacementTarget="{Binding ElementName=image1}"
Placement="Top">
<TextBlock FontSize="14" Background="LightGreen">Placement=Top</TextBlock>
</Popup>
<Popup IsOpen="True" PlacementTarget="{Binding ElementName=image1}"
Placement="Left">
<TextBlock FontSize="14" Background="LightGreen">Placement=Left</TextBlock>
</Popup>
<Popup IsOpen="True" PlacementTarget="{Binding ElementName=image1}"
Placement="Right">
<TextBlock FontSize="14" Background="LightGreen">Placement=Right</TextBlock>
</Popup>
</Canvas>
The following illustration shows the image and the Popup controls
This simple example demonstrates how to set the PlacementTarget and Placement properties, but by using the
PlacementRectangle, HorizontalOffset, and VerticalOffset properties, you have even more control over where
the Popup is positioned.
![NOTE] Depending on your Windows settings related to handedness, the popup may be left or right-
aligned when shown on the top or bottom. The previous image demonstrates right-handedness alignment,
which places the popup to the left.
Target object
Target area
Target origin
These terms provide a convenient way to refer to various aspects of the Popup and the control that it is
associated with.
Target Object
The target object is the element that the Popup is associated with. If the PlacementTarget property is set, it
specifies the target object. If PlacementTarget is not set, and the Popup has a parent, the parent is the target
object. If there is no PlacementTarget value and no parent, there is no target object, and the Popup is
positioned relative to the screen.
The following example creates a Popup that is the child of a Canvas. The example does not set the
PlacementTarget property on the Popup. The default value for Placement is PlacementMode.Bottom, so the
Popup appears below the Canvas.
XAML
The following illustration shows that the Popup is positioned relative to the Canvas.
The following example creates a Popup that is the child of a Canvas, but this time the PlacementTarget is set to
ellipse1 , so the popup appears below the Ellipse.
XAML
<Ellipse Name="ellipse1"
Canvas.Top="60" Canvas.Left="50"
Height="85" Width="60"
Fill="Black"/>
The following illustration shows that the Popup is positioned relative to the Ellipse.
7 Note
For ToolTip, the default value of Placement is Mouse. For ContextMenu, the default value of Placement is
MousePoint. These values are explained later, in "How the Properties Work Together."
Target Area
The target area is the area on the screen that the Popup is relative to. In the previous examples, the Popup is
aligned with the bounds of the target object, but in some cases, the Popup is aligned to other bounds, even if
the Popup has a target object. If the PlacementRectangle property is set, the target area is different than the
bounds of the target object.
The following example creates two Canvas objects, each one containing a Rectangle and a Popup. In both
cases, the target object for the Popup is the Canvas. The Popup in the first Canvas has the PlacementRectangle
set, with its X, Y, Width, and Height properties set to 50, 50, 50, and 100, respectively. The Popup in the second
Canvas does not have the PlacementRectangle set. As a result, the first Popup is positioned below the
PlacementRectangle and the second Popup is positioned below the Canvas. Each Canvas also contains a
Rectangle that has the same bounds as the PlacementRectangle for the first Popup. Note that the
PlacementRectangle does not create a visible element in the application; the example creates a Rectangle to
represent the PlacementRectangle.
XAML
</StackPanel>
The following example creates a Popup and sets the HorizontalOffset and VerticalOffset properties to 20. The
Placement property is set to Bottom (the default), so the target origin is the bottom-left corner of the target
area and the popup alignment point is the top-left corner of the Popup.
XAML
The following table describes the target object, target area, target origin, and popup alignment point and
indicates whether PlacementTarget and PlacementRectangle are used for each PlacementMode enumeration
value.
PlacementMode Target object Target area Target origin Popup alignment point
Absolute Not applicable. The screen, or The top-left corner of the target The top-left corner of the Popup.
PlacementTarget PlacementRectangle area.
is ignored. if it is set. The
PlacementRectangle
is relative to the
screen.
PlacementMode Target object Target area Target origin Popup alignment point
AbsolutePoint Not applicable. The screen, or The top-left corner of the target The top-left corner of the Popup.
PlacementTarget PlacementRectangle area.
is ignored. if it is set. The
PlacementRectangle
is relative to the
screen.
Bottom PlacementTarget The target object, The bottom-left corner of the The top-left corner of the Popup.
or parent. or target area.
PlacementRectangle
if it is set. The
PlacementRectangle
is relative to the
target object.
Center PlacementTarget The target object, The center of the target area. The center of the Popup.
or parent. or
PlacementRectangle
if it is set. The
PlacementRectangle
is relative to the
target object.
Left PlacementTarget The target object, The top-left corner of the target The top-right corner of the
or parent. or area. Popup.
PlacementRectangle
if it is set. The
PlacementRectangle
is relative to the
target object.
Mouse Not applicable. The bounds of the The bottom-left corner of the The top-left corner of the Popup.
PlacementTarget mouse pointer. target area.
is ignored. PlacementRectangle
is ignored.
MousePoint Not applicable. The bounds of the The top-left corner of the target The top-left corner of the Popup.
PlacementTarget mouse pointer. area.
is ignored. PlacementRectangle
is ignored.
Relative PlacementTarget The target object, The top-left corner of the target The top-left corner of the Popup.
or parent. or area.
PlacementRectangle
if it is set. The
PlacementRectangle
is relative to the
target object.
PlacementMode Target object Target area Target origin Popup alignment point
RelativePoint PlacementTarget The target object, The top-left corner of the target The top-left corner of the Popup.
or parent. or area.
PlacementRectangle
if it is set. The
PlacementRectangle
is relative to the
target object.
Right PlacementTarget The target object, The top-right corner of the target The top-left corner of the Popup.
or parent. or area.
PlacementRectangle
if it is set. The
PlacementRectangle
is relative to the
target object.
Top PlacementTarget The target object, The top-left corner of the target The bottom-left corner of the
or parent. or area. Popup.
PlacementRectangle
if it is set. The
PlacementRectangle
is relative to the
target object.
The following illustrations show the Popup, target area, target origin, and popup alignment point for each
PlacementMode value. In each figure, the target area is yellow, and the Popup is blue.
When the Popup Encounters the Edge of the Screen
For security reasons, a Popup cannot be hidden by the edge of a screen. One of the following three things
happens when the Popup encounters a screen edge:
The popup realigns itself along the screen edge that would obscure the Popup.
The popup uses a different target origin and popup alignment point.
The behavior of the Popup when it encounters a screen edge depends on the value of the Placement property
and which screen edge the popup encounters. The following table summarizes the behavior when the Popup
encounters a screen edge for each PlacementMode value.
Absolute Aligns to the top edge. Aligns to the bottom Aligns to the left Aligns to the right
edge. edge. edge.
AbsolutePoint Aligns to the top edge. The popup alignment Aligns to the left The popup
point changes to the edge. alignment point
bottom-left corner of the changes to the top-
Popup. right corner of the
Popup.
Bottom Aligns to the top edge. The target origin changes Aligns to the left Aligns to the right
to the top-left corner of edge. edge.
the target area and the
popup alignment point
changes to the bottom-
left corner of the Popup.
Center Aligns to the top edge. Aligns to the bottom Aligns to the left Aligns to the right
edge. edge. edge.
Left Aligns to the top edge. Aligns to the bottom The target origin Aligns to the right
edge. changes to the top- edge.
right corner of the
target area and the
popup alignment
point changes to
the top-left corner
of the Popup.
Mouse Aligns to the top edge. The target origin changes Aligns to the left Aligns to the right
to the top-left corner of edge. edge.
the target area (the
bounds of the mouse
pointer) and the popup
alignment point changes
to the bottom-left corner
of the Popup.
MousePoint Aligns to the top edge. The popup alignment Aligns to the left The popup
point changes to the edge. alignment point
bottom-left corner of the changes to the top-
Popup. right corner of the
popup.
Relative Aligns to the top edge. Aligns to the bottom Aligns to the left Aligns to the right
edge. edge. edge.
RelativePoint Aligns to the top edge. The popup alignment Aligns to the left The popup
point changes to the edge. alignment point
bottom-left corner of the changes to the top-
Popup. right corner of the
popup.
Right Aligns to the top edge. Aligns to the bottom Aligns to the left The target origin
edge. edge. changes to the top-
left corner of the
target area and the
popup alignment
point changes to
the top-right corner
of the Popup.
PlacementMode Top edge Bottom edge Left edge Right edge
Top The target origin changes to Aligns to the bottom Aligns to the left Aligns to the right
the bottom-left corner of the edge. edge. edge.
target area and the popup
alignment point changes to
the top-left corner of the
Popup. In effect, this is the
same as when Placement is
Bottom.
The following illustration demonstrates that when the bottom screen edge hides all or part of the Popup, the
popup alignment point is the bottom-left corner of the Popup.
The following illustration demonstrates that when the Popup is hidden by the right screen edge, the popup
alignment point is the top-right corner of the Popup.
If the Popup encounters the bottom and right screen edges, the popup alignment point is the bottom-right
corner of the Popup.
The following illustration demonstrates that when Placement is Bottom and the Popup encounters the bottom
screen edge, the target origin is the top-left corner of the target area and the popup alignment point is the
bottom-left corner of the Popup.
The following illustration demonstrates that when Placement is Left and the Popup encounters the left screen
edge, the target origin is the top-right corner of the target area and the popup alignment point is the top-left
corner of the Popup.
The following illustration demonstrates that when Placement is Right and the Popup encounters the right
screen edge, the target origin is the top-left corner of the target area and the popup alignment point is the
top-right corner of the Popup.
The following illustration demonstrates that when Placement is Top and the Popup encounters the top screen
edge, the target origin is the bottom-left corner of the target area and the popup alignment point is the top-
left corner of the Popup.
The following illustration demonstrates that when Placement is Mouse and the Popup encounters the bottom
screen edge, the target origin is the top-left corner of the target area (the bounds of the mouse pointer) and
the popup alignment point is the bottom-left corner of the Popup.
See also
Popup Placement Sample
Popup How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the Popup control to display content in a
separate window that floats over the current application window.
In This Section
Animate a Popup
Specify a Custom Popup Position
Reference
Popup
Related Sections
Popup Overview
How to: Animate a Popup
Article • 02/06/2023
Example
The following example sets the PopupAnimation property to a value of Slide, which
causes the Popup to "slide-in" when it appears.
For the transform to work correctly, the example must set the AllowsTransparency
property to true . In addition, the Margin on the Canvas content must specify enough
space for the Popup to rotate.
XAML
The following example shows how a Click event, which occurs when a Button is clicked,
triggers the Storyboard that starts the animation.
XAML
<Button HorizontalAlignment="Left" Width="200" Margin="20,10,0,0">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="theTransform"
Storyboard.TargetProperty="(RotateTransform.Angle)"
From="0" To="360" Duration="0:0:5" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
Click to see the Popup animate
</Button>
See also
RenderTransform
BulletDecorator
RotateTransform
Storyboard
Popup
How-to Topics
Popup Overview
How to: Specify a Custom Popup
Position
Article • 02/06/2023
This example shows how to specify a custom position for a Popup control when the
Placement property is set to Custom.
Example
When the Placement property is set to Custom, the Popup calls a defined instance of the
CustomPopupPlacementCallback delegate. This delegate returns a set of possible points
that are relative to the top-left corner of the target area and the top-left corner of the
Popup. The Popup placement occurs at the point that provides the best visibility.
The following example shows how to define the position of a Popup by setting the
Placement property to Custom. It also shows how to create and assign a
CustomPopupPlacementCallback delegate in order to position the Popup. The callback
delegate returns two CustomPopupPlacement objects. If the Popup is hidden by a
screen edge at the first position, the Popup is placed at the second position.
XAML
<Popup Name="popup1"
PlacementTarget ="{Binding ElementName=myButton}"
Placement="Custom">
<TextBlock Height="60" Width="200"
Background="LightGray"
TextWrapping="Wrap">Popup positioned by using
CustomPopupPlacement callback delegate</TextBlock>
</Popup>
C#
CustomPopupPlacement placement2 =
new CustomPopupPlacement(new Point(10, 20),
PopupPrimaryAxis.Horizontal);
CustomPopupPlacement[] ttplaces =
new CustomPopupPlacement[] { placement1, placement2 };
return ttplaces;
}
C#
popup1.CustomPopupPlacementCallback =
new CustomPopupPlacementCallback(placePopup);
See also
Popup
Popup overview
How-to articles
ProgressBar
Article • 02/06/2023
In This Section
Reference
ProgressBar
StatusBar
Related Sections
PrintDialog
Article • 02/06/2023
The PrintDialog control is used to instantiate a standard print dialog box that
automatically configures a PrintTicket and PrintQueue according to user input.
Reference
PrintDialog
PrintTicket
PrintQueue
See also
Printing Overview
Documents in WPF
RadioButton
Article • 02/06/2023
RadioButton controls are usually grouped together to offer users a single choice among
several options; only one button at a time can be selected.
Typical RadioButton
Reference
ToggleButton
Related Sections
RepeatButton
Article • 02/06/2023
The following graphic shows an example of the three states of a repeat button control,
Default, PointerFocused, and Pressed. The first button shows the default state of the
RepeatButton. The second shows how the appearance of the button changes when the
mouse pointer hovers over the button, giving it focus. The last button shows the
appearance of the RepeatButton when the user presses the mouse button over the
control.
Typical RepeatButton
In This Section
Reference
RepeatButton
Related Sections
RichTextBox
Article • 02/06/2023
The RichTextBox element defines an editing control with built-in support for features
such as cut and paste, rich document presentation, and content selection.
In This Section
RichTextBox Overview
How-to Topics
See also
TextBox
Documents in WPF
Flow Document Overview
RichTextBox Overview
Article • 03/17/2022
The RichTextBox control enables you to display or edit flow content including
paragraphs, images, tables, and more. This topic introduces the TextBox class and
provides examples of how to use it in both Extensible Application Markup Language
(XAML) and C#.
TextBox or RichTextBox?
Both RichTextBox and TextBox allow users to edit text, however, the two controls are
used in different scenarios. A RichTextBox is a better choice when it is necessary for the
user to edit formatted text, images, tables, or other rich content. For example, editing a
document, article, or blog that requires formatting, images, etc is best accomplished
using a RichTextBox. A TextBox requires less system resources than a RichTextBox and it
is ideal when only plain text needs to be edited (i.e. usage in forms). See TextBox
Overview for more information on TextBox. The table below summarizes the main
features of TextBox and RichTextBox.
7 Note
Although TextBox does not support formatting related commands like ToggleBold
(Ctr+B), many basic commands are supported by both controls such as
MoveToLineEnd.
The features from the table above are covered in more detail later.
Creating a RichTextBox
The code below shows how to create a RichTextBox that a user can edit rich content in.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Page>
Specifically, the content edited in a RichTextBox is flow content. Flow content can
contain many types of elements including formatted text, images, lists, and tables. See
Flow Document Overview for in depth information on flow documents. In order to
contain flow content, a RichTextBox hosts a FlowDocument object which in turn contains
the editable content. To demonstrate flow content in a RichTextBox, the following code
shows how to create a RichTextBox with a paragraph and some bolded text.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<RichTextBox>
<FlowDocument>
<Paragraph>
This is flow content and you can <Bold>edit me!</Bold>
</Paragraph>
</FlowDocument>
</RichTextBox>
</StackPanel>
</Page>
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Documents;
namespace SDKSample
{
public partial class BasicRichTextBoxWithContentExample : Page
{
public BasicRichTextBoxWithContentExample()
{
StackPanel myStackPanel = new StackPanel();
myStackPanel.Children.Add(myRichTextBox);
this.Content = myStackPanel;
}
}
}
Elements like Paragraph and Bold determine how the content inside a RichTextBox
appears. As a user edits RichTextBox content, they change this flow content. To learn
more about the features of flow content and how to work with it, see Flow Document
Overview.
7 Note
Flow content inside a RichTextBox does not behave exactly like flow content
contained in other controls. For example, there are no columns in a RichTextBox
and hence no automatic resizing behavior. Also, built in features like search,
viewing mode, page navigation, and zoom are not available within a RichTextBox.
Context Menu
By default, both TextBox and RichTextBox have a context menu that appears when a user
right-clicks inside the control. The context menu allows the user to cut, copy, or paste
(see illustration below).
You can create your own custom context menu to override the default one. See Position
a Custom Context Menu in a RichTextBox for more information.
Editing Commands
Editing commands enable users to format editable content inside a RichTextBox. Besides
basic editing commands, RichTextBox includes formatting commands that TextBox does
not support. For example, when editing in a RichTextBox, a user could press Ctr+B to
toggle bold text formatting. See EditingCommands for a complete list of commands
available. In addition to using keyboard shortcuts, you can hook commands up to other
controls like buttons. The following example shows how to create a simple tool bar
containing buttons that the user can use to change text formatting.
XAML
<Window x:Class="RichTextBoxInputPanelDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="400"
Width="600"
>
<Grid>
<DockPanel Name="mainPanel">
<!-- This tool bar contains all the editing buttons. -->
<ToolBar Name="mainToolBar" Height="30" DockPanel.Dock="Top">
</ToolBar>
<!-- By default pressing tab moves focus to the next control. Setting
AcceptsTab to true allows the
RichTextBox to accept tab characters. -->
<RichTextBox Name="mainRTB" AcceptsTab="True"></RichTextBox>
</DockPanel>
</Grid>
</Window>
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.SaveLoadPrintRTB" >
<StackPanel>
<RichTextBox Name="richTB">
<FlowDocument>
<Paragraph>
<Run>Paragraph 1</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
C#
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace SDKSample
{
pd.PrintDocument((((IDocumentPaginatorSource)richTB.Document).DocumentPagina
tor), "printing as paginator");
}
}
}
}
See also
How-to Topics
TextBox Overview
RichTextBox How-to Topics
Article • 02/06/2023
This section provides examples that demonstrate how to accomplish common tasks
using the RichTextBox control.
In This Section
Extract the Text Content from a RichTextBox
Change Selection in a RichTextBox Programmatically
Save, Load, and Print RichTextBox Content
Position a Custom Context Menu in a RichTextBox
See also
TextBox
Documents in WPF
Flow Document Overview
How to: Extract the Text Content from a
RichTextBox
Article • 02/06/2023
This example shows how to extract the contents of a RichTextBox as plain text.
XAML
<RichTextBox Name="richTB">
<FlowDocument>
<Paragraph>
<Run>Paragraph 1</Run>
</Paragraph>
<Paragraph>
<Run>Paragraph 2</Run>
</Paragraph>
<Paragraph>
<Run>Paragraph 3</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
The method creates a new TextRange from the contents of the RichTextBox, using the
ContentStart and ContentEnd to indicate the range of the contents to extract.
ContentStart and ContentEnd properties each return a TextPointer, and are accessible on
the underlying FlowDocument that represents the contents of the RichTextBox.
TextRange provides a Text property, which returns the plain text portions of the
TextRange as a string.
C#
string StringFromRichTextBox(RichTextBox rtb)
{
TextRange textRange = new TextRange(
// TextPointer to the start of content in the RichTextBox.
rtb.Document.ContentStart,
// TextPointer to the end of content in the RichTextBox.
rtb.Document.ContentEnd
);
See also
RichTextBox Overview
TextBox Overview
Change Selection in a RichTextBox
Programmatically
Article • 02/06/2023
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.ChangeSelectionProgrammaticaly" >
<StackPanel>
<RichTextBox GotMouseCapture="ChangeSelection" Name="richTB">
<FlowDocument>
<Paragraph Name="myParagraph">
<Run>
When the user clicks in the RichTextBox, the selected
text changes programmatically.
</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</StackPanel>
</Page>
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace SDKSample
{
public partial class ChangeSelectionProgrammaticaly : Page
{
See also
RichTextBox Overview
TextBox Overview
How to: Save, Load, and Print
RichTextBox Content
Article • 02/06/2023
The following example shows how to save content of a RichTextBox to a file, load that
content back into the RichTextBox, and print the contents.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.SaveLoadPrintRTB" >
<StackPanel>
<RichTextBox Name="richTB">
<FlowDocument>
<Paragraph>
<Run>Paragraph 1</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
</Page>
C#
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace SDKSample
{
pd.PrintDocument((((IDocumentPaginatorSource)richTB.Document).DocumentPagina
tor), "printing as paginator");
}
}
}
}
See also
RichTextBox Overview
TextBox Overview
How to: Position a Custom Context
Menu in a RichTextBox
Article • 02/06/2023
This example shows how to position a custom context menu for a RichTextBox.
When you implement a custom context menu for a RichTextBox, you are responsible for
handling the placement of the context menu. By default, a custom context menu is
opened at the center of the RichTextBox.
C#
richTextBox.ContextMenuOpening += new
ContextMenuEventHandler(richTextBox_ContextMenuOpening);
C#
See also
RichTextBox Overview
TextBox Overview
ScrollBar
Article • 02/06/2023
A ScrollBar allows you to view content that is outside of the current viewing area by
sliding the Thumb to make the content visible.
In This Section
Customize the Thumb Size on a ScrollBar
Reference
ScrollBar
Track
Thumb
ScrollViewer
How to: Customize the Thumb Size on a
ScrollBar
Article • 02/06/2023
This topic explains how to set the Thumb of a ScrollBar to a fixed size and how to
specify a minimum size for the Thumb of a ScrollBar.
XAML
<Style TargetType="ScrollBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid Name="Bg"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="{DynamicResource
{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
<RowDefinition Height="0.00001*"/>
<RowDefinition MaxHeight="{DynamicResource
{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
</Grid.RowDefinitions>
<RepeatButton Style="{StaticResource ScrollBarButton}"
IsEnabled="{TemplateBinding IsMouseOver}"
Height="18"
Command="ScrollBar.LineUpCommand"
Content="M 0 4 L 8 4 L 4 0 Z" />
<!-- Set the ViewporSize to NaN to disable autosizing of the
Thumb. -->
<Track Name="PART_Track"
ViewportSize="NaN"
IsDirectionReversed="true"
Grid.Row="1"
Grid.ZIndex="-1">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource
VerticalScrollBarPageButton}"
Command="ScrollBar.PageUpCommand"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource
VerticalScrollBarPageButton}"
Command="ScrollBar.PageDownCommand"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<!-- Set the height of the Thumb.-->
<Thumb Height="30"/>
</Track.Thumb>
</Track>
<RepeatButton
Grid.Row="2"
Style="{StaticResource ScrollBarButton}"
Height="18"
Command="ScrollBar.LineDownCommand"
Content="M 0 0 L 4 4 L 8 0 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="PART_Track" Property="IsEnabled"
Value="false">
<Setter TargetName="PART_Track" Property="Visibility"
Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<Style TargetType="ScrollBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid Name="Bg"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="{DynamicResource
{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
<RowDefinition Height="0.00001*"/>
<RowDefinition MaxHeight="{DynamicResource
{x:Static SystemParameters.VerticalScrollBarButtonHeightKey}}"/>
</Grid.RowDefinitions>
<RepeatButton Style="{StaticResource ScrollBarButton}"
IsEnabled="{TemplateBinding IsMouseOver}"
Height="18"
Command="ScrollBar.LineUpCommand"
Content="M 0 4 L 8 4 L 4 0 Z" />
<Track Name="PART_Track"
IsDirectionReversed="true"
Grid.Row="1"
Grid.ZIndex="-1">
<Track.Resources>
<!-- Set the Thumb's minimum height to 50.
The Thumb's minimum height is half the
value of VerticalScrollBarButtonHeightKey. -->
<sys:Double
x:Key="{x:Static
SystemParameters.VerticalScrollBarButtonHeightKey}">
100
</sys:Double>
</Track.Resources>
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource
VerticalScrollBarPageButton}"
Command="ScrollBar.PageUpCommand"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource
VerticalScrollBarPageButton}"
Command="ScrollBar.PageDownCommand"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb/>
</Track.Thumb>
</Track>
<RepeatButton
Grid.Row="2"
Style="{StaticResource ScrollBarButton}"
Height="18"
Command="ScrollBar.LineDownCommand"
Content="M 0 0 L 4 4 L 8 0 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="PART_Track"
Property="IsEnabled" Value="false">
<Setter TargetName="PART_Track"
Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
See also
ScrollBar Styles and Templates
ScrollViewer
Article • 02/06/2023
The ScrollViewer control creates a scrollable region wherein content can be scrolled
horizontally or vertically.
In This Section
ScrollViewer Overview
How-to Topics
Reference
ScrollBar
ScrollViewer
See also
Panels Overview
Layout
ScrollViewer Overview
Article • 03/17/2022
Content within a user interface is often larger than a computer screen's display area. The
ScrollViewer control provides a convenient way to enable scrolling of content in
Windows Presentation Foundation (WPF) applications. This topic introduces the
ScrollViewer element and provides several usage examples.
The ScrollViewer control responds to both mouse and keyboard commands, and defines
numerous methods with which to scroll content by predetermined increments. You can
use the ScrollChanged event to detect a change in a ScrollViewer state.
A ScrollViewer can only have one child, typically a Panel element that can host a
Children collection of elements. The Content property defines the sole child of the
ScrollViewer.
C#
C#
// Define a ScrollViewer
myScrollViewer = new ScrollViewer();
myScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="ScrollViewer Sample">
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock TextWrapping="Wrap" Margin="0,0,0,20">Scrolling is enabled
when it is necessary.
Resize the window, making it larger and smaller.</TextBlock>
<Rectangle Fill="Red" Width="500" Height="500"></Rectangle>
</StackPanel>
</ScrollViewer>
</Page>
Styling a ScrollViewer
Like all controls in Windows Presentation Foundation, the ScrollViewer can be styled in
order to change the default rendering behavior of the control. For additional
information on control styling, see Styling and Templating.
Paginating Documents
For document content, an alternative to scrolling is to choose a document container
that supports pagination. FlowDocument is for documents that are designed to be
hosted within a viewing control, such as FlowDocumentPageViewer, that supports
paginating content across multiple pages, preventing the need for scrolling.
DocumentViewer provides a solution for viewing FixedDocument content, which uses
traditional scrolling to display content outside the realm of the display area.
For additional information about document formats and presentation options, see
Documents in WPF.
See also
ScrollViewer
ScrollBar
IScrollInfo
How to: Create a Scroll Viewer
Documents in WPF
ScrollBar Styles and Templates
Controls
ScrollViewer How-to Topics
Article • 02/06/2023
The topics in this section demonstrate how to use the ScrollViewer element to create
scrollable regions in your applications.
In This Section
Handle the ScrollChanged Event
Scroll Content by Using the IScrollInfo Interface
Use the Content-Scrolling Methods of ScrollViewer
Reference
ScrollBar
ScrollViewer
See also
Panels Overview
Layout
How to: Handle the ScrollChanged
Event
Article • 02/06/2023
Example
This example shows how to handle the ScrollChanged event of a ScrollViewer.
XAML
XAML
<Paragraph>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
nonummy nibh euismod tincidunt ut
laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim
veniam, quis nostrud exerci tation
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
Duis autem vel eum iriure.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
nonummy nibh euismod tincidunt ut
laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim
veniam, quis nostrud exerci tation
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
Duis autem vel eum iriure.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam
nonummy nibh euismod tincidunt ut
laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim
veniam, quis nostrud exerci tation
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
Duis autem vel eum iriure.
</Paragraph>
</FlowDocument>
</ScrollViewer>
C#
This example shows how to scroll content by using the IScrollInfo interface.
Example
The following example demonstrates the features of the IScrollInfo interface. The
example creates a StackPanel element in Extensible Application Markup Language
(XAML) that is nested in a parent ScrollViewer. The child elements of the StackPanel can
be scrolled logically by using the methods defined by the IScrollInfo interface and cast
to the instance of StackPanel ( sp1 ) in code.
XAML
Each Button in the XAML file triggers an associated custom method that controls
scrolling behavior in StackPanel. The following example shows how to use the LineUp
and LineDown methods; it also generically shows how to use all the positioning
methods that the IScrollInfo class defines.
C#
private void spLineUp(object sender, RoutedEventArgs e)
{
((IScrollInfo)sp1).LineUp();
}
private void spLineDown(object sender, RoutedEventArgs e)
{
((IScrollInfo)sp1).LineDown();
}
See also
ScrollViewer
IScrollInfo
StackPanel
ScrollViewer Overview
How-to Topics
Panels Overview
How to: Use the Content-Scrolling
Methods of ScrollViewer
Article • 02/06/2023
This example shows how to use the scrolling methods of the ScrollViewer element.
These methods provide incremental scrolling of content, either by line or by page, in a
ScrollViewer.
Example
The following example creates a ScrollViewer named sv1 , which hosts a child TextBlock
element. Because the TextBlock is larger than the parent ScrollViewer, scroll bars appear
in order to enable scrolling. Button elements that represent the various scrolling
methods are docked on the left in a separate StackPanel. Each Button in the XAML file
calls a related custom method that controls scrolling behavior in ScrollViewer.
XAML
C#
See also
ScrollViewer
StackPanel
Separator
Article • 02/06/2023
A Separator control draws a line, horizontal or vertical, between items in controls, such
as ListBox, Menu, and ToolBar.
In This Section
Reference
Separator
Slider
Article • 02/06/2023
The Slider allows you select from a range of values by moving a Thumb along a Track.
In This Section
Customize the Ticks on a Slider
Reference
Slider
Track
Thumb
How to: Customize the Ticks on a Slider
Article • 08/18/2022
This example shows how to create a Slider control that has tick marks.
Example
The TickBar displays when you set the TickPlacement property to a value other than
None, which is the default value.
The following example shows how to create a Slider with a TickBar that displays tick
marks. The TickPlacement and TickFrequency properties define the location of the tick
marks and the interval between them. When you move the Thumb, tooltips display the
value of the Slider. The AutoToolTipPlacement property defines where the tooltips occur.
The Thumb movements correspond to the location of the tick marks because
IsSnapToTickEnabled is set to true .
The following example shows how to use the Ticks property to create tick marks along
the Slider at irregular intervals.
XAML
See also
Slider
TickBar
TickPlacement
How to: Bind a Slider to a Property Value
StackPanel
Article • 02/06/2023
In This Section
How-to Topics
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
StackPanel How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the StackPanel element to stack content
horizontally or vertically.
In This Section
Choose Between StackPanel and DockPanel
Create a StackPanel
Horizontally or Vertically Align Content in a StackPanel
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
How to: Choose between StackPanel
and DockPanel
Article • 03/18/2023
Although you can use either DockPanel or StackPanel to stack child elements, the two
controls do not always produce the same results. For example, the order that you place
child elements can affect the size of child elements in a DockPanel but not in a
StackPanel. This different behavior occurs because StackPanel measures in the direction
of stacking at Double.PositiveInfinity; however, DockPanel measures only the available
size.
The examples in this article create a Grid with two panels, which looks like the following
image:
XAML example
The following example demonstrates the key difference between DockPanel and
StackPanel when designing a page in XAML.
XAML
Code-based example
The following example demonstrates the key difference between DockPanel and
StackPanel. This code is run in the Window.Loaded event handler:
C#
gridContainer.RowDefinitions.Add(new RowDefinition());
gridContainer.RowDefinitions.Add(new RowDefinition());
// Dock panel
DockPanel panel1 = new DockPanel();
Grid.SetRow(panel1, 0);
// Create the three controls for the panel
panel1.Children.Add(new ContentControl() { Template = viewBoxTemplate
});
panel1.Children.Add(new ContentControl() { Template = viewBoxTemplate
});
panel1.Children.Add(new ContentControl() { Template = viewBoxTemplate
});
// Stack panel
StackPanel panel2 = new StackPanel();
panel2.Orientation = Orientation.Horizontal;
Grid.SetRow(panel2, 1);
See also
StackPanel
DockPanel
Panels Overview
How to: Create a StackPanel
Article • 02/06/2023
Example
A StackPanel allows you to stack elements in a specified direction. By using properties
that are defined on StackPanel, content can flow both vertically, which is the default
setting, or horizontally.
The following example vertically stacks five TextBlock controls, each with a different
Border and Background, by using StackPanel. The child elements that have no specified
Width stretch to fill the parent window; however, the child elements that have a
specified Width, are centered within the window.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="StackPanel Sample">
<StackPanel>
<Border Background="SkyBlue" BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Black" FontSize="12">Stacked Item
#1</TextBlock>
</Border>
<Border Width="400" Background="CadetBlue" BorderBrush="Black"
BorderThickness="1">
<TextBlock Foreground="Black" FontSize="14">Stacked Item
#2</TextBlock>
</Border>
<Border Background="LightGoldenRodYellow" BorderBrush="Black"
BorderThickness="1">
<TextBlock Foreground="Black" FontSize="16">Stacked Item
#3</TextBlock>
</Border>
<Border Width="200" Background="PaleGreen" BorderBrush="Black"
BorderThickness="1">
<TextBlock Foreground="Black" FontSize="18">Stacked Item
#4</TextBlock>
</Border>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Black" FontSize="20">Stacked Item
#5</TextBlock>
</Border>
</StackPanel>
</Page>
See also
StackPanel
Panels Overview
How-to Topics
How to: Horizontally or Vertically Align
Content in a StackPanel
Article • 02/06/2023
This example shows how to adjust the Orientation of content within a StackPanel
element, and also how to adjust the HorizontalAlignment and VerticalAlignment of child
content.
Example
The following example creates three ListBox elements in Extensible Application Markup
Language (XAML). Each ListBox represents the possible values of the Orientation,
HorizontalAlignment, and VerticalAlignment properties of a StackPanel. When a user
selects a value in any of the ListBox elements, the associated property of the StackPanel
and its child Button elements change.
XAML
The following code-behind file defines the changes to the events that are associated
with the ListBox selection changes. StackPanel is identified by the Name sp1 .
C#
See also
StackPanel
ListBox
HorizontalAlignment
VerticalAlignment
Panels Overview
StatusBar
Article • 02/06/2023
In This Section
Reference
StatusBar
StatusBarItem
Related Sections
TabControl
Article • 02/06/2023
Typical TabControl
Reference
TabControl
TabItem
Related Sections
TextBlock
Article • 02/06/2023
The TextBlock control provides flexible text support for UI scenarios that do not require
more than one paragraph of text.
In This Section
TextBlock Overview
Reference
Label
Related Sections
Documents in WPF
The TextBlock control provides flexible text support for UI scenarios that do not require
more than one paragraph of text. It supports a number of properties that enable precise
control of presentation, such as FontFamily, FontSize, FontWeight, TextEffects, and
TextWrapping. Text content can be added using the Text property. When used in XAML,
content between the open and closing tag is implicitly added as the text of the element.
XAML
C#
See also
Label
TextBox
Article • 02/06/2023
The TextBox control provides support for basic text input in WPF applications.
In This Section
TextBox Overview
How-to Topics
Reference
TextBox
RichTextBox
TextBlock
PasswordBox
See also
WPF Controls Gallery Sample
TextBox Styles and Templates
TextBox Overview
Article • 02/06/2023
The TextBox class enables you to display or edit unformatted text. A common use of a
TextBox is editing unformatted text in a form. For example, a form asking for the user's
name, phone number, etc would use TextBox controls for text input. This topic
introduces the TextBox class and provides examples of how to use it in both Extensible
Application Markup Language (XAML) and C#.
TextBox or RichTextBox?
Both TextBox and RichTextBox allow users to input text but the two controls are used for
different scenarios. A TextBox requires less system resources then a RichTextBox so it is
ideal when only plain text needs to be edited (i.e., usage in a form). A RichTextBox is a
better choice when it is necessary for the user to edit formatted text, images, tables, or
other supported content. For example, editing a document, article, or blog that requires
formatting, images, etc is best accomplished using a RichTextBox. The table below
summarizes the primary features of TextBox and RichTextBox.
7 Note
Although TextBox does not support formatting related editing commands like
ToggleBold (Ctr+B), many basic commands are supported by both controls such as
MoveToLineEnd. See EditingCommands for more information.
Features supported by TextBox are covered in the sections below. For more information
about RichTextBox, see RichTextBox Overview.
Real-time Spellchecking
You can enable real-time spellchecking in a TextBox or RichTextBox. When spellchecking
is turned on, a red line appears underneath any misspelled words (see picture below).
See Enable Spell Checking in a Text Editing Control to learn how to enable spellchecking.
Context Menu
By default, both TextBox and RichTextBox have a context menu that appears when a user
right-clicks inside the control. The context menu allows the user to cut, copy, or paste
(see picture below).
You can create your own custom context menu to override the default behavior. See Use
a Custom Context Menu with a TextBox for more information.
Creating TextBoxes
A TextBox can be a single line in height or comprise multiple lines. A single line TextBox
is best for inputting small amounts of plain text (i.e. "Name", "Phone Number", etc. in a
form). The following example shows how to create a single line TextBox.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBox Width="200" MaxLength="100" />
</StackPanel>
</Page>
You can also create a TextBox that allows the user to enter multiple lines of text. For
example, if your form asked for a biographical sketch of the user, you would want to use
a TextBox that supports multiple lines of text. The following example shows how to use
Extensible Application Markup Language (XAML) to define a TextBox control that
automatically expands to accommodate multiple lines of text.
XAML
<TextBox
Name="tbMultiLine"
TextWrapping="Wrap"
AcceptsReturn="True"
VerticalScrollBarVisibility="Visible"
>
This TextBox will allow the user to enter multiple lines of text. When
the RETURN key is pressed,
or when typed text reaches the edge of the text box, a new line is
automatically inserted.
</TextBox>
Setting the TextWrapping attribute to Wrap causes text to wrap to a new line when the
edge of the TextBox control is reached, automatically expanding the TextBox control to
include room for a new line, if necessary.
Setting the AcceptsReturn attribute to true causes a new line to be inserted when the
RETURN key is pressed, once again automatically expanding the TextBox to include
room for a new line, if necessary.
The VerticalScrollBarVisibility attribute adds a scroll bar to the TextBox, so that the
contents of the TextBox can be scrolled through if the TextBox expands beyond the size
of the frame or window that encloses it.
For more information on different tasks associated with using a TextBox, see How-to
Topics.
See also
How-to Topics
RichTextBox Overview
TextBox How-to Topics
Article • 02/06/2023
This section provides examples that demonstrate how to accomplish common tasks
using the TextBox control.
In This Section
Create a Multiline TextBox Control
Detect When Text in a TextBox Has Changed
Enable Tab Characters in a TextBox Control
Get a Collection of Lines from a TextBox
Make a TextBox Control Read-Only
Position the Cursor at the Beginning or End of Text in a TextBox Control
Retrieve a Text Selection
Set Focus in a TextBox Control
Set the Text Content of a TextBox Control
Enable Spell Checking in a Text Editing Control
Use a Custom Context Menu with a TextBox
Use Spell Checking with a Context Menu
Add a Watermark to a TextBox
Reference
TextBox
RichTextBox
TextBlock
PasswordBox
See also
WPF Controls Gallery Sample
TextBox Styles and Templates
How to: Create a Multiline TextBox
Control
Article • 02/06/2023
This example shows how to use Extensible Application Markup Language (XAML) to
define a TextBox control that will automatically expand to accommodate multiple lines
of text.
Example
Setting the TextWrapping attribute to Wrap will cause entered text to wrap to a new line
when the edge of the TextBox control is reached, automatically expanding the TextBox
control to include room for a new line, if necessary.
Setting the AcceptsReturn attribute to true causes a new line to be inserted when the
RETURN key is pressed, once again automatically expanding the TextBox to include
room for a new line, if necessary.
The VerticalScrollBarVisibility attribute adds a scroll bar to the TextBox, so that the
contents of the TextBox can be scrolled through if the TextBox expands beyond the size
of the frame or window that encloses it.
XAML
<TextBox
Name="tbMultiLine"
TextWrapping="Wrap"
AcceptsReturn="True"
VerticalScrollBarVisibility="Visible"
>
This TextBox will allow the user to enter multiple lines of text. When
the RETURN key is pressed,
or when typed text reaches the edge of the text box, a new line is
automatically inserted.
</TextBox>
See also
TextWrapping
TextBox Overview
RichTextBox Overview
How to: Detect When Text in a TextBox
Has Changed
Article • 03/17/2022
This example shows one way to use the TextChanged event to execute a method
whenever the text in a TextBox control has changed.
In the code-behind class for the XAML that contains the TextBox control that you want
to monitor for changes, insert a method to call whenever the TextChanged event fires.
This method must have a signature that matches what is expected by the
TextChangedEventHandler delegate.
The event handler is called whenever the contents of the TextBox control are changed,
either by a user or programmatically.
7 Note
This event fires when the TextBox control is created and initially populated with
text.
XAML
<TextBox TextChanged="textChangedEventHandler">
Here is the initial text in my TextBox. Each time the contents of this
TextBox are changed,
the TextChanged event fires and textChangedEventHandler is called.
</TextBox>
C#
The event handler is called whenever the contents of the TextBox control are changed,
either by a user or programmatically.
7 Note
This event fires when the TextBox control is created and initially populated with
text.
Comments
See also
TextChangedEventArgs
TextBox Overview
RichTextBox Overview
How to: Enable Tab Characters in a
TextBox Control
Article • 02/06/2023
This example shows how to enable the acceptance of tab characters as normal input in a
TextBox control.
Example
To enable the acceptance of tab characters as input in a TextBox control, set the
AcceptsTab attribute to true.
XAML
<TextBox AcceptsTab="True">
If the AcceptsTab element is "True", the TextBox control will accept tab
characters as regular input when the TAB key is pressed.
If AcceptsTab is "False" (the default), pressing TAB moves the focus to
the next focusable control.
</TextBox>
See also
TextBox Overview
RichTextBox Overview
How to: Get a Collection of Lines from a
TextBox
Article • 02/06/2023
This example shows how to get a collection of lines of text from a TextBox.
Example
The following example shows a simple method that takes a TextBox as the argument,
and returns a StringCollection containing the lines of text in the TextBox. The LineCount
property is used to determine how many lines are currently in the TextBox, and the
GetLineText method is then used to extract each line and add it to the collection of lines.
C#
return lines;
}
See also
TextBox Overview
RichTextBox Overview
How to: Make a TextBox Control Read-
Only
Article • 02/06/2023
This example shows how to configure a TextBox control to not allow user input or
modification.
Example
To prevent users from modifying the contents of a TextBox control, set the IsReadOnly
attribute to true.
XAML
<TextBox
IsReadOnly="True"
>
The user may not modify the contents of this TextBox.
</TextBox>
The IsReadOnly attribute affects user input only; it does not affect text set in the
Extensible Application Markup Language (XAML) description of a TextBox control, or text
set programmatically through the Text property.
See also
TextBox Overview
RichTextBox Overview
How to: Position the Cursor at the
Beginning or End of Text in a TextBox
Control
Article • 02/06/2023
This example shows how to position the cursor at the beginning or end of the text
contents of a TextBox control.
XAML
<TextBox
Name="tbPositionCursor"
>
Here is some text in my text box...
</TextBox>
C#
tbPositionCursor.Select(0, 0);
C#
tbPositionCursor.Select(tbPositionCursor.Text.Length, 0);
See also
TextBox Overview
RichTextBox Overview
How to: Retrieve a Text Selection
Article • 02/06/2023
This example shows one way to use the SelectedText property to retrieve text that the
user has selected in a TextBox control.
In this example, a button with an associated Click event handler is used to retrieve the
text selection. When the user clicks the button, the OnClick method copies any selected
text in the textbox into a string. The particular circumstances by which the text selection
is retrieved (clicking a button), as well as the action taken with that selection (copying
the text selection to a string), can easily be modified to accommodate a wide variety of
scenarios.
XAML
<TextBox Name="tbSelectSomeText">
Some text to select...
</TextBox>
C#
See also
TextBox Overview
RichTextBox Overview
How to: Set Focus in a TextBox Control
Article • 02/06/2023
This example shows how to use the Focus method to set focus on a TextBox control.
XAML
<TextBox Name="tbFocusMe">
This is the text in my text box.
</TextBox>
C#
tbFocusMe.Focus();
See also
Focusable
IsFocused
TextBox Overview
RichTextBox Overview
How to: Set the Text Content of a
TextBox Control
Article • 03/17/2022
This example shows how to use the Text property to set the initial text contents of a
TextBox control.
7 Note
<TextBox Name="tbSettingText">
Initial text contents of the TextBox.
</TextBox>
See also
TextBox Overview
RichTextBox Overview
How to: Enable Spell Checking in a Text
Editing Control
Article • 02/06/2023
The following example shows how to enable real-time spell checking in a TextBox by
using the IsEnabled property of the SpellCheck class.
Example
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBox SpellCheck.IsEnabled="True" Name="myTextBox"></TextBox>
</StackPanel>
</Page>
C#
using System;
using System.Windows;
using System.Windows.Controls;
namespace SDKSample
{
public partial class SpellCheckExample : Page
{
public SpellCheckExample()
{
StackPanel myStackPanel = new StackPanel();
//Create TextBox
TextBox myTextBox = new TextBox();
myTextBox.Width = 200;
myStackPanel.Children.Add(myTextBox);
this.Content = myStackPanel;
}
}
}
See also
Use Spell Checking with a Context Menu
TextBox Overview
RichTextBox Overview
How to: Use a Custom Context Menu
with a TextBox
Article • 02/06/2023
This example shows how to define and implement a simple custom context menu for a
TextBox.
The context menu is defined using a ContextMenu element. The context menu itself
consists of a series of MenuItem elements and Separator elements. Each MenuItem
element defines a command in the context menu; the Header attribute defines the
display text for the menu command, and the Click attribute specifies a handler method
for each menu item. The Separator element simply causes a separating line to be
rendered between the previous and subsequent menu items.
XAML
<TextBox
Name="cxmTextBox"
Grid.Row="1"
AcceptsReturn="True"
AcceptsTab="True"
VerticalScrollBarVisibility="Visible"
TextWrapping="Wrap"
>
<TextBox.ContextMenu>
<ContextMenu
Name="cxm"
Opened="CxmOpened"
>
<MenuItem
Header="Cut"
Name="cxmItemCut"
Click="ClickCut"
/>
<MenuItem
Header="Copy"
Name="cxmItemCopy"
Click="ClickCopy"
/>
<MenuItem
Header="Paste"
Name="cxmItemPaste"
Click="ClickPaste"
/>
<Separator/>
<MenuItem
Header="Select All"
Name="cxmItemSelectAll"
Click="ClickSelectAll"
/>
<MenuItem
Header="Select Current Line"
Name="cxmItemSelectLine"
Click="ClickSelectLine"
/>
<Separator/>
<MenuItem
Header="Undo Last Action"
Name="cxmItemUndo"
Click="ClickUndo"
/>
<MenuItem
Header="Redo Last Action"
Name="cxmItemRedo"
Click="ClickRedo"
/>
<Separator/>
<MenuItem
Header="Clear All Text"
Name="cxmItemClear"
Click="ClickClear"
/>
</ContextMenu>
</TextBox.ContextMenu>
This TextBox uses a simple custom context menu. The context menu can be
disabled by checking
the CheckBox above, which simply sets the TextBox.ContextMenu property to
null.
</TextBox>
To restore the default context menu, use the ClearValue method to clear the value of the
ContextMenu property. To disable the context menu altogether, set the ContextMenu
property to a null reference ( Nothing in Visual Basic).
C#
switch (rb.Name)
{
case "rbCustom":
cxmTextBox.ContextMenu = cxm;
break;
case "rbDefault":
// Clearing the value of the ContextMenu property
// restores the default TextBox context menu.
cxmTextBox.ClearValue(ContextMenuProperty);
break;
case "rbDisabled":
// Setting the ContextMenu propety to
// null disables the context menu.
cxmTextBox.ContextMenu = null;
break;
default:
break;
}
}
See also
Use Spell Checking with a Context Menu
TextBox Overview
RichTextBox Overview
How to: Use Spell Checking with a
Context Menu
Article • 02/06/2023
By default, when you enable spell checking in an editing control like TextBox or
RichTextBox, you get spell-checking choices in the context menu. For example, when
users right-click a misspelled word, they get a set of spelling suggestions or the option
to Ignore All. However, when you override the default context menu with your own
custom context menu, this functionality is lost, and you need to write code to reenable
the spell-checking feature in the context menu. The following example shows how to
enable this on a TextBox.
XAML
<Page x:Class="SDKSample.SpellerCustomContextMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="OnWindowLoaded">
<TextBox
Name="myTextBox"
TextWrapping="Wrap"
SpellCheck.IsEnabled="True"
ContextMenuOpening="tb_ContextMenuOpening">
In a custum menu you need to write code to add speler choices
because everything in a custom context menu has to be added explicitly.
</TextBox>
</Page>
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace SDKSample
{
public partial class SpellerCustomContextMenu : Page
{
myTextBox.ContextMenu = GetContextMenu();
caretIndex = myTextBox.CaretIndex;
cmdIndex = 0;
spellingError = myTextBox.GetSpellingError(caretIndex);
if (spellingError != null)
{
foreach (string str in spellingError.Suggestions)
{
MenuItem mi = new MenuItem();
mi.Header = str;
mi.FontWeight = FontWeights.Bold;
mi.Command = EditingCommands.CorrectSpellingError;
mi.CommandParameter = str;
mi.CommandTarget = myTextBox;
myTextBox.ContextMenu.Items.Insert(cmdIndex, mi);
cmdIndex++;
}
Separator separatorMenuItem1 = new Separator();
myTextBox.ContextMenu.Items.Insert(cmdIndex,
separatorMenuItem1);
cmdIndex++;
MenuItem ignoreAllMI = new MenuItem();
ignoreAllMI.Header = "Ignore All";
ignoreAllMI.Command = EditingCommands.IgnoreSpellingError;
ignoreAllMI.CommandTarget = myTextBox;
myTextBox.ContextMenu.Items.Insert(cmdIndex, ignoreAllMI);
cmdIndex++;
Separator separatorMenuItem2 = new Separator();
myTextBox.ContextMenu.Items.Insert(cmdIndex,
separatorMenuItem2);
}
}
cm.Items.Add(m1);
cm.Items.Add(m2);
cm.Items.Add(m3);
cm.Items.Add(m4);
return cm;
}
}
}
The code used for doing this with a RichTextBox is similar. The main difference is in the
parameter passed to the GetSpellingError method. For a TextBox, pass the integer
index of the caret position:
spellingError = myTextBox.GetSpellingError(caretIndex);
For a RichTextBox, pass the TextPointer that specifies the caret position:
spellingError = myRichTextBox.GetSpellingError(myRichTextBox.CaretPosition);
See also
TextBox Overview
RichTextBox Overview
Enable Spell Checking in a Text Editing Control
Use a Custom Context Menu with a TextBox
How to: Add a Watermark to a TextBox
Article • 06/02/2023
7 Note
The reason a background image is used in this example rather then simply
manipulating the Text property of TextBox, is that a background image will not
interfere with data binding.
Example
The following XAML demonstrates the following:
XAML
<Window x:Class="watermark.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ImageBrush x:Key="watermark" ImageSource="textboxbackground.gif"
AlignmentX="Left" Stretch="None" />
</Window.Resources>
<StackPanel>
<TextBox Name="myTextBox" TextChanged="OnTextBoxTextChanged"
Width="200" Background="{StaticResource watermark}" />
</StackPanel>
</Window>
The following code handles the TextBox.TextChanged event:
C#
See also
TextBox Overview
RichTextBox Overview
ToolBar
Article • 02/06/2023
The ToolBar control is a container for a group of commands or controls that are typically
related in their function.
Horizontal Toolbar
Vertical Toolbar
In This Section
ToolBar Overview
Style Controls on a ToolBar
Reference
ToolBar
ToolBarTray
Related Sections
ToolBar Overview
Article • 02/06/2023
ToolBar controls are containers for a group of commands or controls which are typically
related in their function. A ToolBar usually contains buttons which invoke commands.
ToolBar Control
The ToolBar control takes its name from the bar-like arrangement of buttons or other
controls into a single row or column. WPF ToolBar controls provide an overflow
mechanism which places any items that do not fit naturally within a size-constrained
ToolBar into a special overflow area. Also, WPF ToolBar controls are usually used with the
related ToolBarTray control, which provides special layout behavior as well as support for
user-initiated sizing and arranging of toolbars.
XAML
<ToolBarTray Background="White">
<ToolBar Band="1" BandIndex="1">
<Button>
<Image Source="toolbargraphics\cut.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\copy.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\paste.bmp" />
</Button>
</ToolBar>
<ToolBar Band="2" BandIndex="1">
<Button>
<Image Source="toolbargraphics\undo.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\redo.bmp" />
</Button>
</ToolBar>
<ToolBar Band="2" BandIndex="2">
<Button>
<Image Source="toolbargraphics\paint.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\spell.bmp" />
</Button>
<Separator/>
<Button>
<Image Source="toolbargraphics\save.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\open.bmp" />
</Button>
</ToolBar>
</ToolBarTray>
You can specify when an item on a toolbar is placed on the overflow panel by setting
the ToolBar.OverflowMode attached property to OverflowMode.Always,
OverflowMode.Never, or OverflowMode.AsNeeded. The following example specifies that
the last four buttons on the toolbar should always be on the overflow panel.
XAML
<ToolBarTray Background="White">
<ToolBar Band="1" BandIndex="1">
<Button>
<Image Source="toolbargraphics\cut.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\copy.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\paste.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\undo.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\redo.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\paint.bmp" />
</Button>
<Button>
<Image Source="toolbargraphics\spell.bmp" />
</Button>
<Separator/>
<Button ToolBar.OverflowMode="Always">
<Image Source="toolbargraphics\save.bmp" />
</Button>
<Button ToolBar.OverflowMode="Always">
<Image Source="toolbargraphics\open.bmp" />
</Button>
<Button ToolBar.OverflowMode="Always">
<Image Source="toolbargraphics\print.bmp" />
</Button>
<Button ToolBar.OverflowMode="Always">
<Image Source="toolbargraphics\preview.bmp" />
</Button>
</ToolBar>
</ToolBarTray>
See also
ToolBarPanel
ToolBarOverflowPanel
Style Controls on a ToolBar
WPF Controls Gallery Sample
How to: Style Controls on a ToolBar
Article • 02/06/2023
The ToolBar defines ResourceKey objects to specify the style of controls within the
ToolBar. To style a control in a ToolBar, set the x:key attribute of the style to a
ResourceKey defined in ToolBar.
ButtonStyleKey
CheckBoxStyleKey
ComboBoxStyleKey
MenuStyleKey
RadioButtonStyleKey
SeparatorStyleKey
TextBoxStyleKey
ToggleButtonStyleKey
Example
The following example defines styles for the controls within a ToolBar.
XAML
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Foreground" Value="DarkSlateBlue"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="Menu">
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="LightSteelBlue"/>
</Style>
<Style TargetType="RadioButton">
<Setter Property="Background" Value="LightSteelBlue"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="Background" Value="DarkBlue"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Width" Value="75"/>
</Style>
<Style TargetType="ComboBox">
<Setter Property="Background" Value="LightSteelBlue"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="MinWidth" Value="60"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</Window.Resources>
XAML
<ToolBarTray Margin="10,10,3,3"
Grid.Column="0" Grid.Row="2"
Background="LightBlue">
<ToolBar >
<Button Content="Button 1"/>
<Button Content="Button 2"/>
<Separator/>
<CheckBox Content="CheckBox 1"/>
<CheckBox Content="CheckBox 2"/>
<Separator/>
<RadioButton>One</RadioButton>
<RadioButton>Two</RadioButton>
<Separator/>
<ComboBox>
<ComboBoxItem IsSelected="True">Item 1</ComboBoxItem>
<ComboBoxItem>Item 2</ComboBoxItem>
<ComboBoxItem>Item 3</ComboBoxItem>
<ComboBoxItem>Item 4</ComboBoxItem>
</ComboBox>
<TextBox/>
<Separator/>
<Menu>
<MenuItem Header="Menu">
<MenuItem Header="File">
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</MenuItem>
</MenuItem>
</Menu>
</ToolBar>
</ToolBarTray>
See also
Styling and Templating
ToolTip
Article • 02/06/2023
A tooltip is a small pop-up window that appears when a user pauses the mouse pointer
over an element, such as over a Button.
The following illustration shows a mouse pointer that points to the CloseButton, which
then displays its identifying ToolTip.
In This Section
ToolTip Overview
How-to Topics
Reference
ToolTip
ToolTipService
Popup
Related Sections
Popup Overview
How-to Topics
ToolTip Overview
Article • 08/18/2022
A tooltip is a small pop-up window that appears when a user pauses the mouse pointer
over an element, such as over a Button. This topic introduces the tooltip and discusses
how to create and customize tooltip content.
What Is a Tooltip
When a user moves the mouse pointer over an element that has a tooltip, a window that
contains tooltip content (for example, text content that describes the function of a
control) appears for a specified amount of time. If the user moves the mouse pointer
away from the control, the window disappears because the tooltip content cannot
receive focus.
The content of a tooltip can contain one or more lines of text, images, shapes, or other
visual content. You define a tooltip for a control by setting one of the following
properties to the tooltip content.
FrameworkContentElement.ToolTip
FrameworkElement.ToolTip
Which property you use depends on whether the control that defines the tooltip inherits
from the FrameworkContentElement or FrameworkElement class.
Creating a ToolTip
The following example shows how to create a simple tooltip by setting the ToolTip
property for a Button control to a text string.
XAML
You can also define a tooltip as a ToolTip object. The following example uses XAML to
specify a ToolTip object as the tooltip of a TextBox element. Note that the example
specifies the ToolTip by setting the FrameworkElement.ToolTip property.
XAML
<TextBox HorizontalAlignment="Left">ToolTip with non-text content
<TextBox.ToolTip>
<ToolTip>
<DockPanel Width="50" Height="70">
<Image Source="data\flower.jpg"/>
<TextBlock>Useful information goes here.</TextBlock>
</DockPanel>
</ToolTip>
</TextBox.ToolTip>
</TextBox>
The following example uses code to generate a ToolTip object. The example creates a
ToolTip ( tt ) and associates it with a Button.
C#
You can also create tooltip content that is not defined as a ToolTip object by enclosing
the tooltip content in a layout element, such as a DockPanel. The following example
shows how to set the ToolTip property of a TextBox to content that is enclosed in a
DockPanel control.
XAML
<TextBox>
ToolTip with image and text
<TextBox.ToolTip>
<StackPanel>
<Image Source="data\flower.jpg"/>
<TextBlock>Useful information goes here.</TextBlock>
</StackPanel>
</TextBox.ToolTip>
For an example of how to set properties in order to specify the position of tooltip
content by using the ToolTip and ToolTipService properties, see Position a ToolTip.
Styling a ToolTip
You can style a ToolTip by defining a custom Style. The following example defines a Style
called Simple that shows how to offset the placement of the ToolTip and change its
appearance by setting the Background, Foreground, FontSize, and FontWeight.
XAML
<Style TargetType="ToolTip">
<Setter Property = "HorizontalOffset" Value="10"/>
<Setter Property = "VerticalOffset" Value="10"/>
<Setter Property = "Background" Value="LightBlue"/>
<Setter Property = "Foreground" Value="Purple"/>
<Setter Property = "FontSize" Value="14"/>
<Setter Property = "FontWeight" Value="Bold"/>
</Style>
Use the InitialShowDelay and ShowDuration properties to specify a delay, typically brief,
before a ToolTip appears and also to specify how long a ToolTip remains visible. For
more information, see How to: Delay the Display of a ToolTip.
The following example shows how to set these properties for a tooltip.
XAML
See also
ToolTipService
ToolTip
ToolTipEventArgs
ToolTipEventHandler
How-to Topics
ToolTip How-to Topics
Article • 02/06/2023
In This Section
Position a ToolTip
Use the BetweenShowDelay Property
Reference
ToolTip
ToolTipService
Popup
Related Sections
Popup Overview
How-to Topics
How to: Position a ToolTip
Article • 02/06/2023
This example shows how to specify the position of a tooltip on the screen.
Example
You can position a tooltip by using a set of five properties that are defined in both the
ToolTip and ToolTipService classes. The following table shows these two sets of five
properties and provides links to their reference documentation according to class.
ToolTip.Placement ToolTipService.Placement
ToolTip.PlacementTarget ToolTipService.PlacementTarget
ToolTip.PlacementRectangle ToolTipService.PlacementRectangle
ToolTip.HorizontalOffset ToolTipService.HorizontalOffset
ToolTip.VerticalOffset ToolTipService.VerticalOffset
If you define the contents of a tooltip by using a ToolTip object, you can use the
properties of either class; however, the ToolTipService properties take precedence. Use
the ToolTipService properties for tooltips that are not defined as ToolTip objects.
The following illustrations show how to position a tooltip by using these properties.
Although, the Extensible Application Markup Language (XAML) examples in these
illustrations show how to set the properties that are defined by the ToolTip class, the
corresponding properties of the ToolTipService class follow the same layout rules. For
more information about the possible values for the Placement property, see Popup
Placement Behavior.
The following image shows tooltip placement by using the Placement property:
The following image shows tooltip placement by using the Placement and
PlacementRectangle properties:
The following example shows how to use the ToolTip properties to specify the position
of a tooltip whose content is a ToolTip object.
XAML
C#
The following example shows how to use the ToolTipService properties to specify the
position of a tooltip whose content is not a ToolTip object.
XAML
C#
ToolTipService.SetPlacement(ellipse2, PlacementMode.Right);
ToolTipService.SetPlacementRectangle(ellipse2,
new Rect(50, 0, 0, 0));
ToolTipService.SetHorizontalOffset(ellipse2, 10.0);
ToolTipService.SetVerticalOffset(ellipse2, 20.0);
ToolTipService.SetHasDropShadow(ellipse2, false);
ToolTipService.SetIsEnabled(ellipse2, true);
ToolTipService.SetShowOnDisabled(ellipse2, true);
ellipse2.AddHandler(ToolTipService.ToolTipOpeningEvent,
new RoutedEventHandler(whenToolTipOpens));
ellipse2.AddHandler(ToolTipService.ToolTipClosingEvent,
new RoutedEventHandler(whenToolTipCloses));
See also
ToolTip
ToolTipService
How-to Topics
ToolTip Overview
How to: Use the BetweenShowDelay
Property
Article • 02/06/2023
This example shows how to use the BetweenShowDelay time property so that tooltips
appear quickly—with little or no delay—when a user moves the mouse pointer from one
tooltip directly to another.
Example
In the following example, the InitialShowDelay property is set to one second (1000
milliseconds) and the BetweenShowDelay is set to two seconds (2000 milliseconds) for
the tooltips of both Ellipse controls. If you display the tooltip for one of the ellipses and
then move the mouse pointer to another ellipse within two seconds and pause on it, the
tooltip of the second ellipse displays immediately.
In either of the following scenarios, the InitialShowDelay applies, which causes the
tooltip for the second ellipse to wait one second before it appears:
If the time it takes to move to the second button is more than two seconds.
If the tooltip is not visible at the beginning of the time interval for the first ellipse.
XAML
XAML
See also
ToolTip
ToolTipService
How-to Topics
ToolTip Overview
TreeView
Article • 02/06/2023
In This Section
TreeView Overview
How-to Topics
Reference
TreeView
TreeViewItem
Related Sections
Data Binding Overview
Data Templating Overview
TreeView Overview
Article • 02/06/2023
What Is a TreeView?
TreeView is an ItemsControl that nests the items by using TreeViewItem controls. The
following example creates a TreeView.
XAML
Creating a TreeView
The TreeView control contains a hierarchy of TreeViewItem controls. A TreeViewItem
control is a HeaderedItemsControl that has a Header and an Items collection.
If you are defining a TreeView by using Extensible Application Markup Language (XAML),
you can explicitly define the Header content of a TreeViewItem control and the items
that make up its collection. The previous illustration demonstrates this method.
You can also specify an ItemsSource as a data source and then specify a HeaderTemplate
and ItemTemplate to define the TreeViewItem content.
TreeViewItem Selection
When a user clicks a TreeViewItem control to select it, the Selected event occurs, and its
IsSelected property is set to true . The TreeViewItem also becomes the SelectedItem of
the TreeView control. Conversely, when the selection changes from a TreeViewItem
control, its Unselected event occurs and its IsSelected property is set to false .
The SelectedItem property on the TreeView control is a read-only property; hence, you
cannot explicitly set it. The SelectedItem property is set if the user clicks on a
TreeViewItem control or when the IsSelected property is set to true on the
TreeViewItem control.
TreeView Style
The default style for a TreeView control places it inside a StackPanel object that contains
a ScrollViewer control. When you set the Width and Height properties for a TreeView,
these values are used to size the StackPanel object that displays the TreeView. If the
content to display is larger than the display area, a ScrollViewer automatically displays
so that the user can scroll through the TreeView content.
The following example shows how to set the Foreground and FontSize property values
for a TreeViewItem control by using a Style.
XAML
XAML
<TreeViewItem>
<TreeViewItem.Header>
<DockPanel>
<CheckBox/>
<TextBlock>
TreeViewItem Text
</TextBlock>
</DockPanel>
</TreeViewItem.Header>
</TreeViewItem>
The following example shows how to define a DataTemplate that contains an Image and
a TextBlock that are enclosed in a DockPanel control. You can use a DataTemplate to set
the HeaderTemplate or ItemTemplate for a TreeViewItem.
XAML
<DataTemplate x:Key="NewspaperTVItem">
<DockPanel>
<Image Source="images\icon.jpg"/>
<TextBlock VerticalAlignment="center" Text ="{Binding Path=Name}"/>
</DockPanel>
</DataTemplate>
See also
TreeView
TreeViewItem
How-to Topics
WPF Content Model
TreeView How-to Topics
Article • 02/06/2023
The topics in this section describe how to use the TreeView control to display
information in a hierarchical structure.
In This Section
Create Simple or Complex TreeViews
Use SelectedValue, SelectedValuePath, and SelectedItem
Bind a TreeView to Data That Has an Indeterminable Depth
Improve the Performance of a TreeView
Find a TreeViewItem in a TreeView
Reference
TreeView
TreeViewItem
Related Sections
How to: Create Simple or Complex
TreeViews
Article • 02/06/2023
Example
The Header property of the TreeViewItem contains the content that the TreeView
displays for that item. A TreeViewItem can also have TreeViewItem controls as its child
elements and you can define these child elements by using the Items property.
The following example shows how to explicitly define TreeViewItem content by setting
the Header property to a text string.
XAML
<TreeView>
<TreeViewItem Header="Employee1">
<TreeViewItem Header="Jesper"/>
<TreeViewItem Header="Aaberg"/>
<TreeViewItem Header="12345"/>
</TreeViewItem>
<TreeViewItem Header="Employee2">
<TreeViewItem Header="Dominik"/>
<TreeViewItem Header="Paiha"/>
<TreeViewItem Header="98765"/>
</TreeViewItem>
</TreeView>
The following example show how to define child elements of a TreeViewItem by defining
Items that are Button controls.
XAML
<TreeView>
<TreeViewItem Header ="Employee1">
<TreeViewItem.Items>
<Button>Jesper</Button>
<Button>Aaberg</Button>
<Button>12345</Button>
</TreeViewItem.Items>
</TreeViewItem>
<TreeViewItem Header="Employee2">
<TreeViewItem.Items>
<Button>Dominik</Button>
<Button>Paiha</Button>
<Button>98765</Button>
</TreeViewItem.Items>
</TreeViewItem>
</TreeView>
XAML
XAML
<HierarchicalDataTemplate DataType="EmployeeInfo"
ItemsSource ="{Binding XPath=Item}">
<TextBlock Text="{Binding XPath=EmployeeInfoData}" />
</HierarchicalDataTemplate>
XAML
XAML
<TreeView>
<TreeViewItem Header="Animals">
<TreeViewItem.Items>
<DockPanel>
<Image Source="data\fish.png"/>
<TextBlock Margin="5" Foreground="Brown"
FontSize="12">Fish</TextBlock>
</DockPanel>
<DockPanel>
<Image Source="data\dog.png"/>
<TextBlock Margin="5" Foreground="Brown"
FontSize="12">Dog</TextBlock>
</DockPanel>
<DockPanel>
<Image Source="data\cat.png"/>
<TextBlock Margin="5" Foreground="Brown"
FontSize="12">Cat</TextBlock>
</DockPanel>
</TreeViewItem.Items>
</TreeViewItem>
</TreeView>
See also
TreeView
TreeViewItem
TreeView Overview
How-to Topics
How to: Use SelectedValue,
SelectedValuePath, and SelectedItem
Article • 02/06/2023
This example shows how to use the SelectedValue and SelectedValuePath properties to
specify a value for the SelectedItem of a TreeView.
Example
The SelectedValuePath property provides a way to specify a SelectedValue for the
SelectedItem in a TreeView. The SelectedItem represents an object in the Items
collection and the TreeView displays the value of a single property of the selected item.
The SelectedValuePath property specifies the path to the property that is used to
determine the value of the SelectedValue property. The examples in this topic illustrate
this concept.
XAML
XAML
The following example shows a TreeView that uses the previously defined
HierarchicalDataTemplate and that sets the SelectedValue property to the
EmployeeNumber . When you select an EmployeeName in the TreeView, the SelectedItem
property returns the EmployeeInfo data item that corresponds to the selected
EmployeeName . However, because the SelectedValuePath of this TreeView is set to
XAML
See also
TreeView
TreeViewItem
TreeView Overview
How-to Topics
How to: Bind a TreeView to Data That
Has an Indeterminable Depth
Article • 02/06/2023
There might be times when you want to bind a TreeView to a data source whose depth
is not known. This can occur when the data is recursive in nature, such as a file system,
where folders can contain folders, or a company's organizational structure, where
employees have other employees as direct reports.
The data source must have a hierarchical object model. For example, an Employee class
might contain a collection of Employee objects that are the direct reports of an
employee. If the data is represented in a way that is not hierarchical, you must build a
hierarchical representation of the data.
Example
The following example demonstrates how to bind a TreeView to hierarchical data and
use a HierarchicalDataTemplate to specify the ItemsSource for each TreeViewItem. The
TreeView binds to XML data that represents the employees in a company. Each Employee
element can contain other Employee elements to indicate who reports to whom. Because
the data is recursive, the HierarchicalDataTemplate can be applied to each level.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<XmlDataProvider x:Key="myCompany" XPath="Company/Employee">
<x:XData>
<Company xmlns="">
<Employee Name="Don Hall">
<Employee Name="Alice Ciccu">
<Employee Name="David Pelton">
<Employee Name="Vivian Atlas"/>
</Employee>
<Employee Name="Jeff Price"/>
<Employee Name="Andy Jacobs"/>
</Employee>
<Employee Name="Bill Malone">
<Employee Name="Maurice Taylor"/>
<Employee Name="Sunil Uppal"/>
<Employee Name="Qiang Wang"/>
</Employee>
</Employee>
</Company>
</x:XData>
</XmlDataProvider>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</Page.Resources>
<Grid>
<TreeView ItemsSource="{Binding Source={StaticResource myCompany}}"
ItemTemplate="{StaticResource EmployeeTemplate}"/>
</Grid>
</Page>
See also
Data Binding Overview
Data Templating Overview
How to: Improve the Performance of a
TreeView
Article • 02/06/2023
If a TreeView contains many items, the amount of time it takes to load may cause a
significant delay in the user interface. You can improve the load time by setting the
VirtualizingStackPanel.IsVirtualizing attached property to true . The UI might also
be slow to react when a user scrolls the TreeView by using the mouse wheel or dragging
the thumb of a scrollbar. You can improve the performance of the TreeView when the
user scrolls by setting the VirtualizingStackPanel.VirtualizationMode attached
property to VirtualizationMode.Recycling.
Example
Description
The following example creates a TreeView that sets the
VirtualizingStackPanel.IsVirtualizing attached property to true and the
VirtualizingStackPanel.VirtualizationMode attached property to
Code
XAML
<StackPanel>
<StackPanel.Resources>
<src:TreeViewData x:Key="dataItems"/>
<TreeView Height="200"
ItemsSource="{Binding Source={StaticResource dataItems}}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<TreeView.ItemContainerStyle>
The following example shows the data that the previous example uses.
C#
public TreeViewData()
{
for (int i = 0; i < 100; ++i)
{
ItemsForTreeView item = new ItemsForTreeView();
item.TopLevelName = "item " + i.ToString();
Add(item);
}
}
}
public ItemsForTreeView()
{
for (int i = 0; i < 10; ++i)
{
SecondLevelItems.Add("Second Level " + i.ToString());
}
}
}
See also
Controls
How to: Find a TreeViewItem in a
TreeView
Article • 02/06/2023
The TreeView control provides a convenient way to display hierarchical data. If your
TreeView is bound to a data source, the SelectedItem property provides a convenient
way for you to quickly retrieve the selected data object. It is typically best to work with
the underlying data object, but sometimes you may need to programmatically
manipulate the data's containing TreeViewItem. For example, you may need to
programmatically expand the TreeViewItem, or select a different item in the TreeView.
To find a TreeViewItem that contains a specific data object, you must traverse each level
of the TreeView. The items in a TreeView can also be virtualized to improve performance.
In the case where items might be virtualized, you also must realize a TreeViewItem to
check whether it contains the data object.
Example
Description
The following example searches a TreeView for a specific object and returns the object's
containing TreeViewItem. The example ensures that each TreeViewItem is instantiated so
that its child items can be searched. This example also works if the TreeView does not
use virtualized items.
7 Note
The following example works for any TreeView, regardless of the underlying data
model, and searches every TreeViewItem until the object is found. Another
technique that has better performance is to search the data model for the specified
object, keep track of its location within the data hierarchy, and then find the
corresponding TreeViewItem in the TreeView. However, the technique that has
better performance requires knowledge of the data model and cannot be
generalized for any given TreeView.
Code
C#
/// <summary>
/// Recursively search for an item in this subtree.
/// </summary>
/// <param name="container">
/// The parent ItemsControl. This can be a TreeView or a TreeViewItem.
/// </param>
/// <param name="item">
/// The item to search for.
/// </param>
/// <returns>
/// The TreeViewItem that contains the specified item.
/// </returns>
private TreeViewItem GetTreeViewItem(ItemsControl container, object item)
{
if (container != null)
{
if (container.DataContext == item)
{
return container as TreeViewItem;
}
container.ApplyTemplate();
ItemsPresenter itemsPresenter =
(ItemsPresenter)container.Template.FindName("ItemsHost",
container);
if (itemsPresenter != null)
{
itemsPresenter.ApplyTemplate();
}
else
{
// The Tree template has not named the ItemsPresenter,
// so walk the descendents and find the child.
itemsPresenter = FindVisualChild<ItemsPresenter>(container);
if (itemsPresenter == null)
{
container.UpdateLayout();
itemsPresenter = FindVisualChild<ItemsPresenter>(container);
}
}
Panel itemsHostPanel =
(Panel)VisualTreeHelper.GetChild(itemsPresenter, 0);
// Ensure that the generator for this panel has been created.
UIElementCollection children = itemsHostPanel.Children;
MyVirtualizingStackPanel virtualizingPanel =
itemsHostPanel as MyVirtualizingStackPanel;
subContainer =
(TreeViewItem)container.ItemContainerGenerator.
ContainerFromIndex(i);
}
else
{
subContainer =
(TreeViewItem)container.ItemContainerGenerator.
ContainerFromIndex(i);
if (subContainer != null)
{
// Search the next level for the object.
TreeViewItem resultContainer = GetTreeViewItem(subContainer,
item);
if (resultContainer != null)
{
return resultContainer;
}
else
{
// The object is not under this TreeViewItem
// so collapse it.
subContainer.IsExpanded = false;
}
}
}
}
return null;
}
/// <summary>
/// Search for an element of a certain type in the visual tree.
/// </summary>
/// <typeparam name="T">The type of element to find.</typeparam>
/// <param name="visual">The parent element.</param>
/// <returns></returns>
private T FindVisualChild<T>(Visual visual) where T : Visual
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
Visual child = (Visual)VisualTreeHelper.GetChild(visual, i);
if (child != null)
{
T correctlyTyped = child as T;
if (correctlyTyped != null)
{
return correctlyTyped;
}
T descendent = FindVisualChild<T>(child);
if (descendent != null)
{
return descendent;
}
}
}
return null;
}
C#
this.BringIndexIntoView(index);
}
}
The following XAML shows how to create a TreeView that uses the custom
VirtualizingStackPanel.
XAML
<TreeView VirtualizingStackPanel.IsVirtualizing="True">
See also
Improve the Performance of a TreeView
WrapPanel
Article • 02/06/2023
The WrapPanel element positions child elements in sequential position from left to right,
breaking content to the next line at the edge of its containing box.
Reference
Panel
Canvas
DockPanel
Grid
StackPanel
VirtualizingStackPanel
WrapPanel
Related Sections
Layout
ScrollViewer Overview
Viewbox
Article • 02/06/2023
In This Section
Apply Stretch Properties to the Contents of a Viewbox
Reference
Viewbox
Image
See also
WPF Controls Gallery Sample
How to: Apply Stretch Properties to the
Contents of a Viewbox
Article • 02/06/2023
Example
This example shows how to change the value of the StretchDirection and Stretch
properties of a Viewbox.
The first example uses Extensible Application Markup Language (XAML) to define a
Viewbox element. It assigns a MaxWidth and MaxHeight of 400. The example nests an
Image element within the Viewbox. Button elements that correspond to the property
values for the Stretch and StretchDirection enumerations manipulate the stretching
behavior of the nested Image.
XAML
The following code-behind file handles the Button Click events that the previous XAML
example defines.
C#
See also
Viewbox
Stretch
StretchDirection
Styles and Templates
Article • 02/06/2023
In This Section
Styling and Templating
How to: Find ControlTemplate-Generated Elements
Reference
Style
ControlTemplate
DataTemplate
Related Sections
Advanced
Control Customization
Graphics and Multimedia
Styles and templates in WPF
Article • 03/03/2023
Another feature of the WPF styling model is the separation of presentation and logic.
Designers can work on the appearance of an app by using only XAML at the same time
that developers work on the programming logic by using C# or Visual Basic.
This overview focuses on the styling and templating aspects of the app and doesn't
discuss any data-binding concepts. For information about data binding, see Data
Binding Overview.
It's important to understand resources, which are what enable styles and templates to
be reused. For more information about resources, see XAML Resources.
Sample
The sample code provided in this overview is based on a simple photo browsing
application shown in the following illustration.
This simple photo sample uses styling and templating to create a visually compelling
user experience. The sample has two TextBlock elements and a ListBox control that is
bound to a list of images.
For the complete sample, see Introduction to Styling and Templating Sample .
Styles
You can think of a Style as a convenient way to apply a set of property values to multiple
elements. You can use a style on any element that derives from FrameworkElement or
FrameworkContentElement such as a Window or a Button.
The most common way to declare a style is as a resource in the Resources section in a
XAML file. Because styles are resources, they obey the same scoping rules that apply to
all resources. Put simply, where you declare a style affects where the style can be
applied. For example, if you declare the style in the root element of your app definition
XAML file, the style can be used anywhere in your app.
For example, the following XAML code declares two styles for a TextBlock , one
automatically applied to all TextBlock elements, and another that must be explicitly
referenced.
XAML
<Window.Resources>
<!-- .... other resources .... -->
<!--A Style that extends the previous TextBlock Style with an x:Key of
TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="TitleText">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#90DDDD" />
<GradientStop Offset="1.0" Color="#5BFFFF" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
XAML
<StackPanel>
<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My
Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>
ControlTemplates
In WPF, the ControlTemplate of a control defines the appearance of the control. You can
change the structure and appearance of a control by defining a new ControlTemplate
and assigning it to a control. In many cases, templates give you enough flexibility so that
you do not have to write your own custom controls.
Each control has a default template assigned to the Control.Template property. The
template connects the visual presentation of the control with the control's capabilities.
Because you define a template in XAML, you can change the control's appearance
without writing any code. Each template is designed for a specific control, such as a
Button.
Control templates are a lot more involved than a style. This is because the control
template rewrites the visual appearance of the entire control, while a style simply applies
property changes to the existing control. However, since the template of a control is
applied by setting the Control.Template property, you can use a style to define or set a
template.
Designers generally allow you to create a copy of an existing template and modify it. For
example, in the Visual Studio WPF designer, select a CheckBox control, and then right-
click and select Edit template > Create a copy. This command generates a style that
defines a template.
XAML
Editing a copy of a template is a great way to learn how templates work. Instead of
creating a new blank template, it's easier to edit a copy and change a few aspects of the
visual presentation.
DataTemplates
In this sample app, there is a ListBox control that is bound to a list of photos.
XAML
Most controls have some type of content, and that content often comes from data that
you are binding to. In this sample, the data is the list of photos. In WPF, you use a
DataTemplate to define the visual representation of data. Basically, what you put into a
DataTemplate determines what the data looks like in the rendered app.
In our sample app, each custom Photo object has a Source property of type string that
specifies the file path of the image. Currently, the photo objects appear as file paths.
C#
XAML
<Window.Resources>
<!-- .... other resources .... -->
Notice that the DataType property is similar to the TargetType property of the Style. If
your DataTemplate is in the resources section, when you specify the DataType property
to a type and omit an x:Key , the DataTemplate is applied whenever that type appears.
You always have the option to assign the DataTemplate with an x:Key and then set it as
a StaticResource for properties that take DataTemplate types, such as the ItemTemplate
property or the ContentTemplate property.
Essentially, the DataTemplate in the above example defines that whenever there is a
Photo object, it should appear as an Image within a Border. With this DataTemplate, our
app now looks like this.
The data templating model provides other features. For example, if you are displaying
collection data that contains other collections using a HeaderedItemsControl type such
as a Menu or a TreeView, there is the HierarchicalDataTemplate. Another data
templating feature is the DataTemplateSelector, which allows you to choose a
DataTemplate to use based on custom logic. For more information, see Data Templating
Overview, which provides a more in-depth discussion of the different data templating
features.
Triggers
A trigger sets properties or starts actions, such as an animation, when a property value
changes or when an event is raised. Style, ControlTemplate, and DataTemplate all have a
Triggers property that can contain a set of triggers. There are several types of triggers.
PropertyTriggers
A Trigger that sets property values or starts actions based on the value of a property is
called a property trigger.
To demonstrate how to use property triggers, you can make each ListBoxItem partially
transparent unless it is selected. The following style sets the Opacity value of a
ListBoxItem to 0.5 . When the IsSelected property is true , however, the Opacity is set to
1.0 .
XAML
<Window.Resources>
<!-- .... other resources .... -->
<Style TargetType="ListBoxItem">
<Setter Property="Opacity" Value="0.5" />
<Setter Property="MaxHeight" Value="75" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter Property="Opacity" Value="1.0" />
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
This example uses a Trigger to set a property value, but note that the Trigger class also
has the EnterActions and ExitActions properties that enable a trigger to perform actions.
Notice that the MaxHeight property of the ListBoxItem is set to 75 . In the following
illustration, the third item is the selected item.
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter Property="Opacity" Value="1.0" />
</Trigger.Setters>
</Trigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.2"
Storyboard.TargetProperty="MaxHeight"
To="90" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:1"
Storyboard.TargetProperty="MaxHeight" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
Visual States
Controls are always in a specific state. For example, when the mouse moves over the
surface of a control, the control is considered to be in a common state of MouseOver . A
control without a specific state is considered to be in the common Normal state. States
are broken into groups, and the previously mentioned states are part of the state group
CommonStates . Most controls have two state groups: CommonStates and FocusStates . Of
each state group applied to a control, a control is always in one state of each group,
such as CommonStates.MouseOver and FocusStates.Unfocused . However, a control can't
be in two different states within the same group, such as CommonStates.Normal and
CommonStates.Disabled . Here is a table of states most controls recognize and use.
For example, the following XAML code watches the CommonStates.MouseOver state to
animate the fill color of the element named backgroundElement . When the control
returns to the CommonStates.Normal state, the fill color of the element named
backgroundElement is restored.
XAML
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<ColorAnimation
Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).
(SolidColorBrush.Color)"
To="{TemplateBinding Background}"
Duration="0:0:0.3"/>
</VisualState>
<VisualState Name="MouseOver">
<ColorAnimation
Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).
(SolidColorBrush.Color)"
To="Yellow"
Duration="0:0:0.3"/>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
...
WPF themes are defined by using the styling and templating mechanism that WPF
exposes for customizing the visuals of any element.
WPF theme resources are stored in embedded resource dictionaries. These resource
dictionaries must be embedded within a signed assembly, and can either be embedded
in the same assembly as the code itself or in a side-by-side assembly. For
PresentationFramework.dll, the assembly that contains WPF controls, theme resources
are in a series of side-by-side assemblies.
The theme becomes the last place to look when searching for the style of an element.
Typically, the search will begin by walking up the element tree searching for an
appropriate resource, then look in the app resource collection and finally query the
system. This gives app developers a chance to redefine the style for any object at the
tree or app level before reaching the theme.
You can define resource dictionaries as individual files that enable you to reuse a theme
across multiple apps. You can also create swappable themes by defining multiple
resource dictionaries that provide the same types of resources but with different values.
Redefining these styles or other resources at the app level is the recommended
approach for skinning an app.
To share a set of resources, including styles and templates, across apps, you can create a
XAML file and define a ResourceDictionary that includes reference to a shared.xaml file.
XAML
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>
If you are creating a theme for your custom control, see the Defining resources at the
theme level section of the Control authoring overview.
See also
Pack URIs in WPF
How to: Find ControlTemplate-Generated Elements
Find DataTemplate-Generated Elements
Create a template for a control
Article • 03/01/2022
With Windows Presentation Foundation (WPF), you can customize an existing control's
visual structure and behavior with your own reusable template. Templates can be
applied globally to your application, windows and pages, or directly to controls. Most
scenarios that require you to create a new control can be covered by instead creating a
new template for an existing control.
In this article, you'll explore creating a new ControlTemplate for the Button control.
In most user interfaces, a button has the same general appearance: a rectangle with
some text. If you wanted to create a rounded button, you could create a new control
that inherits from the button or recreates the functionality of the button. In addition, the
new user control would provide the circular visual.
You can avoid creating new controls by customizing the visual layout of an existing
control. With a rounded button, you create a ControlTemplate with the desired visual
layout.
On the other hand, if you need a control with new functionality, different properties, and
new settings, you would create a new UserControl.
Prerequisites
Create a new WPF application and in MainWindow.xaml (or another window of your
choice) set the following properties on the <Window> element:
Property Value
SizeToContent WidthAndHeight
MinWidth 250
XAML
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
In the end, the MainWindow.xaml file should look similar to the following:
XAML
<Window x:Class="IntroToStylingAndTemplating.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
xmlns:local="clr-namespace:IntroToStylingAndTemplating"
mc:Ignorable="d"
Title="Template Intro Sample" SizeToContent="WidthAndHeight"
MinWidth="250">
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
</Window>
XAML
<Window x:Class="IntroToStylingAndTemplating.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
xmlns:local="clr-namespace:IntroToStylingAndTemplating"
mc:Ignorable="d"
Title="Template Intro Sample" SizeToContent="WidthAndHeight"
MinWidth="250">
<Window.Resources>
</Window.Resources>
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
</Window>
Property Value
x:Key roundbutton
TargetType Button
XAML
TemplateBinding
When you create a new ControlTemplate, you still might want to use the public
properties to change the control's appearance. The TemplateBinding markup extension
binds a property of an element that is in the ControlTemplate to a public property that is
defined by the control. When you use a TemplateBinding, you enable properties on the
control to act as parameters to the template. That is, when a property on a control is set,
that value is passed on to the element that has the TemplateBinding on it.
Ellipse
Notice that the Fill and Stroke properties of the <Ellipse> element are bound to the
control's Foreground and Background properties.
ContentPresenter
A <ContentPresenter> element is also added to the template. Because this template is
designed for a button, take into consideration that the button inherits from
ContentControl. The button presents the content of the element. You can set anything
inside of the button, such as plain text or even another control. Both of the following are
valid buttons:
XAML
<Button>My Text</Button>
<Button>
<CheckBox>Checkbox in a button</CheckBox>
</Button>
In both of the previous examples, the text and the checkbox are set as the
Button.Content property. Whatever is set as the content can be presented through a
<ContentPresenter>, which is what the template does.
XAML
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
XAML
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button Template="{StaticResource roundbutton}">Button 2</Button>
</StackPanel>
If you run the project and look at the result, you'll see that the button has a rounded
background.
You may have noticed that the button isn't a circle but is skewed. Because of the way the
<Ellipse> element works, it always expands to fill the available space. Make the circle
uniform by changing the button's width and height properties to the same value:
XAML
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button Template="{StaticResource roundbutton}" Width="65"
Height="65">Button 2</Button>
</StackPanel>
Add a Trigger
Even though a button with a template applied looks different, it behaves the same as
any other button. If you press the button, the Click event fires. However, you may have
noticed that when you move your mouse over the button, the button's visuals don't
change. These visual interactions are all defined by the template.
With the dynamic event and property systems that WPF provides, you can watch a
specific property for a value and then restyle the template when appropriate. In this
example, you'll watch the button's IsMouseOver property. When the mouse is over the
control, style the <Ellipse> with a new color. This type of trigger is known as a
PropertyTrigger.
For this to work, you'll need to add a name to the <Ellipse> that you can reference. Give
it the name of backgroundElement.
XAML
Next, add a new Trigger to the ControlTemplate.Triggers collection. The trigger will
watch the IsMouseOver event for the value true .
XAML
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Next, add a <Setter> to the <Trigger> that changes the Fill property of the <Ellipse>
to a new color.
XAML
Run the project. Notice that when you move the mouse over the button, the color of the
<Ellipse> changes.
Use a VisualState
Visual states are defined and triggered by a control. For example, when the mouse is
moved on top of the control, the CommonStates.MouseOver state is triggered. You can
animate property changes based on the current state of the control. In the previous
section, a <PropertyTrigger> was used to change the foreground of the button to
AliceBlue when the IsMouseOver property was true . Instead, create a visual state that
animates the change of this color, providing a smooth transition. For more information
about VisualStates, see Styles and templates in WPF.
XAML
XAML
Any animations defined in a <VisualState> are applied when that state is triggered.
Create animations for each state. Animations are put inside of a <Storyboard> element.
For more information about storyboards, see Storyboards Overview.
Normal
This state animates the ellipse fill, restoring it to the control's Background color.
XAML
<Storyboard>
<ColorAnimation Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).
(SolidColorBrush.Color)"
To="{TemplateBinding Background}"
Duration="0:0:0.3"/>
</Storyboard>
MouseOver
This state animates the ellipse Background color to a new color: Yellow .
XAML
<Storyboard>
<ColorAnimation Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).
(SolidColorBrush.Color)"
To="Yellow"
Duration="0:0:0.3"/>
</Storyboard>
XAML
Run the project. Notice that when you move the mouse over the button, the color of the
<Ellipse> animates.
Next steps
Styles and templates in WPF
Overview of XAML Resources
How to: Find ControlTemplate-
Generated Elements
Article • 02/06/2023
This example shows how to find elements that are generated by a ControlTemplate.
Example
The following example shows a style that creates a simple ControlTemplate for the
Button class:
XAML
To find an element within the template after the template has been applied, you can call
the FindName method of the Template. The following example creates a message box
that shows the actual width value of the Grid within the control template:
C#
See also
Find DataTemplate-Generated Elements
Styling and Templating
WPF XAML Namescopes
Trees in WPF
Control Customization
Article • 02/06/2023
This category covers the various base classes, interfaces and other elements and
concepts used in creating a fully functional Windows Presentation Foundation (WPF)
control.
In This Section
Control Authoring Overview
Guidelines for Designing Stylable Controls
Adorners
Control Styles and Templates
UI Automation of a WPF Custom Control
See also
Styling and Templating
Control authoring overview
Article • 03/17/2022
The extensibility of the Windows Presentation Foundation (WPF) control model greatly
reduces the need to create a new control. However, in certain cases you may still need
to create a custom control. This topic discusses the features that minimize your need to
create a custom control and the different control authoring models in Windows
Presentation Foundation (WPF). This topic also demonstrates how to create a new
control.
Rich Content. Many of the standard WPF controls support rich content. For
example, the content property of a Button is of type Object, so theoretically
anything can be displayed on a Button. To have a button display an image and
text, you can add an image and a TextBlock to a StackPanel and assign the
StackPanel to the Content property. Because the controls can display WPF visual
elements and arbitrary data, there is less need to create a new control or to modify
an existing control to support a complex visualization. For more information about
the content model for Button and other content models in WPF, see WPF Content
Model.
7 Note
Triggers. A Trigger allows you to dynamically change the appearance and behavior
of a control without creating a new control. For example, suppose you have
multiple ListBox controls in your application and want the items in each ListBox to
be bold and red when they are selected. Your first instinct might be to create a
class that inherits from ListBox and override the OnSelectionChanged method to
change the appearance of the selected item, but a better approach is to add a
trigger to a style of a ListBoxItem that changes the appearance of the selected
item. A trigger enables you to change property values or take actions based on the
value of a property. An EventTrigger enables you to take actions when an event
occurs.
For more information about styles, templates, and triggers, see Styling and Templating.
In general, if your control mirrors the functionality of an existing control, but you want
the control to look different, you should first consider whether you can use any of the
methods discussed in this section to change the existing control's appearance.
If built correctly, a UserControl can take advantage of the benefits of rich content, styles,
and triggers. However, if your control inherits from UserControl, people who use your
control will not be able to use a DataTemplate or ControlTemplate to customize its
appearance. It is necessary to derive from the Control class or one of its derived classes
(other than UserControl) to create a custom control that supports templates.
You want to build your control similarly to how you build an application.
Consider deriving from Control instead of using the UserControl class if any of the
following apply:
You want to define the appearance of your control by defining your own render
logic.
You want to compose existing elements in novel ways that go beyond what is
possible with UserControl and Control.
If you want a property of your control to support any of this functionality, you should
implement it as a dependency property. The following example defines a dependency
property named Value by doing the following:
The metadata for the property. The metadata contains the property's default
value, a CoerceValueCallback and a PropertyChangedCallback.
Define a CLR wrapper property named Value , which is the same name that is used
to register the dependency property, by implementing the property's get and set
accessors. Note that the get and set accessors only call GetValue and SetValue
respectively. It is recommended that the accessors of dependency properties not
contain additional logic because clients and WPF can bypass the accessors and call
GetValue and SetValue directly. For example, when a property is bound to a data
source, the property's set accessor is not called. Instead of adding additional logic
to the get and set accessors, use the ValidateValueCallback, CoerceValueCallback,
and PropertyChangedCallback delegates to respond to or check the value when it
changes. For more information on these callbacks, see Dependency Property
Callbacks and Validation.
C#
/// <summary>
/// Identifies the Value dependency property.
/// </summary>
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value", typeof(decimal), typeof(NumericUpDown),
new FrameworkPropertyMetadata(MinValue, new
PropertyChangedCallback(OnValueChanged),
new
CoerceValueCallback(CoerceValue)));
/// <summary>
/// Gets or sets the value assigned to the control.
/// </summary>
public decimal Value
{
get { return (decimal)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static object CoerceValue(DependencyObject element, object value)
{
decimal newValue = (decimal)value;
NumericUpDown control = (NumericUpDown)element;
return newValue;
}
RoutedPropertyChangedEventArgs<decimal> e = new
RoutedPropertyChangedEventArgs<decimal>(
(decimal)args.OldValue, (decimal)args.NewValue, ValueChangedEvent);
control.OnValueChanged(e);
}
The routing strategy is Bubble, which means that an event handler on the
source (the object that raises the event) is called first, and then event handlers
on the source's parent elements are called in succession, starting with the event
handler on the closest parent element.
C#
/// <summary>
/// Identifies the ValueChanged routed event.
/// </summary>
public static readonly RoutedEvent ValueChangedEvent =
EventManager.RegisterRoutedEvent(
"ValueChanged", RoutingStrategy.Bubble,
typeof(RoutedPropertyChangedEventHandler<decimal>),
typeof(NumericUpDown));
/// <summary>
/// Occurs when the Value property changes.
/// </summary>
public event RoutedPropertyChangedEventHandler<decimal> ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
/// <summary>
/// Raises the ValueChanged event.
/// </summary>
/// <param name="args">Arguments associated with the ValueChanged event.
</param>
protected virtual void
OnValueChanged(RoutedPropertyChangedEventArgs<decimal> args)
{
RaiseEvent(args);
}
For more information, see Routed Events Overview and Create a Custom Routed Event.
Use Binding
To decouple the UI of your control from its logic, consider using data binding. This is
particularly important if you define the appearance of your control by using a
ControlTemplate. When you use data binding, you might be able to eliminate the need
to reference specific parts of the UI from the code. It's a good idea to avoid referencing
elements that are in the ControlTemplate because when the code references elements
that are in the ControlTemplate and the ControlTemplate is changed, the referenced
element needs to be included in the new ControlTemplate.
The following example updates the TextBlock of the NumericUpDown control, assigning a
name to it and referencing the textbox by name in code.
XAML
C#
XAML
</Border>
For more information about data binding, see Data Binding Overview.
Dependency Properties
Be sure to implement CLR get and set accessors as described earlier, in "Use
Dependency Properties." Designers may use the wrapper to detect the presence of a
dependency property, but they, like WPF and clients of the control, are not required to
call the accessors when getting or setting the property.
Attached Properties
You should implement attached properties on custom controls using the following
guidelines:
Implement a pair of public static CLR methods named Set PropertyName and
Get PropertyName. Both methods should accept a class derived from
DependencyProperty as their first argument. The Set PropertyName method also
accepts an argument whose type matches the registered data type for the
property. The Get PropertyName method should return a value of the same type. If
the Set PropertyName method is missing, the property is marked read-only.
Set PropertyName and Get PropertyName must route directly to the GetValue and
When an application looks for a resource, it looks at three levels in the following order:
The system starts with the element that references the resource and then searches
resources of the logical parent and so forth until the root element is reached.
Theme-level dictionaries are stored in a subfolder named Themes. The files in the
Themes folder correspond to themes. For example, you might have
Aero.NormalColor.xaml, Luna.NormalColor.xaml, Royale.NormalColor.xaml, and so
on. You can also have a file named generic.xaml. When the system looks for a
resource at the themes level, it first looks for it in the theme-specific file and then
looks for it in generic.xaml.
When your control is in an assembly that is separate from the application, you must put
your global resources at the element level or at the theme level. Both methods have
their advantages.
XAML
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<LinearGradientBrush
x:Key="myBrush"
StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
</LinearGradientBrush>
</ResourceDictionary>
Once you have defined your dictionary, you need to merge it with your control's
resource dictionary. You can do this by using XAML or code.
XAML
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
C#
internal static class SharedDictionaryManager
{
internal static ResourceDictionary SharedDictionary
{
get
{
if (_sharedDictionary == null)
{
System.Uri resourceLocater =
new
System.Uri("/ElementResourcesCustomControlLibrary;component/Dictionary1.xaml
",
System.UriKind.Relative);
_sharedDictionary =
(ResourceDictionary)Application.LoadComponent(resourceLocater);
}
return _sharedDictionary;
}
}
The following example merges the shared resource with the resources of a custom
control in the control's constructor before it calls InitializeComponent . Because the
SharedDictionaryManager.SharedDictionary is a static property, the ResourceDictionary
is created only once. Because the resource dictionary was merged before
InitializeComponent was called, the resources are available to the control in its XAML
file.
C#
public NumericUpDown()
{
this.Resources.MergedDictionaries.Add(SharedDictionaryManager.SharedDictiona
ry);
InitializeComponent();
}
WPF enables you to create resources for different Windows themes. As a control author,
you can define a resource for a specific theme to change your control's appearance
depending on what theme is in use. For example, the appearance of a Button in the
Windows Classic theme (the default theme for Windows 2000) differs from a Button in
the Windows Luna theme (the default theme for Windows XP) because the Button uses
a different ControlTemplate for each theme.
Resources that are specific to a theme are kept in a resource dictionary with a specific
file name. These files must be in a folder named Themes that is a subfolder of the folder
that contains the control. The following table lists the resource dictionary files and the
theme that is associated with each file:
You do not need to define a resource for every theme. If a resource is not defined for a
specific theme, then the control checks Classic.xaml for the resource. If the resource is
not defined in the file that corresponds to the current theme or in Classic.xaml , the
control uses the generic resource, which is in a resource dictionary file named
generic.xaml . The generic.xaml file is located in the same folder as the theme-specific
When you put a ControlTemplate in any of the theme-specific resource dictionary files,
you must create a static constructor for your control and call the
OverrideMetadata(Type, PropertyMetadata) method on the DefaultStyleKey, as shown in
the following example.
C#
static NumericUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown),
new FrameworkPropertyMetadata(typeof(NumericUpDown)));
}
When you define a resource at the element level, you can assign a string as its key and
access the resource via the string. When you define a resource at the theme level, you
must use a ComponentResourceKey as the key. The following example defines a
resource in generic.xaml.
XAML
<LinearGradientBrush
x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type
local:Painter},
ResourceId=MyEllipseBrush}"
StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="Blue" Offset="0" />
<GradientStop Color="Red" Offset="0.5" />
<GradientStop Color="Green" Offset="1"/>
</LinearGradientBrush>
XAML
<RepeatButton
Grid.Column="1" Grid.Row="0"
Background="{StaticResource {ComponentResourceKey
TypeInTargetAssembly={x:Type local:NumericUpDown},
ResourceId=ButtonBrush}}">
Up
</RepeatButton>
<RepeatButton
Grid.Column="1" Grid.Row="1"
Background="{StaticResource {ComponentResourceKey
TypeInTargetAssembly={x:Type local:NumericUpDown},
ResourceId=ButtonBrush}}">
Down
</RepeatButton>
C#
[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly,
ResourceDictionaryLocation.SourceAssembly)]
See also
Design XAML in Visual Studio
Pack URIs in WPF
Control Customization
Creating a Control That Has a
Customizable Appearance
Article • 08/04/2022
Windows Presentation Foundation (WPF) gives you the ability to create a control whose
appearance can be customized. For example, you can change the appearance of a
CheckBox beyond what setting properties will do by creating a new ControlTemplate.
The following illustration shows a CheckBox that uses a default ControlTemplate and a
CheckBox that uses a custom ControlTemplate.
If you follow the parts and states model when you create a control, your control's
appearance will be customizable. Designer tools such as Blend for Visual Studio support
the parts and states model, so when you follow this model your control will be
customizable in those types of applications. This topic discusses the parts and states
model and how to follow it when you create your own control. This topic uses an
example of a custom control, NumericUpDown , to illustrate the philosophy of this model.
The NumericUpDown control displays a numeric value, which a user can increase or
decrease by clicking on the control's buttons. The following illustration shows the
NumericUpDown control that is discussed in this topic.
Prerequisites
Complete Example
Prerequisites
This topic assumes that you know how to create a new ControlTemplate for an existing
control, are familiar with what the elements on a control contract are, and understand
the concepts discussed in Create a template for a control.
7 Note
To create a control that can have its appearance customized, you must create a
control that inherits from the Control class or one of its subclasses other than
UserControl. A control that inherits from UserControl is a control that can be
quickly created, but it does not use a ControlTemplate and you cannot customize
its appearance.
Define the visual structure and visual behavior in the ControlTemplate of a control.
Follow certain best practices when your control's logic interacts with parts of the
control template.
When you define the visual structure and visual behavior in the ControlTemplate of a
control, application authors can change the visual structure and visual behavior of your
control by creating a new ControlTemplate instead of writing code. You must provide a
control contract that tells application authors which FrameworkElement objects and
states should be defined in the ControlTemplate. You should follow some best practices
when you interact with the parts in the ControlTemplate so that your control properly
handles an incomplete ControlTemplate. If you follow these three principles, application
authors will be able to create a ControlTemplate for your control just as easily as they
can for the controls that ship with WPF. The following section explains each of these
recommendations in detail.
In the example of the NumericUpDown control, the visual structure includes two
RepeatButton controls and a TextBlock. If you add these controls in the code of the
NumericUpDown control--in its constructor, for example--the positions of those controls
would be unalterable. Instead of defining the control's visual structure and visual
behavior in its code, you should define it in the ControlTemplate. Then an application
developer to customize the position of the buttons and TextBlock and specify what
behavior occurs when Value is negative because the ControlTemplate can be replaced.
The following example shows the visual structure of the NumericUpDown control, which
includes a RepeatButton to increase Value , a RepeatButton to decrease Value , and a
TextBlock to display Value .
XAML
<ControlTemplate TargetType="src:NumericUpDown">
<Grid Margin="3"
Background="{TemplateBinding Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ControlTemplate>
A visual behavior of the NumericUpDown control is that the value is in a red font if it is
negative. If you change the Foreground of the TextBlock in code when the Value is
negative, the NumericUpDown will always show a red negative value. You specify the visual
behavior of the control in the ControlTemplate by adding VisualState objects to the
ControlTemplate. The following example shows the VisualState objects for the Positive
and Negative states. Positive and Negative are mutually exclusive (the control is
always in exactly one of the two), so the example puts the VisualState objects into a
single VisualStateGroup. When the control goes into the Negative state, the Foreground
of the TextBlock turns red. When the control is in the Positive state, the Foreground
returns to its original value. Defining VisualState objects in a ControlTemplate is further
discussed in Create a template for a control.
7 Note
XAML
<ControlTemplate TargetType="local:NumericUpDown">
<Grid Margin="3"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValueStates">
</VisualState>
The following practices will ensure that your control responds properly to missing
FrameworkElement objects:
1. Set the x:Name attribute for each FrameworkElement that you need to reference in
code.
2. Define private properties for each FrameworkElement that you need to interact
with.
3. Subscribe to and unsubscribe from any events that your control handles in the
FrameworkElement property's set accessor.
5. Check that the FrameworkElement is not null before accessing its members. If it is
null , do not report an error.
The following examples show how the NumericUpDown control interacts with
FrameworkElement objects in accordance with the recommendations in the preceding
list.
In the example that defines the visual structure of the NumericUpDown control in the
ControlTemplate, the RepeatButton that increases Value has its x:Name attribute set to
UpButton . The following example declares a property called UpButtonElement that
represents the RepeatButton that is declared in the ControlTemplate. The set accessor
first unsubscribes to the button's Click event if UpDownElement is not null , then it sets
the property, and then it subscribes to the Click event. There is also a property defined,
but not shown here, for the other RepeatButton, called DownButtonElement .
C#
set
{
if (upButtonElement != null)
{
upButtonElement.Click -=
new RoutedEventHandler(upButtonElement_Click);
}
upButtonElement = value;
if (upButtonElement != null)
{
upButtonElement.Click +=
new RoutedEventHandler(upButtonElement_Click);
}
}
}
The following example shows the OnApplyTemplate for the NumericUpDown control. The
example uses the GetTemplateChild method to get the FrameworkElement objects from
the ControlTemplate. Notice that the example guards against cases where
GetTemplateChild finds a FrameworkElement with the specified name that is not of the
expected type. It is also a best practice to ignore elements that have the specified
x:Name but are of the wrong type.
C#
UpdateStates(false);
}
By following the practices that are shown in the previous examples, you ensure that your
control will continue to run when the ControlTemplate is missing a FrameworkElement.
The following example repeats the previous example that shows the VisualState objects
that correspond to the Positive and Negative states of the control. The Storyboard in
the Negative VisualState turns the Foreground of the TextBlock red. When the
NumericUpDown control is in the Negative state, the storyboard in the Negative state
begins. Then the Storyboard in the Negative state stops when the control returns to the
Positive state. The Positive VisualState does not need to contain a Storyboard because
when the Storyboard for the Negative stops, the Foreground returns to its original color.
XAML
<ControlTemplate TargetType="local:NumericUpDown">
<Grid Margin="3"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValueStates">
</VisualState>
Note that the TextBlock is given a name, but the TextBlock is not in the control contract
for NumericUpDown because the control's logic never references the TextBlock. Elements
that are referenced in the ControlTemplate have names, but do not need to be part of
the control contract because a new ControlTemplate for the control might not need to
reference that element. For example, someone who creates a new ControlTemplate for
NumericUpDown might decide to not indicate that Value is negative by changing the
Foreground. In that case, neither the code nor the ControlTemplate references the
TextBlock by name.
The control's logic is responsible for changing the control's state. The following example
shows that the NumericUpDown control calls the GoToState method to go into the
Positive state when Value is 0 or greater, and the Negative state when Value is less
than 0.
C#
if (Value >= 0)
{
VisualStateManager.GoToState(this, "Positive", useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Negative", useTransitions);
}
The GoToState method performs the logic necessary to start and stop the storyboards
appropriately. When a control calls GoToState to change its state, the
VisualStateManager does the following:
If the VisualState that the control is going to has a Storyboard, the storyboard
begins. Then, if the VisualState that the control is coming from has a Storyboard,
the storyboard ends.
If the control is already in the state that is specified, GoToState takes no action and
returns true .
The NumericUpDown control uses its Value property to track whether it is in the Positive
or Negative state. The NumericUpDown control also defines the Focused and UnFocused
states, which tracks the IsFocused property. If you use states that do not naturally
correspond to a property of the control, you can define a private property to track the
state.
A single method that updates all the states centralizes calls to the VisualStateManager
and keeps your code manageable. The following example shows the NumericUpDown
control's helper method, UpdateStates . When Value is greater than or equal to 0, the
Control is in the Positive state. When Value is less than 0, the control is in the
Negative state. When IsFocused is true , the control is in the Focused state; otherwise, it
is in the Unfocused state. The control can call UpdateStates whenever it needs to change
its state, regardless of what state changes.
C#
if (IsFocused)
{
VisualStateManager.GoToState(this, "Focused", useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Unfocused", useTransitions);
}
}
If you pass a state name to GoToState when the control is already in that state,
GoToState does nothing, so you don't need to check for the control's current state. For
example, if Value changes from one negative number to another negative number, the
storyboard for the Negative state is not interrupted and the user will not see a change
in the control.
VisualStateGroup and the Focused and Unfocused VisualState objects in another. (You
can see the Focused and Unfocused VisualState defined in the Complete Example section
in this topic When the control goes from the Positive state to the Negative state, or
vice versa, the control remains in either the Focused or Unfocused state.
There are three typical places where the state of a control might change:
The following examples demonstrate updating the state of the NumericUpDown control in
these cases.
You should update the state of the control in the OnApplyTemplate method so that the
control appears in the correct state when the ControlTemplate is applied. The following
example calls UpdateStates in OnApplyTemplate to ensure that the control is in the
appropriate states. For example, suppose that you create a NumericUpDown control, and
then set its Foreground to green and Value to -5. If you do not call UpdateStates when
the ControlTemplate is applied to the NumericUpDown control, the control is not in the
Negative state and the value is green instead of red. You must call UpdateStates to put
C#
UpdateStates(false);
}
You often need to update the states of a control when a property changes. The
following example shows the entire ValueChangedCallback method. Because
ValueChangedCallback is called when Value changes, the method calls UpdateStates in
case Value changed from positive to negative or vice versa. It is acceptable to call
UpdateStates when Value changes but remains positive or negative because in that
case, the control will not change states.
C#
You might also need to update states when an event occurs. The following example
shows that the NumericUpDown calls UpdateStates on the Control to handle the GotFocus
event.
C#
The VisualStateManager helps you manage your control's states. By using the
VisualStateManager, you ensure that your control correctly transitions between states. If
you follow the recommendations described in this section for working with the
VisualStateManager, your control's code will remain readable and maintainable.
The states of the control and the group each state belongs to.
Positive
Negative
Unfocused
To specify what FrameworkElement objects the control expects, you use the
TemplatePartAttribute, which specifies the name and type of the expected elements. To
specify the possible states of a control, you use the TemplateVisualStateAttribute, which
specifies the state's name and which VisualStateGroup it belongs to. Put the
TemplatePartAttribute and TemplateVisualStateAttribute on the class definition of the
control.
Any public property that affects the appearance of your control is also a part of the
control contract.
The following example specifies the FrameworkElement object and states for the
NumericUpDown control.
C#
Complete Example
The following example is the entire ControlTemplate for the NumericUpDown control.
XAML
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValueStates">
</VisualState>
<VisualStateGroup Name="FocusStates">
Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
namespace VSMCustomControl
{
[TemplatePart(Name = "UpButtonElement", Type = typeof(RepeatButton))]
[TemplatePart(Name = "DownButtonElement", Type = typeof(RepeatButton))]
[TemplateVisualState(Name = "Positive", GroupName = "ValueStates")]
[TemplateVisualState(Name = "Negative", GroupName = "ValueStates")]
[TemplateVisualState(Name = "Focused", GroupName = "FocusedStates")]
[TemplateVisualState(Name = "Unfocused", GroupName = "FocusedStates")]
public class NumericUpDown : Control
{
public NumericUpDown()
{
DefaultStyleKey = typeof(NumericUpDown);
this.IsTabStop = true;
}
set
{
SetValue(ValueProperty, value);
}
}
if (IsFocused)
{
VisualStateManager.GoToState(this, "Focused",
useTransitions);
}
else
{
VisualStateManager.GoToState(this, "Unfocused",
useTransitions);
}
}
UpdateStates(false);
}
set
{
if (downButtonElement != null)
{
downButtonElement.Click -=
new RoutedEventHandler(downButtonElement_Click);
}
downButtonElement = value;
if (downButtonElement != null)
{
downButtonElement.Click +=
new RoutedEventHandler(downButtonElement_Click);
}
}
}
set
{
if (upButtonElement != null)
{
upButtonElement.Click -=
new RoutedEventHandler(upButtonElement_Click);
}
upButtonElement = value;
if (upButtonElement != null)
{
upButtonElement.Click +=
new RoutedEventHandler(upButtonElement_Click);
}
}
}
See also
Create a template for a control
Control Customization
Guidelines for Designing Stylable
Controls
Article • 08/18/2022
This document summarizes a set of best practices to consider when designing a control
which you intend to be easily stylable and templatable. We came to this set of best
practices through a lot of trial and error while working on the theme control styles for
the built-in WPF control set. We learned that successful styling is as much a function of a
well-designed object model as it is of the style itself. The intended audience for this
document is the control author, not the style author.
Terminology
"Styling and templating" refer to the suite of technologies that enable a control author
to defer the visual aspects of the control to the style and template of the control. This
suite of technologies includes:
Resources.
Control templates.
Data templates.
To understand your control's common usage, it's good to think about the value
proposition of the control. What does your control bring to the table that no other
control can offer? Common usage does not imply any specific visual appearance, but
rather the philosophy of the control and a reasonable set of expectations about its
usage. This understanding allows you to make some assumptions about the
composition model and the style-defined behaviors of the control in the common case.
In the case of ComboBox, for example, understanding the common usage won't give
you any insight about whether a particular ComboBox has rounded corners, but it will
give you insight into the fact that the ComboBox probably needs a pop-up window and
some way of toggling whether it is open.
General Guidelines
Do not strictly enforce template contracts. The template contract of a control
might consist of elements, commands, bindings, triggers, or even property settings
that are required or expected for a control to function properly.
Design around the expectation that during design time (that is, when using a
design tool) it is common for a control template to be in an incomplete state.
WPF does not offer a "composing" state infrastructure, so controls have to be
built with the expectation that such a state might be valid.
Standalone helper types are public and reusable controls or primitives that are
used "anonymously" in a template, meaning that neither the helper element nor
the styled control is aware of the other. Technically, any element can be an
anonymous type, but in this context the term describes those types that
encapsulate specialized functionality to enable targeted scenarios.
The following table shows helper elements employed by control styles today (this
list is not exhaustive):
Named helper elements should be identified by the parent and the parent
should establish any required settings on the helper element.
Type-based helper elements should establish any required settings directly on
themselves. Doing this may require the helper element to query for information
context in which it is being used, including its TemplatedParent (the control type
of the template in which it is being used). For example, ContentPresenter
automatically binds the Content property of its TemplatedParent to its Content
property when used in a ContentControl derived type.
Use the Name property to flag elements within a template. A control that needs
to find an element in its style in order to access it programmatically should do so
using the Name property and the FindName paradigm. A control should not throw
an exception when an element is not found, but silently and gracefully disable the
functionality which required that element.
Use best practices for expressing control state and behavior in a style. The
following is an ordered list of best practices for expressing control state changes
and behavior in a style. You should use the first item on the list that enables your
scenario.
7. Bubbled events from named helper types. If you listen for bubbled events
from a style element, you should require that the element generating the
event can be uniquely identified. Example: Thumb in ToolBar.
Use style triggers (as opposed to template triggers) sparingly. Triggers that affect
properties on elements in the template must be declared in the template. Triggers
that affect properties on the control (no TargetName ) may be declared in the style
unless you know that changing the template should also destroy the trigger.
Be consistent with existing styling patterns. Many times there are multiple ways
to solve a problem. Be aware of and, when possible, consistent with existing
control styling patterns. This is especially important for controls that derive from
the same base type (for example, ContentControl, ItemsControl, RangeBase, and so
on).
Theme Considerations
Theme styles should attempt to have consistent property semantics across all
themes, but make no guarantee. As part of its documentation, your control
should have a document describing the control's property semantics, that is, the
"meaning" of a property for a control. For example, the ComboBox control should
define the meaning of the Background property within ComboBox. The default
styles for your control should attempt to follow the semantics defined in that
document across all themes. Control users, on the other hand, should be aware
that property semantics can change from theme to theme. In certain cases, a given
property may not be expressible under the visual constraints required by a
particular theme. (The Classic theme, for example, does not have a single border to
which Thickness can be applied for many controls.)
Theme styles do not need to have consistent trigger semantics across all themes.
The behavior exposed by a control style through triggers or animations may vary
from theme to theme. Control users should be aware that a control will not
necessarily employ the same mechanism to achieve a particular behavior across all
themes. One theme, for example, may use an animation to express hover behavior
where another theme uses a trigger. This can result in inconsistencies in behavior
preservation on customized controls. (Changing the background property, for
example, might not affect the hover state of the control if that state is expressed
using a trigger. However, if the hover state is implemented using an animation,
changing to background could irreparably break the animation and therefore the
state transition.)
Theme styles do not need to have consistent "layout" semantics across all
themes. For example, the default style does not need to guarantee that a control
will occupy the same amount of size in all themes or guarantee that a control will
have the same content margins / padding across all themes.
See also
Styling and Templating
Control Authoring Overview
Adorners
Article • 02/06/2023
This section provides information about Adorners and the Windows Presentation
Foundation (WPF) Adorner framework.
In This Section
Adorners Overview
How-to Topics
Reference
AdornedElementPlaceholder
Adorner
AdornerDecorator
AdornerHitTestResult
AdornerLayer
Related Sections
Adorners Overview
Article • 03/17/2022
Adorners are a special type of FrameworkElement, used to provide visual cues to a user.
Among other uses, Adorners can be used to add functional handles to elements or
provide state information about a control.
About Adorners
An Adorner is a custom FrameworkElement that is bound to a UIElement. Adorners are
rendered in an AdornerLayer, which is a rendering surface that is always on top of the
adorned element or a collection of adorned elements. Rendering of an adorner is
independent from rendering of the UIElement that the adorner is bound to. An adorner
is typically positioned relative to the element to which it is bound, using the standard 2D
coordinate origin located at the upper-left of the adorned element.
Windows Presentation Foundation (WPF) provides a basic framework for adorning visual
elements. The following table lists the primary types used when adorning objects, and
their purpose. Several usage examples follow:
Class Description
Adorner An abstract base class from which all concrete adorner implementations
inherit.
AdornerLayer A class representing a rendering layer for the adorner(s) of one or more
adorned elements.
7 Note
The parent of an Adorner is the AdornerLayer that renders the Adorner, not the
element being adorned.
The following example shows a class that implements a simple adorner. The example
adorner simply adorns the corners of a UIElement with circles.
C#
7 Note
Anything placed in the adorner layer is rendered on top of the rest of any styles
you have set. In other words, adorners are always visually on top and cannot be
overridden using z-order.
To enable pass-through hit testing of elements under an adorner, set the hit test
IsHitTestVisible property to false on the adorner. For more information about hit testing,
see Hit Testing in the Visual Layer.
1. Call the static method GetAdornerLayer to get an AdornerLayer object for the
UIElement to be adorned. GetAdornerLayer walks up the visual tree, starting at the
specified UIElement, and returns the first adorner layer it finds. (If no adorner layers
are found, the method returns null.)
2. Call the Add method to bind the adorner to the target UIElement.
C#
myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
myAdornerLayer.Add(new SimpleCircleAdorner(myTextBox));
7 Note
1. Call the static method GetAdornerLayer to find an adorner layer for the element
whose children are to be adorned.
2. Enumerate through the children of the parent element and call the Add method to
bind an adorner to each child element.
C#
See also
AdornerHitTestResult
Shapes and Basic Drawing in WPF Overview
Painting with Images, Drawings, and Visuals
Drawing Objects Overview
How-to Topics
Adorners How-to Topics
Article • 02/06/2023
The following examples demonstrate how to accomplish common tasks using the
Windows Presentation Foundation (WPF) adorner framework.
In This Section
Implement an Adorner
Bind an Adorner to an Element
Adorn the Children of a Panel
Remove an Adorner from an Element
Remove all Adorners from an Element
Reference
AdornedElementPlaceholder
Adorner
AdornerDecorator
AdornerHitTestResult
AdornerLayer
Related Sections
How to: Implement an Adorner
Article • 02/06/2023
Example
Description
A custom adorner is created by implementing a class that inherits from the abstract
Adorner class. The example adorner simply adorns the corners of a UIElement with
circles by overriding the OnRender method.
Code
C#
See also
Adorners Overview
How to: Bind an Adorner to an Element
Article • 02/06/2023
Example
To bind an adorner to a particular UIElement, follow these steps:
1. Call the static method GetAdornerLayer to get an AdornerLayer object for the
UIElement to be adorned. GetAdornerLayer walks up the visual tree, starting at the
specified UIElement, and returns the first adorner layer it finds. (If no adorner
layers are found, the method returns null.)
2. Call the Add method to bind the adorner to the target UIElement.
C#
myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
myAdornerLayer.Add(new SimpleCircleAdorner(myTextBox));
7 Note
See also
Adorners Overview
How to: Adorn the Children of a Panel
Article • 02/06/2023
Example
To bind an adorner to the children of a Panel, follow these steps:
1. Declare a new AdornerLayer object and call the static GetAdornerLayer method to
find an adorner layer for the element whose children are to be adorned.
2. Enumerate through the children of the parent element and call the Add method to
bind an adorner to each child element.
C#
7 Note
See also
Adorners Overview
How to: Remove an Adorner from an
Element
Article • 02/06/2023
C#
Example
This condensed code example is functionally equivalent to the verbose example shown
above. This code does not explicitly check for a null array, so it is possible that a
NullReferenceException exception may be raised. This code is best suited for
applications where a null array is expected to be rare.
C#
try { myAdornerLayer.Remove((myAdornerLayer.GetAdorners(myTextBox))[0]); }
catch { }
See also
Adorners Overview
How to: Remove all Adorners from an
Element
Article • 02/06/2023
This example shows how to programmatically remove all adorners from a specified
UIElement.
C#
Code example
This condensed code example is functionally equivalent to the verbose example shown
above. This code does not explicitly check for a null array, so it is possible that a
NullReferenceException exception may be raised. This code is best suited for
applications where a null array is expected to be rare.
C#
See also
Adorners Overview
Control Styles and Templates
Article • 02/06/2023
The desktop themes determine which resource dictionary is used. The resource
dictionaries for the desktop themes are included with your Visual Studio installation. The
folder that contains the themes is generally located at C:\Program Files (x86)\Microsoft
Visual Studio\2019\<visual studio edition>\DesignTools\SystemThemes\wpf, where
<visual studio edition> represents the edition of Visual Studio.
The following table describes the resource dictionary file names and their corresponding
desktop themes.
Classic.xaml Classic Windows look (from Windows 95, Windows 98, and Windows
2000) on the Windows XP operating system..
In This Section
Button Styles and Templates
Calendar Styles and Templates
CheckBox Styles and Templates
ComboBox Styles and Templates
ContextMenu Styles and Templates
DataGrid Styles and Templates
DatePicker Styles and Templates
DocumentViewer Styles and Templates
Expander Styles and Templates
Frame Styles and Templates
GroupBox Styles and Templates
Label Styles and Templates
ListBox Styles and Templates
ListView Styles and Templates
Menu Styles and Templates
NavigationWindow Styles and Templates
PasswordBox Styles and Templates
ProgressBar Styles and Templates
RadioButton Styles and Templates
RepeatButton Styles and Templates
ScrollBar Styles and Templates
ScrollViewer Styles and Templates
Slider Styles and Templates
StatusBar Styles and Templates
TabControl Styles and Templates
TextBox Styles and Templates
Thumb Styles and Templates
ToggleButton Styles and Templates
ToolBar Styles and Templates
ToolTip Styles and Templates
TreeView Styles and Templates
Window Styles and Templates
Reference
System.Windows.Controls
ControlTemplate
Related Sections
Control Authoring Overview
This topic describes the styles and templates for the Button control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
Button Parts
The Button control does not have any named parts.
Button States
The following table lists the visual states for the Button control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<!-- FocusVisual -->
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="2"
StrokeThickness="1"
Stroke="#60000000"
StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5" />
<VisualTransition GeneratedDuration="0"
To="Pressed" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Border.BorderBrush).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
PressedBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
PressedBorderLightColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="(TextBlock.Foreground).
(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDefault"
Value="true">
<Setter TargetName="Border"
Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
DefaultBorderBrushLightBrush}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
DefaultBorderBrushDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Calendar Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the Calendar control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
Calendar Parts
The following table lists the named parts for the Calendar control.
Calendar States
The following table lists the visual states for the Calendar control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
CalendarItem Parts
The following table lists the named parts for the CalendarItem control.
PART_PreviousButton Button The button that displays the previous page of the
calendar when it is clicked.
PART_NextButton Button The button that displays the next page of the
calendar when it is clicked.
CalendarItem States
The following table lists the visual states for the CalendarItem control.
Disabled State CommonStates The state of the calendar when the IsEnabled property is
false .
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
CalendarDayButton States
The following table lists the visual states for the CalendarDayButton control.
CalendarButton Parts
The CalendarButton control does not have any named parts.
CalendarButton States
The following table lists the visual states for the CalendarButton control.
XAML
Storyboard.TargetProperty="Visibility"
Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState Name="CalendarButtonUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="DayButtonFocusVisual"
Storyboard.TargetProperty="Visibility"
Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup Name="ActiveStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState Name="Active" />
<VisualState Name="Inactive">
<Storyboard>
<ColorAnimation Duration="0"
Storyboard.TargetName="NormalText"
Storyboard.TargetProperty="
(TextElement.Foreground).
(SolidColorBrush.Color)"
To="#FF777777" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup Name="DayStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState Name="RegularDay" />
<VisualState Name="Today">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TodayBackground"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ColorAnimation Duration="0"
Storyboard.TargetName="NormalText"
Storyboard.TargetProperty="
(TextElement.Foreground).
(SolidColorBrush.Color)"
To="#FFFFFFFF" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup Name="BlackoutDayStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState Name="NormalDay" />
<VisualState Name="BlackoutDay">
<Storyboard>
<DoubleAnimation Duration="0"
Storyboard.TargetName="Blackout"
Storyboard.TargetProperty="Opacity"
To=".2" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="TodayBackground"
RadiusX="1"
RadiusY="1"
Opacity="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource
SelectedBackgroundColor}" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="SelectedBackground"
RadiusX="1"
RadiusY="1"
Opacity="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource
SelectedBackgroundColor}" />
</Rectangle.Fill>
</Rectangle>
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" />
<Rectangle x:Name="HighlightBackground"
RadiusX="1"
RadiusY="1"
Opacity="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource
ControlMouseOverColor}" />
</Rectangle.Fill>
</Rectangle>
<ContentPresenter x:Name="NormalText"
HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding
VerticalContentAlignment}"
Margin="5,1,5,1">
<TextElement.Foreground>
<SolidColorBrush Color="#FF333333" />
</TextElement.Foreground>
</ContentPresenter>
<Path x:Name="Blackout"
Opacity="0"
Margin="3"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
RenderTransformOrigin="0.5,0.5"
Fill="#FF000000"
Stretch="Fill"
Data="M8.1772461,11.029181 L10.433105,
11.029181 L11.700684,12.801641 L12.973633,
11.029181 L15.191895,11.029181 L12.844727,
13.999395 L15.21875,17.060919 L12.962891,
17.060919 L11.673828,15.256231 L10.352539,
17.060919 L8.1396484,17.060919 L10.519043,
14.042364 z" />
<Rectangle x:Name="DayButtonFocusVisual"
Visibility="Collapsed"
IsHitTestVisible="false"
RadiusX="1"
RadiusY="1">
<Rectangle.Stroke>
<SolidColorBrush Color="{DynamicResource
SelectedBackgroundColor}" />
</Rectangle.Stroke>
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Storyboard.TargetName="CalendarButtonFocusVisual"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState Name="CalendarButtonUnfocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="SelectedBackground"
RadiusX="1"
RadiusY="1"
Opacity="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource
SelectedBackgroundColor}" />
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="Background"
RadiusX="1"
RadiusY="1"
Opacity="0">
<Rectangle.Fill>
<SolidColorBrush Color="{DynamicResource
SelectedBackgroundColor}" />
</Rectangle.Fill>
</Rectangle>
<ContentPresenter x:Name="NormalText"
HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding
VerticalContentAlignment}"
Margin="1,0,1,1">
<TextElement.Foreground>
<SolidColorBrush Color="#FF333333" />
</TextElement.Foreground>
</ContentPresenter>
<Rectangle x:Name="CalendarButtonFocusVisual"
Visibility="Collapsed"
IsHitTestVisible="false"
RadiusX="1"
RadiusY="1">
<Rectangle.Stroke>
<SolidColorBrush Color="{DynamicResource
SelectedBackgroundColor}" />
</Rectangle.Stroke>
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource ControlMediumColor}" />
</Setter.Value>
</Setter>
</Style>
Storyboard.TargetName="PART_DisabledVisual" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="1">
<Border BorderBrush="#FFFFFFFF"
BorderThickness="2"
CornerRadius="1">
<Grid>
<Grid.Resources>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button x:Name="PART_PreviousButton"
Template="{StaticResource PreviousButtonTemplate}"
Focusable="False"
HorizontalAlignment="Left"
Grid.Column="0"
Grid.Row="0"
Height="20"
Width="28" />
<Button x:Name="PART_HeaderButton"
FontWeight="Bold"
Focusable="False"
FontSize="10.5"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Column="1"
Grid.Row="0"
Template="{StaticResource HeaderButtonTemplate}" />
<Button x:Name="PART_NextButton"
Focusable="False"
HorizontalAlignment="Right"
Grid.Column="2"
Grid.Row="0"
Template="{StaticResource NextButtonTemplate}"
Height="20"
Width="28" />
<Grid x:Name="PART_MonthView"
Visibility="Visible"
Grid.ColumnSpan="3"
Grid.Row="1"
Margin="6,-1,6,6"
HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
</Grid>
<Grid x:Name="PART_YearView"
Visibility="Hidden"
Grid.ColumnSpan="3"
Grid.Row="1"
HorizontalAlignment="Center"
Margin="6,-3,7,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
</Grid>
</Grid>
</Border>
</Border>
<Rectangle x:Name="PART_DisabledVisual"
Fill="{StaticResource DisabledColor}"
Opacity="0"
RadiusY="2"
RadiusX="2"
Stretch="Fill"
Stroke="{StaticResource DisabledColor}"
StrokeThickness="1"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Visibility"
TargetName="PART_DisabledVisual"
Value="Visible" />
</Trigger>
<DataTrigger Binding="{Binding DisplayMode,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Calendar}}}"
Value="Year">
<Setter Property="Visibility"
TargetName="PART_MonthView"
Value="Hidden" />
<Setter Property="Visibility"
TargetName="PART_YearView"
Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding DisplayMode,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Calendar}}}"
Value="Decade">
<Setter Property="Visibility"
TargetName="PART_MonthView"
Value="Hidden" />
<Setter Property="Visibility"
TargetName="PART_YearView"
Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
CheckBox Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the CheckBox control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
CheckBox Parts
The CheckBox control does not have any named parts.
CheckBox States
The following table lists the visual states for the CheckBox control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
Storyboard.TargetName="CheckMark">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="
(UIElement.Visibility)"
Storyboard.TargetName="InderminateMark">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="4,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
RecognizesAccessKey="True" />
</BulletDecorator>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ComboBox Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ComboBox control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
ComboBox Parts
The following table lists the named parts for the ComboBox control.
PART_Popup Popup The drop-down that contains the items in the combo box.
When you create a ControlTemplate for a ComboBox, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
ComboBox; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is
not the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
ComboBox States
The following table lists the states for the ComboBox control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
VisualState Name VisualStateGroup Description
Name
ComboBoxItem Parts
The ComboBoxItem control does not have any named parts.
ComboBoxItem States
The following table lists the states for the ComboBoxItem control.
SelectedUnfocused SelectionStates The item is selected, but does not have focus.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<ControlTemplate x:Key="ComboBoxToggleButton"
TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed" />
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(SolidColorBrush.Color)"
Storyboard.TargetName="Arrow">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border"
Grid.ColumnSpan="2"
CornerRadius="2"
BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<Border Grid.Column="0"
CornerRadius="2,0,0,2"
Margin="1" >
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlLightColor}"/>
</Border.Background>
</Border>
<Path x:Name="Arrow"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z" >
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}"/>
</Path.Fill>
</Path>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox"
TargetType="{x:Type TextBox}">
<Border x:Name="PART_ContentHost"
Focusable="False"
Background="{TemplateBinding Background}" />
</ControlTemplate>
Storyboard.TargetName="PART_EditableTextBox">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="ContentSite">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Uneditable" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ToggleButton x:Name="ToggleButton"
Template="{StaticResource ComboBoxToggleButton}"
Grid.Column="2"
Focusable="false"
ClickMode="Press"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay,
RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter x:Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding
SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding
ItemTemplateSelector}"
Margin="3,3,23,3"
VerticalAlignment="Stretch"
HorizontalAlignment="Left">
</ContentPresenter>
<TextBox x:Name="PART_EditableTextBox"
Style="{x:Null}"
Template="{StaticResource ComboBoxTextBox}"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Margin="3,3,23,3"
Focusable="True"
Background="Transparent"
Visibility="Hidden"
IsReadOnly="{TemplateBinding IsReadOnly}" />
<Popup x:Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
<Grid x:Name="DropDown"
SnapsToDevicePixels="True"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource
BorderMediumColor}" />
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush Color="{DynamicResource
ControlLightColor}" />
</Border.Background>
</Border>
<ScrollViewer Margin="4,6,4,6"
SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems"
Value="false">
<Setter TargetName="DropDownBorder"
Property="MinHeight"
Value="95" />
</Trigger>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
<Trigger SourceName="Popup"
Property="AllowsTransparency"
Value="true">
<Setter TargetName="DropDownBorder"
Property="CornerRadius"
Value="4" />
<Setter TargetName="DropDownBorder"
Property="Margin"
Value="0,2,0,0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ContextMenu Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ContextMenu control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
ContextMenu Parts
The ContextMenu control does not have any named parts.
When you create a ControlTemplate for a ContextMenu, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
ContextMenu; the ScrollViewer enables scrolling within the control). If the
ItemsPresenter is not the direct child of the ScrollViewer, you must give the
ItemsPresenter the name, ItemsPresenter .
ContextMenu States
The following table lists the visual states for the ContextMenu control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
DataGrid Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the DataGrid control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
DataGrid Parts
The following table lists the named parts for the DataGrid control.
When you create a ControlTemplate for a DataGrid, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
DataGrid; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is
not the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
The default template for the DataGrid contains a ScrollViewer control. For more
information about the parts defined by the ScrollViewer, see ScrollViewer Styles and
Templates.
DataGrid States
The following table lists the visual states for the DataGrid control.
InvalidUnfocused ValidationStates The control is not valid and does not have focus.
DataGridCell States
The following table lists the visual states for the DataGridCell element.
InvalidUnfocused ValidationStates The cell is not valid and does not have focus.
DataGridRow Parts
The DataGridRow element does not have any named parts.
DataGridRow States
The following table lists the visual states for the DataGridRow element.
DataGridRowHeader Parts
The following table lists the named parts for the DataGridRowHeader element.
PART_TopHeaderGripper Thumb The element that is used to resize the row header from
the top.
Part Type Description
PART_BottomHeaderGripper Thumb The element that is used to resize the row header from
the bottom.
DataGridRowHeader States
The following table lists the visual states for the DataGridRowHeader element.
DataGridColumnHeadersPresenter Parts
The following table lists the named parts for the DataGridColumnHeadersPresenter
element.
DataGridColumnHeadersPresenter States
The following table lists the visual states for the DataGridColumnHeadersPresenter
element.
InvalidUnfocused ValidationStates The cell is not valid and does not have focus.
DataGridColumnHeader Parts
The following table lists the named parts for the DataGridColumnHeader element.
PART_LeftHeaderGripper Thumb The element that is used to resize the column header from
the left.
PART_RightHeaderGripper Thumb The element that is used to resize the column header from
the right.
DataGridColumnHeader States
The following table lists the visual states for the DataGridColumnHeader element.
InvalidUnfocused ValidationStates The control is not valid and does not have focus.
XAML
<!--Style and template for the button in the upper left corner of the
DataGrid.-->
<Style TargetType="{x:Type Button}"
x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle,
TypeInTargetAssembly={x:Type DataGrid}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="
(UIElement.Visibility)"
Storyboard.TargetName="Arrow">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="Border"
SnapsToDevicePixels="True">
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource BorderMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Rectangle.Stroke>
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Polygon x:Name="Arrow"
HorizontalAlignment="Right"
Margin="8,8,3,3"
Opacity="0.15"
Points="0,10 10,10 10,0"
Stretch="Uniform"
VerticalAlignment="Bottom">
<Polygon.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Polygon.Fill>
</Polygon>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Focusable="false"
Command="{x:Static DataGrid.SelectAllCommand}"
Style="{DynamicResource {ComponentResourceKey
ResourceId=DataGridSelectAllButtonStyle,
TypeInTargetAssembly={x:Type DataGrid}}}"
Visibility="{Binding HeadersVisibility,
ConverterParameter={x:Static
DataGridHeadersVisibility.All},
Converter={x:Static
DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type
DataGrid}}}"
Width="{Binding CellsPanelHorizontalOffset,
RelativeSource={RelativeSource AncestorType={x:Type
DataGrid}}}" />
<DataGridColumnHeadersPresenter
x:Name="PART_ColumnHeadersPresenter"
Grid.Column="1"
Visibility="{Binding
HeadersVisibility,
ConverterParameter={x:Static
DataGridHeadersVisibility.Column},
Converter={x:Static
DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type
DataGrid}}}" />
<ScrollContentPresenter
x:Name="PART_ScrollContentPresenter"
Grid.ColumnSpan="2"
Grid.Row="1"
CanContentScroll="{TemplateBinding
CanContentScroll}" />
<ScrollBar x:Name="PART_VerticalScrollBar"
Grid.Column="2"
Grid.Row="1"
Orientation="Vertical"
ViewportSize="{TemplateBinding ViewportHeight}"
Maximum="{TemplateBinding ScrollableHeight}"
Visibility="{TemplateBinding
ComputedVerticalScrollBarVisibility}"
Value="{Binding VerticalOffset, Mode=OneWay,
RelativeSource={RelativeSource TemplatedParent}}"/>
<Grid Grid.Column="1"
Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding
NonFrozenColumnsViewportHorizontalOffset,
RelativeSource={RelativeSource AncestorType=
{x:Type DataGrid}}}" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollBar x:Name="PART_HorizontalScrollBar"
Grid.Column="1"
Orientation="Horizontal"
ViewportSize="{TemplateBinding
ViewportWidth}"
Maximum="{TemplateBinding ScrollableWidth}"
Visibility="{TemplateBinding
ComputedHorizontalScrollBarVisibility}"
Value="{Binding HorizontalOffset,
Mode=OneWay,
RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding
SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
</Style.Triggers>
</Style>
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ContentAreaColorDark}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused_Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[0].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMediumColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal_Editing">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[0].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMediumColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver_Editing">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[0].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMediumColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver_Unfocused_Editing">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[0].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMediumColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused_Editing">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[0].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMediumColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[0].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMediumColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver_Unfocused_Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[0].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</SelectiveScrollingGrid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1"
ItemsPanel="{TemplateBinding
ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding
SnapsToDevicePixels}" />
<DataGridDetailsPresenter Grid.Column="1"
Grid.Row="1"
Visibility="{TemplateBinding
DetailsVisibility}"
SelectiveScrollingGrid.SelectiveScrollingOrientation=
"{Binding AreRowDetailsFrozen,
ConverterParameter={x:Static
SelectiveScrollingOrientation.Vertical},
Converter={x:Static DataGrid.RowDetailsScrollingConverter},
RelativeSource={RelativeSource AncestorType={x:Type
DataGrid}}}"/>
<DataGridRowHeader Grid.RowSpan="2"
SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
Visibility="{Binding HeadersVisibility,
ConverterParameter={x:Static DataGridHeadersVisibility.Row},
Converter={x:Static DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type
DataGrid}}}" />
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Thumb x:Name="PART_TopHeaderGripper"
Style="{StaticResource RowHeaderGripperStyle}"
VerticalAlignment="Top" />
<Thumb x:Name="PART_BottomHeaderGripper"
Style="{StaticResource RowHeaderGripperStyle}"
VerticalAlignment="Bottom" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Thumb x:Name="PART_LeftHeaderGripper"
HorizontalAlignment="Left"
Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb x:Name="PART_RightHeaderGripper"
HorizontalAlignment="Right"
Style="{StaticResource ColumnHeaderGripperStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
This topic describes the styles and templates for the DatePicker control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
DatePicker Parts
The following table lists the named parts for the DatePicker control.
PART_Button Button The button that opens and closes the Calendar.
PART_TextBox DatePickerTextBox The text box that allows you to input a date.
DatePicker States
The following table lists the visual states for the DatePicker control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
DatePickerTextBox Parts
The following table lists the named parts for the DatePickerTextBox control.
PART_Watermark ContentControl The element that contains the initial text in the
DatePicker.
DatePickerTextBox States
The following table lists the visual states for the DatePickerTextBox control.
Watermarked WatermarkStates The control displays its initial text. The DatePickerTextBox
is in the state when the user has not entered text or
selected a date.
Unwatermarked WatermarkStates The user has entered text into the DatePickerTextBox or
selected a date in the DatePicker.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
Storyboard.TargetName="BackgroundGradient"
Storyboard.TargetProperty="
(Border.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#F2FFFFFF" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetName="BackgroundGradient"
Storyboard.TargetProperty="
(Border.Background).
(GradientBrush.GradientStops)[2].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#CCFFFFFF" />
</ColorAnimationUsingKeyFrames>
<ColorAnimation Duration="0"
To="#FF448DCA"
Storyboard.TargetProperty="
(Border.Background).
(SolidColorBrush.Color)"
Storyboard.TargetName="Background" />
<ColorAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetName="BackgroundGradient"
Storyboard.TargetProperty="
(Border.Background).
(GradientBrush.GradientStops)[3].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#7FFFFFFF" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="
(Border.Background).
(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#FF448DCA" />
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetProperty="
(UIElement.Opacity)"
Storyboard.TargetName="Highlight">
<SplineDoubleKeyFrame KeyTime="0"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetName="BackgroundGradient"
Storyboard.TargetProperty="
(Border.Background).
(GradientBrush.GradientStops)[0].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#F4FFFFFF" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetName="BackgroundGradient"
Storyboard.TargetProperty="
(Border.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#EAFFFFFF" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetName="BackgroundGradient"
Storyboard.TargetProperty="
(Border.Background).
(GradientBrush.GradientStops)[2].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#C6FFFFFF" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0"
Duration="00:00:00.001"
Storyboard.TargetName="BackgroundGradient"
Storyboard.TargetProperty="
(Border.Background).
(GradientBrush.GradientStops)[3].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0"
Value="#6BFFFFFF" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="#11FFFFFF"
FlowDirection="LeftToRight"
HorizontalAlignment="Center"
Height="18"
Margin="0"
VerticalAlignment="Center"
Width="19">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="20*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="23*" />
<RowDefinition Height="19*" />
<RowDefinition Height="19*" />
<RowDefinition Height="19*" />
</Grid.RowDefinitions>
<Border x:Name="Highlight"
BorderThickness="1"
Grid.ColumnSpan="4"
CornerRadius="0,0,1,1"
Margin="-1"
Opacity="1"
Grid.Row="0"
Grid.RowSpan="4">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource
ControlPressedColor}" />
</Border.BorderBrush>
</Border>
<Border x:Name="Background"
BorderBrush="#FFFFFFFF"
BorderThickness="1"
Grid.ColumnSpan="4"
CornerRadius=".5"
Margin="0,-1,0,0"
Opacity="1"
Grid.Row="1"
Grid.RowSpan="3">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlDarkColor}"
/>
</Border.Background>
</Border>
<Border x:Name="BackgroundGradient"
BorderBrush="#BF000000"
BorderThickness="1"
Grid.ColumnSpan="4"
CornerRadius=".5"
Margin="0,-1,0,0"
Opacity="1"
Grid.Row="1"
Grid.RowSpan="3">
<Border.Background>
<LinearGradientBrush EndPoint=".7,1"
StartPoint=".7,0">
<GradientStop Color="#FFFFFFFF"
Offset="0" />
<GradientStop Color="#F9FFFFFF"
Offset="0.375" />
<GradientStop Color="#E5FFFFFF"
Offset="0.625" />
<GradientStop Color="#C6FFFFFF"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
<Rectangle Grid.ColumnSpan="4"
Grid.RowSpan="1"
StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource HeaderTopColor}" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.48,-1"
StartPoint="0.48,1.25">
<GradientStop Color="#FF494949" />
<GradientStop Color="#FF9F9F9F"
Offset="1" />
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
<Path Fill="#FF2F2F2F"
Grid.Row="1"
Grid.Column="0"
Grid.RowSpan="3"
Grid.ColumnSpan="4"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5"
Margin="4,3,4,3"
Stretch="Fill"
Data="M11.426758,8.4305077 L11.749023,8.4305077
L11.749023,16.331387 L10.674805,16.331387
L10.674805,10.299648 L9.0742188,11.298672
L9.0742188,10.294277 C9.4788408,10.090176
9.9094238,9.8090878 10.365967,9.4510155
C10.82251,9.0929432 11.176106,8.7527733
11.426758,8.4305077 z M14.65086,8.4305077
L18.566387,8.4305077 L18.566387,9.3435936
L15.671368,9.3435936 L15.671368,11.255703
C15.936341,11.058764 16.27293,10.960293
16.681133,10.960293 C17.411602,10.960293
17.969301,11.178717 18.354229,11.615566
C18.739157,12.052416 18.931622,12.673672
18.931622,13.479336 C18.931622,15.452317
18.052553,16.438808 16.294415,16.438808
C15.560365,16.438808 14.951641,16.234707
14.468243,15.826504 L14.881817,14.929531
C15.368796,15.326992 15.837872,15.525723
16.289043,15.525723 C17.298809,15.525723
17.803692,14.895514 17.803692,13.635098
C17.803692,12.460618 17.305971,11.873379
16.310528,11.873379 C15.83071,11.873379
15.399232,12.079271 15.016094,12.491055
L14.65086,12.238613 z" />
<Ellipse Grid.ColumnSpan="4"
Fill="#FFFFFFFF"
HorizontalAlignment="Center"
Height="3"
StrokeThickness="0"
VerticalAlignment="Center"
Width="3" />
<Border x:Name="DisabledVisual"
BorderBrush="#B2FFFFFF"
BorderThickness="1"
Grid.ColumnSpan="4"
CornerRadius="0,0,.5,.5"
Opacity="0"
Grid.Row="0"
Grid.RowSpan="4" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Storyboard.TargetName="PART_DisabledVisual" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="PART_Root"
HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding
VerticalContentAlignment}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="PART_Button"
Grid.Column="1"
Foreground="{TemplateBinding Foreground}"
Focusable="False"
HorizontalAlignment="Left"
Margin="3,0,3,0"
Grid.Row="0"
Style="{StaticResource DropDownButtonStyle}"
VerticalAlignment="Top" />
<DatePickerTextBox x:Name="PART_TextBox"
Grid.Column="0"
Foreground="{TemplateBinding Foreground}"
Focusable="{TemplateBinding Focusable}"
HorizontalContentAlignment="Stretch"
Grid.Row="0"
VerticalContentAlignment="Stretch" />
<Grid x:Name="PART_DisabledVisual"
Grid.ColumnSpan="2"
Grid.Column="0"
IsHitTestVisible="False"
Opacity="0"
Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0"
Fill="#A5FFFFFF"
RadiusY="1"
Grid.Row="0"
RadiusX="1" />
<Rectangle Grid.Column="1"
Fill="#A5FFFFFF"
Height="18"
Margin="3,0,3,0"
RadiusY="1"
Grid.Row="0"
RadiusX="1"
Width="19" />
<Popup x:Name="PART_Popup"
AllowsTransparency="True"
Placement="Bottom"
PlacementTarget="{Binding ElementName=PART_TextBox}"
StaysOpen="False" />
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
DocumentViewer Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the DocumentViewer control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
DocumentViewer Parts
The following table lists the named parts for the DocumentViewer control.
DocumentViewer States
The following table lists the visual states for the DocumentViewer control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<ScrollViewer Grid.Row="1"
CanContentScroll="true"
HorizontalScrollBarVisibility="Auto"
x:Name="PART_ContentHost"
IsTabStop="true">
<ScrollViewer.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</ScrollViewer.Background>
</ScrollViewer>
<ContentControl Grid.Row="2"
x:Name="PART_FindToolBarHost"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Expander Styles and Templates
Article • 06/02/2023
This topic describes the styles and templates for the Expander control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
Expander Parts
The Expander control does not have any named parts.
Expander States
The following table lists the visual states for the Expander control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
Expander ControlTemplate
The following example is a copy of the default template for a Expander control:
XAML
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="Expander.Static.Circle.Stroke"
Color="#FF333333"/>
<SolidColorBrush x:Key="Expander.Static.Circle.Fill" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="Expander.Static.Arrow.Stroke"
Color="#FF333333"/>
<SolidColorBrush x:Key="Expander.MouseOver.Circle.Stroke"
Color="#FF5593FF"/>
<SolidColorBrush x:Key="Expander.MouseOver.Circle.Fill"
Color="#FFF3F9FF"/>
<SolidColorBrush x:Key="Expander.MouseOver.Arrow.Stroke"
Color="#FF000000"/>
<SolidColorBrush x:Key="Expander.Pressed.Circle.Stroke"
Color="#FF3C77DD"/>
<SolidColorBrush x:Key="Expander.Pressed.Circle.Fill"
Color="#FFD9ECFF"/>
<SolidColorBrush x:Key="Expander.Pressed.Arrow.Stroke"
Color="#FF000000"/>
<SolidColorBrush x:Key="Expander.Disabled.Circle.Stroke"
Color="#FFBCBCBC"/>
<SolidColorBrush x:Key="Expander.Disabled.Circle.Fill"
Color="#FFE6E6E6"/>
<SolidColorBrush x:Key="Expander.Disabled.Arrow.Stroke"
Color="#FF707070"/>
<Style x:Key="ExpanderHeaderFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="0" StrokeDashArray="1 2"
Stroke="Black" SnapsToDevicePixels="true" StrokeThickness="1"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type
ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent"
SnapsToDevicePixels="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="circle" Fill="{StaticResource
Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19"
Stroke="{StaticResource Expander.Static.Circle.Stroke}"
VerticalAlignment="Center" Width="19"/>
<Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L
8,1.5" HorizontalAlignment="Center" Stroke="{StaticResource
Expander.Static.Arrow.Stroke}" SnapsToDevicePixels="false"
StrokeThickness="2" VerticalAlignment="Center"/>
<ContentPresenter Grid.Column="1"
HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True"
SnapsToDevicePixels="True" VerticalAlignment="Center"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Data" TargetName="arrow"
Value="M 1,4.5 L 4.5,1 L 8,4.5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
<Setter Property="StrokeThickness"
TargetName="circle" Value="1.5"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderUpHeaderStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent"
SnapsToDevicePixels="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid>
<Grid.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<TransformCollection>
<RotateTransform
Angle="180"/>
</TransformCollection>
</TransformGroup.Children>
</TransformGroup>
</Grid.LayoutTransform>
<Ellipse x:Name="circle" Fill="
{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center"
Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}"
VerticalAlignment="Center" Width="19"/>
<Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L
8,1.5" HorizontalAlignment="Center" Stroke="{StaticResource
Expander.Static.Arrow.Stroke}" SnapsToDevicePixels="false"
StrokeThickness="2" VerticalAlignment="Center"/>
</Grid>
<ContentPresenter Grid.Column="1"
HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True"
SnapsToDevicePixels="True" VerticalAlignment="Center"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Data" TargetName="arrow"
Value="M 1,4.5 L 4.5,1 L 8,4.5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
<Setter Property="StrokeThickness"
TargetName="circle" Value="1.5"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderLeftHeaderStyle" TargetType="{x:Type
ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent"
SnapsToDevicePixels="False">
<Grid.RowDefinitions>
<RowDefinition Height="19"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid>
<Grid.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<TransformCollection>
<RotateTransform
Angle="90"/>
</TransformCollection>
</TransformGroup.Children>
</TransformGroup>
</Grid.LayoutTransform>
<Ellipse x:Name="circle" Fill="
{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center"
Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}"
VerticalAlignment="Center" Width="19"/>
<Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L
8,1.5" HorizontalAlignment="Center" Stroke="{StaticResource
Expander.Static.Arrow.Stroke}" SnapsToDevicePixels="false"
StrokeThickness="2" VerticalAlignment="Center"/>
</Grid>
<ContentPresenter HorizontalAlignment="Center"
Margin="0,4,0,0" RecognizesAccessKey="True" Grid.Row="1"
SnapsToDevicePixels="True" VerticalAlignment="Top"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Data" TargetName="arrow"
Value="M 1,4.5 L 4.5,1 L 8,4.5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
<Setter Property="StrokeThickness"
TargetName="circle" Value="1.5"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderRightHeaderStyle" TargetType="{x:Type
ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent"
SnapsToDevicePixels="False">
<Grid.RowDefinitions>
<RowDefinition Height="19"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid>
<Grid.LayoutTransform>
<TransformGroup>
<TransformGroup.Children>
<TransformCollection>
<RotateTransform
Angle="-90"/>
</TransformCollection>
</TransformGroup.Children>
</TransformGroup>
</Grid.LayoutTransform>
<Ellipse x:Name="circle" Fill="
{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center"
Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}"
VerticalAlignment="Center" Width="19"/>
<Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L
8,1.5" HorizontalAlignment="Center" Stroke="{StaticResource
Expander.Static.Arrow.Stroke}" SnapsToDevicePixels="false"
StrokeThickness="2" VerticalAlignment="Center"/>
</Grid>
<ContentPresenter HorizontalAlignment="Center"
Margin="0,4,0,0" RecognizesAccessKey="True" Grid.Row="1"
SnapsToDevicePixels="True" VerticalAlignment="Top"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Data" TargetName="arrow"
Value="M 1,4.5 L 4.5,1 L 8,4.5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
<Setter Property="StrokeThickness"
TargetName="circle" Value="1.5"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Stroke" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
<Setter Property="Fill" TargetName="circle"
Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
<Setter Property="Stroke" TargetName="arrow"
Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderStyle1" TargetType="{x:Type Expander}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static
SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="
{TemplateBinding BorderThickness}" CornerRadius="3"
SnapsToDevicePixels="true">
<DockPanel>
<ToggleButton x:Name="HeaderSite"
ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding
Header}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
DockPanel.Dock="Top" FontStretch="{TemplateBinding FontStretch}"
Foreground="{TemplateBinding Foreground}" FocusVisualStyle="{StaticResource
ExpanderHeaderFocusVisual}" FontStyle="{TemplateBinding FontStyle}"
FontFamily="{TemplateBinding FontFamily}" FontWeight="{TemplateBinding
FontWeight}" FontSize="{TemplateBinding FontSize}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource
TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="
{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ContentPresenter x:Name="ExpandSite"
DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="
{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding
Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Visibility="Collapsed"/>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter Property="Visibility"
TargetName="ExpandSite" Value="Visible"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Right">
<Setter Property="DockPanel.Dock"
TargetName="ExpandSite" Value="Right"/>
<Setter Property="DockPanel.Dock"
TargetName="HeaderSite" Value="Left"/>
<Setter Property="Style" TargetName="HeaderSite"
Value="{StaticResource ExpanderRightHeaderStyle}"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Up">
<Setter Property="DockPanel.Dock"
TargetName="ExpandSite" Value="Top"/>
<Setter Property="DockPanel.Dock"
TargetName="HeaderSite" Value="Bottom"/>
<Setter Property="Style" TargetName="HeaderSite"
Value="{StaticResource ExpanderUpHeaderStyle}"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Left">
<Setter Property="DockPanel.Dock"
TargetName="ExpandSite" Value="Left"/>
<Setter Property="DockPanel.Dock"
TargetName="HeaderSite" Value="Right"/>
<Setter Property="Style" TargetName="HeaderSite"
Value="{StaticResource ExpanderLeftHeaderStyle}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="
{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Frame Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the Frame control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
Frame Parts
The following table lists the named parts for the Frame control.
Frame States
The following table lists the visual states for the Frame control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style x:Key="FrameButtonStyle"
TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Command"
Value="NavigationCommands.BrowseBack" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].
(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Arrow"
Storyboard.TargetProperty="
(Shape.Fill).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse x:Name="Ellipse"
StrokeThickness="1"
Width="16"
Height="16">
<Ellipse.Stroke>
<SolidColorBrush Color="{DynamicResource NavButtonFrameColor}"
/>
</Ellipse.Stroke>
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Path x:Name="Arrow"
Margin="0,0,2,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 4 0 L 0 4 L 4 8 Z" >
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}"/>
</Path.Fill>
</Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Command"
Value="{x:Static NavigationCommands.BrowseForward}">
<Setter TargetName="Arrow"
Property="Data"
Value="M 0 0 L 4 4 L 0 8 z" />
<Setter TargetName="Arrow"
Property="Margin"
Value="2,0,0,0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="FrameMenu"
TargetType="{x:Type Menu}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="KeyboardNavigation.TabNavigation"
Value="None" />
<Setter Property="IsMainMenu"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Menu}">
<DockPanel IsItemsHost="true" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="FrameHeaderMenuItem"
TargetType="{x:Type MenuItem}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Grid>
<Popup x:Name="PART_Popup"
Placement="Bottom"
VerticalOffset="2"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Fade">
<Border x:Name="SubMenuBorder"
BorderThickness="1"
Background="{DynamicResource MenuPopupBrush}">
<Border.BorderBrush>
<SolidColorBrush Color="{StaticResource BorderMediumColor}"
/>
</Border.BorderBrush>
<StackPanel IsItemsHost="true"
Margin="2"
KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.DirectionalNavigation="Cycle"
/>
</Border>
</Popup>
<Grid x:Name="Panel"
Width="24"
Background="Transparent"
HorizontalAlignment="Right">
<Border Visibility="Hidden"
x:Name="HighlightBorder"
BorderThickness="1"
CornerRadius="2">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}" />
<GradientStop Color="{DynamicResource
ControlMouseOverColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<Path x:Name="Arrow"
SnapsToDevicePixels="false"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="0,2,4,0"
StrokeLineJoin="Round"
Data="M 0 0 L 4 4 L 8 0 Z">
<Path.Stroke>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Stroke>
</Path>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted"
Value="true">
<Setter TargetName="HighlightBorder"
Property="Visibility"
Value="Visible" />
</Trigger>
<Trigger Property="IsSubmenuOpen"
Value="true">
<Setter TargetName="HighlightBorder"
Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
BorderDarkColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
BorderMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Background"
TargetName="HighlightBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource
ControlPressedColor}"
Offset="0.984" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled"
Value="false">
<Setter TargetName="Arrow"
Property="Fill">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource
DisabledForegroundColor}" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="FrameSubmenuItem"
TargetType="{x:Type MenuItem}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Header"
Value="{Binding (JournalEntry.Name)}" />
<Setter Property="Command"
Value="NavigationCommands.NavigateJournal" />
<Setter Property="CommandTarget"
Value="{Binding TemplatedParent,
RelativeSource={RelativeSource AncestorType={x:Type Menu}}}" />
<Setter Property="CommandParameter"
Value="{Binding RelativeSource={RelativeSource Self}}" />
<Setter Property="JournalEntryUnifiedViewConverter.JournalEntryPosition"
Value="{Binding
(JournalEntryUnifiedViewConverter.JournalEntryPosition)}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border BorderThickness="1"
Name="Border">
<Grid x:Name="Panel"
Background="Transparent"
SnapsToDevicePixels="true"
Height="35"
Width="250">
<Path x:Name="Glyph"
SnapsToDevicePixels="false"
Margin="7,5"
Width="10"
Height="10"
HorizontalAlignment="Left"
StrokeStartLineCap="Triangle"
StrokeEndLineCap="Triangle"
StrokeThickness="2">
<Path.Stroke>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Stroke>
</Path>
<ContentPresenter ContentSource="Header"
Margin="24,5,50,5" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger
Property="JournalEntryUnifiedViewConverter.JournalEntryPosition"
Value="Current">
<Setter TargetName="Glyph"
Property="Data"
Value="M 0,5 L 2.5,8 L 7,3 " />
</Trigger>
<Trigger Property="IsHighlighted"
Value="true">
<Setter Property="Background"
TargetName="Border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="Transparent"
Offset="0" />
<GradientStop Color="{DynamicResource
ControlMouseOverColor}"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush"
TargetName="Border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource BorderMediumColor}"
Offset="0" />
<GradientStop Color="Transparent"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted"
Value="true" />
<Condition
Property="JournalEntryUnifiedViewConverter.JournalEntryPosition"
Value="Forward" />
</MultiTrigger.Conditions>
<Setter TargetName="Glyph"
Property="Data"
Value="M 3 1 L 7 5 L 3 9 z" />
<Setter TargetName="Glyph"
Property="Stroke"
Value="{x:Null}" />
<Setter TargetName="Glyph"
Property="Fill">
<Setter.Value>
<SolidColorBrush Color="{StaticResource GlyphColor}" />
</Setter.Value>
</Setter>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted"
Value="true" />
<Condition
Property="JournalEntryUnifiedViewConverter.JournalEntryPosition"
Value="Back" />
</MultiTrigger.Conditions>
<Setter TargetName="Glyph"
Property="Data"
Value="M 7 1 L 3 5 L 7 9 z" />
<Setter TargetName="Glyph"
Property="Stroke"
Value="{x:Null}" />
<Setter TargetName="Glyph"
Property="Fill">
<Setter.Value>
<SolidColorBrush Color="{StaticResource GlyphColor}" />
</Setter.Value>
</Setter>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<JournalEntryUnifiedViewConverter x:Key="JournalEntryUnifiedViewConverter"
/>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Menu x:Name="NavMenu"
Grid.ColumnSpan="3"
Height="16"
Margin="1,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource FrameMenu}">
<MenuItem Style="{StaticResource FrameHeaderMenuItem}"
ItemContainerStyle="{StaticResource
FrameSubmenuItem}"
IsSubmenuOpen="{Binding (MenuItem.IsSubmenuOpen),
Mode=TwoWay, RelativeSource={RelativeSource
TemplatedParent}}">
<MenuItem.ItemsSource>
<MultiBinding Converter="{StaticResource
JournalEntryUnifiedViewConverter}">
<Binding RelativeSource="{RelativeSource
TemplatedParent}"
Path="BackStack" />
<Binding RelativeSource="{RelativeSource
TemplatedParent}"
Path="ForwardStack" />
</MultiBinding>
</MenuItem.ItemsSource>
</MenuItem>
</Menu>
<Path Grid.Column="0"
SnapsToDevicePixels="false"
IsHitTestVisible="false"
Margin="2,1.5,0,1.5"
Grid.ColumnSpan="3"
StrokeThickness="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Data="M15,14 Q18,12.9 20.9,14 A8.3,8.3,0,0,0,35.7,8.7
A8.3,8.3,0,0,0,
25.2,0.6 Q18, 3.3 10.8,0.6 A8.3,8.3,0,0,0,0.3,8.7
A8.3,8.3,0,0,0,15,14 z"
Stroke="{x:Null}">
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlDarkColor}"
Offset="1" />
</LinearGradientBrush>
</Path.Fill>
</Path>
<Button Style="{StaticResource FrameButtonStyle}"
Command="NavigationCommands.BrowseBack"
Content="M 4 0 L 0 4 L 4 8 Z"
Margin="2.7,1.5,1.3,1.5"
Grid.Column="0" />
<Button Style="{StaticResource FrameButtonStyle}"
Command="NavigationCommands.BrowseForward"
Content="M 4 0 L 0 4 L 4 8 Z"
Margin="1.3,1.5,0,1.5"
Grid.Column="1" />
</Grid>
</Border>
<Border BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}"
/>
</Border.BorderBrush>
<ContentPresenter x:Name="PART_FrameCP"
Height="458"
Width="640" />
</Border>
</DockPanel>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="CanGoForward"
Value="false" />
<Condition Property="CanGoBack"
Value="false" />
</MultiTrigger.Conditions>
<Setter TargetName="NavMenu"
Property="IsEnabled"
Value="false" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The preceding example uses one or more of the following resources.
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
GroupBox Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the GroupBox control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
GroupBox Parts
The GroupBox control does not have any named parts.
GroupBox States
The following table lists the visual states for the GroupBox control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style TargetType="GroupBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0"
BorderThickness="1"
CornerRadius="2,2,0,0">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Margin="4"
ContentSource="Header"
RecognizesAccessKey="True" />
</Border>
<Border Grid.Row="1"
BorderThickness="1,0,1,1"
CornerRadius="0,0,2,2">
<Border.BorderBrush>
<SolidColorBrush Color="{StaticResource BorderMediumColor}" />
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
MappingMode="RelativeToBoundingBox"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource
ContentAreaColorLight}"
Offset="0" />
<GradientStop Color="{DynamicResource ContentAreaColorDark}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Margin="4" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Label Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the Label control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
Label Parts
The Label control does not have any named parts.
Label States
The following table lists the visual states for the Label control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ListBox Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ListBox control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
ListBox Parts
The ListBox control does not have any named parts.
When you create a ControlTemplate for a ListBox, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
ListBox; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is not
the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
ListBox States
The following table lists the visual states for the ListBox control.
InvalidUnfocused ValidationStates The control is not valid and does not have focus.
ListBoxItem Parts
The ListBoxItem control does not have any named parts.
ListBoxItem States
The following table lists the visual states for the ListBox control.
SelectedUnfocused SelectionStates The item is selected, but does not have focus.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
</Setter>
</Trigger>
<Trigger Property="IsGrouping"
Value="true">
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ListView Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ListView control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
ListView Parts
The ListView control does not have any named parts.
When you create a ControlTemplate for a ListView, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
ListView; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is
not the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
ListView States
The following table lists the visual states for the ListView control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
ListViewItem Parts
The ListViewItem control does not have any named parts.
ListViewItem States
The following table lists the states for the ListViewItem control.
VisualState Name VisualStateGroup Description
Name
SelectedUnfocused SelectionStates The item is selected, but does not have focus.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<ScrollContentPresenter Name="PART_ScrollContentPresenter"
KeyboardNavigation.DirectionalNavigation="Local"
CanContentScroll="True"
CanHorizontallyScroll="False"
CanVerticallyScroll="False" />
</DockPanel>
<ScrollBar Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Value="{TemplateBinding HorizontalOffset}"
Visibility="{TemplateBinding
ComputedHorizontalScrollBarVisibility}" />
<ScrollBar Name="PART_VerticalScrollBar"
Grid.Column="1"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{TemplateBinding VerticalOffset}"
Visibility="{TemplateBinding
ComputedVerticalScrollBarVisibility}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="GridViewColumnHeaderGripper"
TargetType="Thumb">
<Setter Property="Width"
Value="18" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Padding="{TemplateBinding Padding}"
Background="Transparent">
<Rectangle HorizontalAlignment="Center"
Width="1"
Fill="{TemplateBinding Background}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
Storyboard.TargetName="HeaderBorder">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="HeaderBorder"
BorderThickness="0,1,0,1"
Padding="2,0,2,0">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter x:Name="HeaderContent"
Margin="0,0,0,1"
RecognizesAccessKey="True"
VerticalAlignment="{TemplateBinding
VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding
SnapsToDevicePixels}"/>
</Border>
<Thumb x:Name="PART_HeaderGripper"
HorizontalAlignment="Right"
Margin="0,0,-9,0"
Style="{StaticResource GridViewColumnHeaderGripper}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Role"
Value="Floating">
<Setter Property="Opacity"
Value="0.7" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Canvas Name="PART_FloatingHeaderCanvas">
<Rectangle Fill="#60000000"
Width="{TemplateBinding ActualWidth}"
Height="{TemplateBinding ActualHeight}" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="Role"
Value="Padding">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Border Name="HeaderBorder"
BorderThickness="0,1,0,1">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlLightColor}"
/>
</Border.Background>
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Menu Styles and Templates
Article • 06/02/2023
This topic describes the styles and templates for the Menu control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
Menu Parts
The Menu control does not have any named parts.
When you create a ControlTemplate for a Menu, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
Menu; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is not
the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
Menu States
The following table lists the visual states for the Menu control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
Menu ControlTemplate
The following example is a copy of the default template for a Window control:
XAML
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="Menu.Static.Background" Color="#FFF0F0F0"/>
<Style x:Key="MenuStyle1" TargetType="{x:Type Menu}">
<Setter Property="Background" Value="{StaticResource
Menu.Static.Background}"/>
<Setter Property="FontFamily" Value="{DynamicResource {x:Static
SystemFonts.MenuFontFamilyKey}}"/>
<Setter Property="FontSize" Value="{DynamicResource {x:Static
SystemFonts.MenuFontSizeKey}}"/>
<Setter Property="FontStyle" Value="{DynamicResource {x:Static
SystemFonts.MenuFontStyleKey}}"/>
<Setter Property="FontWeight" Value="{DynamicResource {x:Static
SystemFonts.MenuFontWeightKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static
SystemColors.MenuTextBrushKey}}"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Menu}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="
{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ItemsPresenter SnapsToDevicePixels="
{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
MenuItem Parts
The following table lists the named parts for the Menu control.
When you create a ControlTemplate for a MenuItem, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
MenuItem; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is
not the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
MenuItem States
The following table lists the visual states for the MenuItem control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
MenuItem ControlTemplate
The following example is a copy of the default template for a Window control:
XAML
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
NavigationWindow Styles and
Templates
Article • 02/06/2023
This topic describes the styles and templates for the NavigationWindow control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
NavigationWindow Parts
The following table lists the named parts for the NavigationWindow control.
NavigationWindow States
The following table lists the visual states for the NavigationWindow control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style x:Key="NavWinButtonStyle"
TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Command"
Value="NavigationCommands.BrowseBack" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Arrow"
Storyboard.TargetProperty="
(Shape.Fill).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse x:Name="Ellipse"
StrokeThickness="1"
Width="24"
Height="24">
<Ellipse.Stroke>
<SolidColorBrush Color="{DynamicResource NavButtonFrameColor}"
/>
</Ellipse.Stroke>
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Path x:Name="Arrow"
Margin="0,0,3,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 6 0 L 0 6 L 6 12 Z">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Fill>
</Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Command"
Value="{x:Static NavigationCommands.BrowseForward}">
<Setter TargetName="Arrow"
Property="Data"
Value="M 0 0 L 6 6 L 0 12 z" />
<Setter TargetName="Arrow"
Property="Margin"
Value="3,0,0,0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Border Visibility="Hidden"
x:Name="HighlightBorder"
BorderThickness="1"
CornerRadius="2">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}" />
<GradientStop Color="{DynamicResource
ControlMouseOverColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<Path x:Name="Arrow"
SnapsToDevicePixels="false"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="0,2,4,0"
StrokeLineJoin="Round"
Data="M 0 0 L 4 4 L 8 0 Z">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Fill>
</Path>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted"
Value="true">
<Setter TargetName="HighlightBorder"
Property="Visibility"
Value="Visible" />
</Trigger>
<Trigger Property="IsSubmenuOpen"
Value="true">
<Setter TargetName="HighlightBorder"
Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
BorderDarkColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
BorderMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Background"
TargetName="HighlightBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource
ControlPressedColor}"
Offset="0.984" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="NavWinSubmenuItem"
TargetType="{x:Type MenuItem}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Header"
Value="{Binding (JournalEntry.Name)}" />
<Setter Property="Command"
Value="NavigationCommands.NavigateJournal" />
<Setter Property="CommandTarget"
Value="{Binding TemplatedParent, RelativeSource={RelativeSource
AncestorType={x:Type Menu}}}" />
<Setter Property="CommandParameter"
Value="{Binding RelativeSource={RelativeSource Self}}" />
<Setter Property="JournalEntryUnifiedViewConverter.JournalEntryPosition"
Value="{Binding
(JournalEntryUnifiedViewConverter.JournalEntryPosition)}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border Name="Border"
BorderThickness="1">
<Grid x:Name="Panel"
Background="Transparent"
SnapsToDevicePixels="true"
Height="35"
Width="250">
<Path x:Name="Glyph"
SnapsToDevicePixels="false"
Margin="7,5"
Width="10"
Height="10"
HorizontalAlignment="Left"
StrokeStartLineCap="Triangle"
StrokeEndLineCap="Triangle"
StrokeThickness="2">
<Path.Stroke>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Stroke>
</Path>
<ContentPresenter ContentSource="Header"
Margin="24,5,50,5" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Value="Current"
Property="JournalEntryUnifiedViewConverter.JournalEntryPosition">
<Setter TargetName="Glyph"
Property="Data"
Value="M 0,5 L 2.5,8 L 7,3 " />
</Trigger>
<Trigger Property="IsHighlighted"
Value="true">
<Setter Property="Background"
TargetName="Border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="Transparent"
Offset="0" />
<GradientStop Color="{DynamicResource
ControlMouseOverColor}"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush"
TargetName="Border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource BorderMediumColor}"
Offset="0" />
<GradientStop Color="Transparent"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted"
Value="true" />
<Condition Value="Forward"
Property="JournalEntryUnifiedViewConverter.JournalEntryPosition" />
</MultiTrigger.Conditions>
<Setter TargetName="Glyph"
Property="Data"
Value="M 3 1 L 7 5 L 3 9 z" />
<Setter TargetName="Glyph"
Property="Fill">
<Setter.Value>
<SolidColorBrush Color="{StaticResource GlyphColor}" />
</Setter.Value>
</Setter>
<Setter TargetName="Glyph"
Property="Stroke"
Value="{x:Null}" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted"
Value="true" />
<Condition Value="Back"
Property="JournalEntryUnifiedViewConverter.JournalEntryPosition" />
</MultiTrigger.Conditions>
<Setter TargetName="Glyph"
Property="Data"
Value="M 7 1 L 3 5 L 7 9 z" />
<Setter TargetName="Glyph"
Property="Fill">
<Setter.Value>
<SolidColorBrush Color="{StaticResource GlyphColor}" />
</Setter.Value>
</Setter>
<Setter TargetName="Glyph"
Property="Stroke"
Value="{x:Null}" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<JournalEntryUnifiedViewConverter x:Key="JournalEntryUnifiedViewConverter"
/>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Menu x:Name="NavMenu"
Grid.ColumnSpan="3"
Height="20"
Margin="1,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource NavWinMenu}">
<MenuItem Style="{StaticResource NavWinHeaderMenuItem}"
ItemContainerStyle="{StaticResource
NavWinSubmenuItem}"
IsSubmenuOpen="{Binding (MenuItem.IsSubmenuOpen),
Mode=TwoWay, RelativeSource={RelativeSource
TemplatedParent}}">
<MenuItem.ItemsSource>
<MultiBinding Converter="{StaticResource
JournalEntryUnifiedViewConverter}">
<Binding RelativeSource="{RelativeSource
TemplatedParent}"
Path="BackStack" />
<Binding RelativeSource="{RelativeSource
TemplatedParent}"
Path="ForwardStack" />
</MultiBinding>
</MenuItem.ItemsSource>
</MenuItem>
</Menu>
<Path Grid.Column="0"
SnapsToDevicePixels="false"
IsHitTestVisible="false"
Margin="2,1.5,0,1.5"
Grid.ColumnSpan="3"
StrokeThickness="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Data="M22.5767,21.035 Q27,19.37
31.424,21.035 A12.5,12.5,0,0,0,53.5,13
A12.5,12.5,0,0,0,37.765,0.926
Q27,4.93 16.235,0.926
A12.5,12.5,0,0,0,0.5,13
A12.5,12.5,0,0,0,22.5767,21.035 z">
<Path.Stroke>
<SolidColorBrush Color="{DynamicResource
BorderMediumColor}" />
</Path.Stroke>
<Path.Fill>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="0" />
<ResizeGrip x:Name="WindowResizeGrip"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Visibility="Collapsed"
IsTabStop="false" />
</Grid>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="ResizeMode"
Value="CanResizeWithGrip">
<Setter TargetName="WindowResizeGrip"
Property="Visibility"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The preceding example uses one or more of the following resources.
XAML
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
PasswordBox Styles and Templates
Article • 07/26/2022
This topic describes the styles and templates for the PasswordBox control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
PasswordBox Parts
The following table lists the named parts for the PasswordBox control.
PasswordBox States
The following table lists the visual states for the PasswordBox control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ProgressBar Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ProgressBar control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
ProgressBar Parts
The following table lists the named parts for the ProgressBar control.
PART_Track FrameworkElement The object that defines the path of the progress indicator.
ProgressBar States
The following table lists the visual states for the ProgressBar control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
Storyboard.TargetName="PART_Indicator"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush>Transparent</SolidColorBrush>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="PART_Track"
CornerRadius="2"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}"
/>
</Border.BorderBrush>
</Border>
<Border x:Name="PART_Indicator"
CornerRadius="2"
BorderThickness="1"
HorizontalAlignment="Left"
Background="{TemplateBinding Foreground}"
Margin="0,-1,0,1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
BorderMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Grid ClipToBounds="True"
x:Name="Animation">
<Rectangle x:Name="PART_GlowRect"
Width="100"
HorizontalAlignment="Left"
Fill="{DynamicResource
ProgressBarIndicatorAnimatedFill}"
Margin="-100,0,0,0" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlDarkColor}"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
RadioButton Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the RadioButton control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
RadioButton Parts
The RadioButton control does not have any named parts.
RadioButton States
The following table lists the visual states for the RadioButton control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
Storyboard.TargetName="CheckMark">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="4,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
RecognizesAccessKey="True" />
</BulletDecorator>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
RepeatButton Styles and Templates
Article • 07/26/2022
This topic describes the styles and templates for the RepeatButton control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
RepeatButton Parts
The RepeatButton control does not have any named parts.
RepeatButton States
The following table lists the visual states for the RepeatButton control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
<Style x:Key="ScrollBarLineButton"
TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border x:Name="Border"
Margin="1"
CornerRadius="2"
BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderMediumColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}"/>
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Arrow"
Storyboard.TargetProperty="
(Shape.Fill).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path x:Name="Arrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="{Binding Content,
RelativeSource={RelativeSource TemplatedParent}}" >
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}"/>
</Path.Fill>
</Path>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ScrollBar Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ScrollBar control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
ScrollBar Parts
The following table lists the named parts for the ScrollBar control.
PART_Track Track The container for the element that indicates the position of the ScrollBar.
ScrollBar States
The following table lists the visual states for the ScrollBar control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style x:Key="ScrollBarLineButton"
TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border x:Name="Border"
Margin="1"
CornerRadius="2"
BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderMediumColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}"/>
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Arrow"
Storyboard.TargetProperty="
(Shape.Fill).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path x:Name="Arrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="{Binding Content,
RelativeSource={RelativeSource TemplatedParent}}" >
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}"/>
</Path.Fill>
</Path>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarPageButton"
TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="IsTabStop"
Value="false" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarThumb"
TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="IsTabStop"
Value="false" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="VerticalScrollBar"
TargetType="{x:Type ScrollBar}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="18" />
<RowDefinition Height="0.00001*" />
<RowDefinition MaxHeight="18" />
</Grid.RowDefinitions>
<Border Grid.RowSpan="3"
CornerRadius="2"
Background="#F0F0F0" />
<RepeatButton Grid.Row="0"
Style="{StaticResource ScrollBarLineButton}"
Height="18"
Command="ScrollBar.LineUpCommand"
Content="M 0 4 L 8 4 L 4 0 Z" />
<Track x:Name="PART_Track"
Grid.Row="1"
IsDirectionReversed="true">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageUpCommand" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"
Margin="1,0,1,0">
<Thumb.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Thumb.BorderBrush>
<Thumb.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Thumb.Background>
</Thumb>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageDownCommand" />
</Track.IncreaseRepeatButton>
</Track>
<RepeatButton Grid.Row="2"
Style="{StaticResource ScrollBarLineButton}"
Height="18"
Command="ScrollBar.LineDownCommand"
Content="M 0 0 L 4 4 L 8 0 Z" />
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="HorizontalScrollBar"
TargetType="{x:Type ScrollBar}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="18" />
<ColumnDefinition Width="0.00001*" />
<ColumnDefinition MaxWidth="18" />
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="3"
CornerRadius="2"
Background="#F0F0F0" />
<RepeatButton Grid.Column="0"
Style="{StaticResource ScrollBarLineButton}"
Width="18"
Command="ScrollBar.LineLeftCommand"
Content="M 4 0 L 4 8 L 0 4 Z" />
<Track x:Name="PART_Track"
Grid.Column="1"
IsDirectionReversed="False">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageLeftCommand" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"
Margin="0,1,0,1">
<Thumb.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Thumb.BorderBrush>
<Thumb.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Thumb.Background>
</Thumb>
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource ScrollBarPageButton}"
Command="ScrollBar.PageRightCommand" />
</Track.IncreaseRepeatButton>
</Track>
<RepeatButton Grid.Column="2"
Style="{StaticResource ScrollBarLineButton}"
Width="18"
Command="ScrollBar.LineRightCommand"
Content="M 0 0 L 4 4 L 0 8 Z" />
</Grid>
</ControlTemplate>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ScrollViewer Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ScrollViewer control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
ScrollViewer Parts
The following table lists the named parts for the ScrollViewer control.
ScrollViewer States
The following table lists the visual states for the ScrollViewer control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
<Style x:Key="LeftScrollViewer"
TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Grid.Column="1"
BorderThickness="0,1,1,1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}"
/>
</Border.BorderBrush>
<ScrollContentPresenter CanContentScroll="{TemplateBinding
CanContentScroll}" />
</Border>
<ScrollBar x:Name="PART_VerticalScrollBar"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding
ComputedVerticalScrollBarVisibility}"/>
<ScrollBar x:Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Grid.Column="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding
ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Slider Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the Slider control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
Slider Parts
The following table lists the named parts for the Slider control.
PART_Track Track The container for the element that indicates the
position of the Slider.
Slider States
The following table lists the visual states for the Slider control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style x:Key="SliderButtonStyle"
TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="IsTabStop"
Value="false" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SliderThumbStyle"
TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Height"
Value="14" />
<Setter Property="Width"
Value="14" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Ellipse x:Name="Ellipse"
StrokeThickness="1">
<Ellipse.Stroke>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Ellipse.Stroke>
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
<GradientStop Color="{DynamicResource ControlLightColor}" />
</LinearGradientBrush>
</Ellipse.Fill>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Ellipse">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Ellipse">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Ellipse">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Ellipse>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Border x:Name="TrackBackground"
Margin="0"
CornerRadius="2"
Width="4"
Grid.Column="1"
BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="1,0"
StartPoint="0.25,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource SliderTrackDarkColor}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
<Track Grid.Column="1"
x:Name="PART_Track">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource SliderButtonStyle}"
Command="Slider.DecreaseLarge" />
</Track.DecreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource SliderThumbStyle}" />
</Track.Thumb>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource SliderButtonStyle}"
Command="Slider.IncreaseLarge" />
</Track.IncreaseRepeatButton>
</Track>
<TickBar x:Name="BottomTick"
SnapsToDevicePixels="True"
Grid.Column="2"
Fill="{TemplateBinding Foreground}"
Placement="Right"
Width="4"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="TickPlacement"
Value="TopLeft">
<Setter TargetName="TopTick"
Property="Visibility"
Value="Visible" />
</Trigger>
<Trigger Property="TickPlacement"
Value="BottomRight">
<Setter TargetName="BottomTick"
Property="Visibility"
Value="Visible" />
</Trigger>
<Trigger Property="TickPlacement"
Value="Both">
<Setter TargetName="TopTick"
Property="Visibility"
Value="Visible" />
<Setter TargetName="BottomTick"
Property="Visibility"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
StatusBar Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the StatusBar control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
StatusBar Parts
The StatusBar control does not have any named parts.
StatusBar States
The following table lists the visual states for the StatusBar control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
StatusBarItem Parts
The StatusBarItem control does not have any named parts.
StatusBarItem States
The following table lists the visual states for the StatusBarItem control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
VisualState VisualStateGroup Description
Name Name
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
TabControl Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the TabControl control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
TabControl Parts
The following table lists the named parts for the TabControl control.
When you create a ControlTemplate for a TabControl, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
TabControl; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is
not the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
TabControl States
The following table lists the visual states for the TabControl control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
TabItem States
The following table lists the visual states for the TabItem control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
Storyboard.TargetName="Border">
<EasingThicknessKeyFrame KeyTime="0"
Value="1,1,1,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Border.BorderBrush).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledBorderLightColor}"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border"
Margin="0,0,-4,0"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}"
/>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource
ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"
RecognizesAccessKey="True" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Panel.ZIndex"
Value="100" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
TextBox Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the TextBox control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
TextBox Parts
The following table lists the named parts for the TextBox control.
TextBox States
The following table lists the visual states for the TextBox control.
ReadOnly CommonStates The user cannot change the text in the TextBox.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Thumb Styles and Templates
Article • 08/18/2022
This topic describes the styles and templates for the Thumb control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
Thumb Parts
The Thumb control does not have any named parts.
Thumb States
The following table lists the visual states for the Thumb control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style x:Key="SliderThumbStyle"
TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Height"
Value="14" />
<Setter Property="Width"
Value="14" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Ellipse x:Name="Ellipse"
StrokeThickness="1">
<Ellipse.Stroke>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Ellipse.Stroke>
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
<GradientStop Color="{DynamicResource ControlLightColor}" />
</LinearGradientBrush>
</Ellipse.Fill>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Ellipse">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Ellipse">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Ellipse">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Ellipse>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
For the complete sample, see Styling with ControlTemplates Sample .
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ToggleButton Styles and Templates
Article • 08/18/2022
This topic describes the styles and templates for the ToggleButton control. You can
modify the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
ToggleButton Parts
The ToggleButton control does not have any named parts.
ToggleButton States
The following table lists the visual states for the ToggleButton control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
If the Indeterminate visual state does not exist in your control template, then the
Unchecked visual state will be used as default visual state.
XAML
<ControlTemplate x:Key="ComboBoxToggleButton"
TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed" />
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Shape.Fill).
(SolidColorBrush.Color)"
Storyboard.TargetName="Arrow">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border"
Grid.ColumnSpan="2"
CornerRadius="2"
BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0,1"
StartPoint="0,0">
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource BorderDarkColor}"
Offset="1" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
</Border>
<Border Grid.Column="0"
CornerRadius="2,0,0,2"
Margin="1" >
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlLightColor}"/>
</Border.Background>
</Border>
<Path x:Name="Arrow"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z" >
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}"/>
</Path.Fill>
</Path>
</Grid>
</ControlTemplate>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ToolBar Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ToolBar control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
ToolBar Parts
The following table lists the named parts for the ToolBar control.
When you create a ControlTemplate for a ToolBar, your template might contain an
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
ToolBar; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is
not the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
ToolBar States
The following table lists the visual states for the ToolBar control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style x:Key="ToolBarButtonBaseStyle"
TargetType="{x:Type ButtonBase}">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border x:Name="Border"
BorderThickness="1">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource BorderLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource BorderMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ToolBarThumbStyle"
TargetType="{x:Type Thumb}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Cursor"
Value="SizeAll" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="Transparent"
SnapsToDevicePixels="True">
<Rectangle Margin="0,2">
<Rectangle.Fill>
<DrawingBrush Viewport="0,0,4,4"
ViewportUnits="Absolute"
Viewbox="0,0,8,8"
ViewboxUnits="Absolute"
TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="#AAA"
Geometry="M 4 4 L 4 8 L 8 8 L 8 4 z" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ToolBarOverflowButtonStyle"
TargetType="{x:Type ToggleButton}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="Border"
CornerRadius="0,3,3,0"
SnapsToDevicePixels="true">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#00000000"
Offset="0" />
<GradientStop Offset="1" />
</LinearGradientBrush>
</Border.Background>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames
Storyboard.TargetName="Border"
Storyboard.TargetProperty="
(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
DisabledBorderLightColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Path x:Name="Arrow"
Fill="Black"
VerticalAlignment="Bottom"
Margin="2,3"
Data="M -0.5 3 L 5.5 3 L 2.5 6 Z" />
<ContentPresenter />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FFF"
Offset="0.0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<DockPanel>
<ToggleButton DockPanel.Dock="Right"
IsEnabled="{TemplateBinding HasOverflowItems}"
Style="{StaticResource
ToolBarOverflowButtonStyle}"
ClickMode="Press"
IsChecked="{Binding IsOverflowOpen, Mode=TwoWay,
RelativeSource={RelativeSource TemplatedParent}}">
<Popup x:Name="OverflowPopup"
AllowsTransparency="true"
Placement="Bottom"
StaysOpen="false"
Focusable="false"
PopupAnimation="Slide"
IsOpen="{Binding IsOverflowOpen,
RelativeSource={RelativeSource TemplatedParent}}">
<Border x:Name="DropDownBorder"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource
BorderMediumColor}" />
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource
ControlLightColor}" />
<GradientStop Color="{DynamicResource
ControlMediumColor}"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ToolBarOverflowPanel x:Name="PART_ToolBarOverflowPanel"
Margin="2"
WrapWidth="200"
Focusable="true"
FocusVisualStyle="{x:Null}"
KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</Border>
</Popup>
</ToggleButton>
<Thumb x:Name="ToolBarThumb"
Style="{StaticResource ToolBarThumbStyle}"
Width="10" />
<ToolBarPanel x:Name="PART_ToolBarPanel"
IsItemsHost="true"
Margin="0,1,2,2" />
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsOverflowOpen"
Value="true">
<Setter TargetName="ToolBarThumb"
Property="IsEnabled"
Value="false" />
</Trigger>
<Trigger Property="ToolBarTray.IsLocked"
Value="true">
<Setter TargetName="ToolBarThumb"
Property="Visibility"
Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
For the complete sample, see Styling with ControlTemplates Sample .
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
ToolTip Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the ToolTip control. You can modify the
default ControlTemplate to give the control a unique appearance. For more information,
see Create a template for a control.
ToolTip Parts
The ToolTip control does not have any named parts.
ToolTip States
The following table lists the visual states for the ToolTip control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
</Border.Background>
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<ContentPresenter Margin="4"
HorizontalAlignment="Left"
VerticalAlignment="Top" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow"
Value="true">
<Setter TargetName="Border"
Property="CornerRadius"
Value="4" />
<Setter TargetName="Border"
Property="SnapsToDevicePixels"
Value="true" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
TreeView Styles and Templates
Article • 02/06/2023
This topic describes the styles and templates for the TreeView control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
TreeView Parts
The TreeView control does not have any named parts.
When you create a ControlTemplate for an TreeView, your template might contain a
ItemsPresenter within a ScrollViewer. (The ItemsPresenter displays each item in the
TreeView; the ScrollViewer enables scrolling within the control). If the ItemsPresenter is
not the direct child of the ScrollViewer, you must give the ItemsPresenter the name,
ItemsPresenter .
TreeView States
The following table lists the visual states for the TreeView control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
TreeViewItem Parts
The following table lists the named parts for the TreeViewItem control.
PART_Header FrameworkElement A visual element that contains that header content of the
TreeView control.
TreeViewItem States
The following table lists the visual states for TreeViewItem control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
XAML
<Style x:Key="ExpandCollapseToggleStyle"
TargetType="ToggleButton">
<Setter Property="Focusable"
Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid Width="15"
Height="13"
Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="
(UIElement.Visibility)"
Storyboard.TargetName="Collapsed">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="
(UIElement.Visibility)"
Storyboard.TargetName="Expanded">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path x:Name="Collapsed"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="1,1,1,1"
Data="M 4 0 L 8 4 L 4 8 Z">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Fill>
</Path>
<Path x:Name="Expanded"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="1,1,1,1"
Data="M 0 4 L 8 4 L 4 8 Z"
Visibility="Hidden">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Fill>
</Path>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TreeViewItemFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="0,0,0,0"
StrokeThickness="5"
Stroke="Black"
StrokeDashArray="1 2"
Opacity="0" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type TreeViewItem}"
TargetType="{x:Type TreeViewItem}">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="HorizontalContentAlignment"
Value="{Binding Path=HorizontalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="VerticalContentAlignment"
Value="{Binding Path=VerticalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Padding"
Value="1,0,0,0" />
<Setter Property="Foreground"
Value="{DynamicResource {x:Static
SystemColors.ControlTextBrushKey}}" />
<Setter Property="FocusVisualStyle"
Value="{StaticResource TreeViewItemFocusVisual}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19"
Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd"
Storyboard.TargetProperty="
(Panel.Background).
(SolidColorBrush.Color)"
>
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
SelectedBackgroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unselected" />
<VisualState x:Name="SelectedInactive">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd"
Storyboard.TargetProperty="
(Panel.Background).
(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource
SelectedUnfocusedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ExpansionStates">
<VisualState x:Name="Expanded">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="
(UIElement.Visibility)"
Storyboard.TargetName="ItemsHost">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{x:Static
Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ToggleButton x:Name="Expander"
Style="{StaticResource ExpandCollapseToggleStyle}"
ClickMode="Press"
IsChecked="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"/>
<Border x:Name="Bd"
Grid.Column="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}"/>
</Border>
<ItemsPresenter x:Name="ItemsHost"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems"
Value="false">
<Setter TargetName="Expander"
Property="Visibility"
Value="Hidden" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader"
Value="false" />
<Condition Property="Width"
Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header"
Property="MinWidth"
Value="75" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader"
Value="false" />
<Condition Property="Height"
Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header"
Property="MinHeight"
Value="19" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215,
0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush"
EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
StartPoint="0,0"
EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF"
Offset="0" />
<GradientStop Color="#600000FF"
Offset="0.4" />
<GradientStop Color="#600000FF"
Offset="0.6" />
<GradientStop Color="#000000FF"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
Window Styles and Templates
Article • 06/02/2023
This topic describes the styles and templates for the Window control. You can modify
the default ControlTemplate to give the control a unique appearance. For more
information, see Create a template for a control.
Window Parts
The Window control does not have any named parts.
Window States
The following table lists the visual states for the Window control.
Valid ValidationStates The control uses the Validation class and the
Validation.HasError attached property is false .
Window ControlTemplate
The following example is a slightly modified copy of the default template for a Window
control:
XAML
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ResourceDictionary>
See also
Style
ControlTemplate
Control Styles and Templates
Control Customization
Styling and Templating
Create a template for a control
UI Automation of a WPF Custom
Control
Article • 02/06/2023
The base Control class does not have a corresponding peer class. If you need a peer
class to correspond to a custom control that derives from Control, you should derive the
custom peer class from FrameworkElementAutomationPeer.
Security Considerations for Derived Peers
Automation peers must run in a partial-trust environment. Code in the
UIAutomationClient assembly is not configured to run in a partial-trust environment,
and automation peer code should not reference that assembly. Instead, you should use
the classes in the UIAutomationTypes assembly. For example, you should use the
AutomationElementIdentifiers class from the UIAutomationTypes assembly, which
corresponds to the AutomationElement class in the UIAutomationClient assembly. It is
safe to reference the UIAutomationTypes assembly in automation peer code.
Peer Navigation
After locating an automation peer, in-process code can navigate the peer tree by calling
the object's GetChildren and GetParent methods. Navigation among WPF elements
within a control is supported by the peer's implementation of the GetChildrenCore
method. The UI Automation system calls this method to build up a tree of subelements
contained within a control; for example, list items in a list box. The default
UIElementAutomationPeer.GetChildrenCore method traverses the visual tree of
elements to build the tree of automation peers. Custom controls override this method
to expose children elements to automation clients, returning the automation peers of
elements that convey information or allow user interaction.
When implementing a custom control, you must override the "Core" methods from the
base automation peer class that describe behavior unique and specific to your custom
control.
Override OnCreateAutomationPeer
Override the OnCreateAutomationPeer method for your custom control so that it
returns your provider object, which must derive directly or indirectly from
AutomationPeer.
Override GetPattern
Automation peers simplify some implementation aspects of server-side UI Automation
providers, but custom control automation peers must still handle pattern interfaces. Like
non-WPF providers, peers support control patterns by providing implementations of
interfaces in the System.Windows.Automation.Provider namespace, such as
IInvokeProvider. The control pattern interfaces can be implemented by the peer itself or
by another object. The peer's implementation of GetPattern returns the object that
supports the specified pattern. UI Automation code calls the GetPattern method and
specifies a PatternInterface enumeration value. Your override of GetPattern should
return the object that implements the specified pattern. If your control does not have a
custom implementation of a pattern, you can call the base type's implementation of
GetPattern to retrieve either its implementation or null if the pattern is not supported
for this control type. For example, a custom NumericUpDown control can be set to a
value within a range, so its UI Automation peer would implement the
IRangeValueProvider interface. The following example shows how the peer's GetPattern
method is overridden to respond to a PatternInterface.RangeValue value.
C#
A GetPattern method can also specify a subelement as a pattern provider. The following
code shows how ItemsControl transfers scroll pattern handling to the peer of its internal
ScrollViewer control.
C#
To specify a subelement for pattern handling, this code gets the subelement object,
creates a peer by using the CreatePeerForElement method, sets the EventsSource
property of the new peer to the current peer, and returns the new peer. Setting
EventsSource on a subelement prevents the subelement from appearing in the
automation peer tree and designates all events raised by the subelement as originating
from the control specified in EventsSource. The ScrollViewer control does not appear in
the automation tree, and scrolling events that it generates appear to originate from the
ItemsControl object.
C#
Your automation peer should provide appropriate default values for your control. Note
that XAML that references your control can override your peer implementations of core
methods by including AutomationProperties attributes. For example, the following
XAML creates a button that has two customized UI Automation properties.
XAML
<Button AutomationProperties.Name="Special"
AutomationProperties.HelpText="This is a special button."/>
C#
C#
For an example implementation, see the C# or Visual Basic source code that
implements and consumes a NumericUpDown custom control.
Raise Events
Automation clients can subscribe to automation events. Custom controls must report
changes to control state by calling the RaiseAutomationEvent method. Similarly, when a
property value changes, call the RaisePropertyChangedEvent method. The following
code shows how to get the peer object from within the control code and call a method
to raise an event. As an optimization, the code determines if there are any listeners for
this event type. Raising the event only when there are listeners avoids unnecessary
overhead and helps the control remain responsive.
C#
if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
NumericUpDownAutomationPeer peer =
UIElementAutomationPeer.FromElement(nudCtrl) as
NumericUpDownAutomationPeer;
if (peer != null)
{
peer.RaisePropertyChangedEvent(
RangeValuePatternIdentifiers.ValueProperty,
(double)oldValue,
(double)newValue);
}
}
See also
UI Automation Overview
Server-Side UI Automation Provider Implementation
NumericUpDown custom control (C#) on GitHub
NumericUpDown custom control (Visual Basic) on GitHub
Walkthroughs: Create a Custom
Animated Button
Article • 02/06/2023
As its name suggests, Windows Presentation Foundation (WPF) is great for making rich
presentation experiences for customers. These walkthroughs show you how to
customize the look and behavior of a button (including animations). This customization
is done using a style and template so that you can apply this custom button easily to
any buttons in your application. The following illustration shows the customized button
that you will create.
The vector graphics that make up the appearance of the button are created by using
XAML is similar to HTML except it is more powerful and extensible. Extensible
Application Markup Language (XAML) can be typed in manually using Visual Studio or
Notepad, or you can use a visual design tool such as Blend for Visual Studio. Blend
works by creating underlying XAML code, so both methods create the same graphics.
In This Section
Create a Button by Using Microsoft Expression Blend Demonstrates how to create
buttons with custom behavior by using the designer features of Expression Blend.
Create a Button by Using XAML Demonstrates how to create buttons with custom
behavior by using XAML and Visual Studio.
Related Sections
Styling and Templating Describes how styles and templates can be used to determine
the appearance and behavior of controls.
Animation Overview Describes how objects can be animated by using the WPF
animation and timing system.
Painting with Solid Colors and Gradients Overview Describes how to use brush objects
to paint with solid colors, linear gradients, and radial gradients.
Bitmap Effects Overview Describes the bitmap effects supported by WPF and explains
how to apply them.
Walkthrough: Create a Button by Using
Microsoft Expression Blend
Article • 08/18/2022
This walkthrough steps you through the process of creating a WPF customized button
using Microsoft Expression Blend.
) Important
The following illustration shows the customized button that you will create.
At this point you have a blank WPF project. You can press F5 to run the application. As
you might expect, the application consists of only a blank window. Next, you create a
rounded rectangle and convert it into a button.
2. Draw a rectangle approximately the size of a button on the Window: Select the
rectangle tool on the left-hand tool panel and drag the rectangle onto the
Window.
3. Round out the corners of the rectangle: Either drag the control points of the
rectangle or directly set the RadiusX and RadiusY properties. Set the values of
RadiusX and RadiusY to 20.
4. Change the rectangle into a button: Select the rectangle. On the Tools menu, click
Make Button.
5. Specify the scope of the style/template: A dialog box like the following appears.
For Resource name (Key), select Apply to all. This will make the resulting style and
button template apply to all objects that are buttons. For Define in, select
Application. This will make the resulting style and button template have scope
over the entire application. When you set the values in these two boxes, the button
style and template apply to all buttons within the entire application and any button
you create in the application will, by default, use this template.
In the template editor, notice that the button is now separated into a Rectangle
and the ContentPresenter. The ContentPresenter is used to present content within
the button (for example, the string "Button"). Both the rectangle and
ContentPresenter are laid out inside of a Grid.
2. Change the names of the template components: Right-click the rectangle in the
template inventory, change the Rectangle name from "[Rectangle]" to
"outerRectangle", and change "[ContentPresenter]" to "myContentPresenter".
3. Alter the rectangle so that it is empty inside (like a donut): Select outerRectangle
and set Fill to "Transparent" and StrokeThickness to 5.
Then set the Stroke to the color of whatever the template will be. To do this, click
the small white box next to Stroke, select CustomExpression, and type "
{TemplateBinding Background}" in the dialog box.
4. Create an inner rectangle: Now, create another rectangle (name it
"innerRectangle") and position it symmetrically on the inside of outerRectangle .
For this kind of work, you will probably want to zoom to make the button larger in
the editing area.
7 Note
Your rectangle might look different than the one in the figure (for example, it
might have rounded corners).
5. Move ContentPresenter to the top: At this point, it is possible that the text
"Button" will not be visible any longer. If this is so, this is because innerRectangle is
on top of the myContentPresenter. To fix this, drag myContentPresenter below
innerRectangle. Reposition rectangles and myContentPresenter to look similar to
below.
7 Note
10. Make glassCube look like glass: Set the Fill to a glassy look by using a linear
gradient that is 75% opaque and alternates between the color White and
Transparent over 6 approximately evenly spaced intervals. This is what to set the
gradient stops to:
3. IsMouseOver triggers opacity of 100% for glassCube: Notice that the Trigger
recording is on (see the preceding figure). This means that any changes you make
to the property values of glassCube while recording is on will become an action
that takes place when IsMouseOver is true . While recording, change the Opacity
of glassCube to 100%.
You have now created your first property trigger. Notice that the Triggers panel of
the editor has recorded the Opacity being changed to 100%.
Press F5 to run the application, and move the mouse pointer over and off the
button. You should see the glass layer appear when you mouse-over the button
and disappear when the pointer leaves.
4. IsMouseOver triggers stroke value change: Let's associate some other actions
with the IsMouseOver trigger. While recording continues, switch your selection
from glassCube to outerRectangle. Then set the Stroke of outerRectangle to the
custom expression of "{DynamicResource {x:Static
SystemColors.HighlightBrushKey}}". This sets the Stroke to the typical highlight
color used by buttons. Press F5 to see the effect when you mouse over the button.
5. IsMouseOver triggers blurry text: Let's associate one more action to the
IsMouseOver property trigger. Make the content of the button appear a little
blurry when the glass appears over it. To do this, we can apply a blur BitmapEffect
to the ContentPresenter (myContentPresenter).
7 Note
To return the Properties panel back to what it was before you did the search
for BitmapEffect, clear the text from the Search box.
At this point, we have used a property trigger with several associated actions to
create highlighting behavior for when the mouse pointer enters and leaves the
button area. Another typical behavior for a button is to highlight when it has focus
(as after it is clicked). We can add such behavior by adding another property
trigger for the IsFocused property.
6. Create property trigger for IsFocused: Using the same procedure as for
IsMouseOver (see the first step of this section), create another property trigger for
the IsFocused property. While Trigger recording is on, add the following actions to
the trigger:
As the final step in this walkthrough, we will add animations to the button. These
animations will be triggered by events—specifically, the MouseEnter and Click events.
To use event triggers and animations to add interactivity
1. Create a MouseEnter Event Trigger: Add a new event trigger and select
MouseEnter as the event to use in the trigger.
7 Note
You may need to resize your window and/or panels to see the display.
3. Create a keyframe: To create an animation, select the object you want to animate,
create two or more keyframes on the timeline, and for those keyframes, set the
property values you want the animation to interpolate between. The following
figure guides you through the creation of a keyframe.
4. Shrink glassCube at this keyframe: With the second keyframe selected, shrink the
size of the glassCube to 90% of its full size using the Size Transform.
Press F5 to run the application. Move the mouse pointer over the button. Notice
that the glass layer shrinks on top of the button.
5. Create another Event Trigger and associate a different animation with it: Let's
add one more animation. Use a similar procedure to what you used to create the
previous event trigger animation:
d. With the keyframe at 0.3 seconds highlighted, set the Rotate Transform Angle
to 360 degrees.
e. Press F5 to run the application. Click the button. Notice that the glass layer spins
around.
Conclusion
You have completed a customized button. You did this using a button template that was
applied to all buttons in the application. If you leave the template editing mode (see the
following figure) and create more buttons, you will see that they look and behave like
your custom button rather than like the default button.
Press F5 to run the application. Click the buttons and notice how they all behave the
same.
Remember that while you were customizing the template, you set the Fill property of
innerRectangle and the Stroke property outerRectangle to the template background
({TemplateBinding Background}). Because of this, when you set the background color of
the individual buttons, the background you set will be used for those respective
properties. Try changing the backgrounds now. In the following figure, different
gradients are used. Therefore, although a template is useful for overall customization of
controls like button, controls with templates can still be modified to look different from
each other.
In conclusion, in the process of customizing a button template you have learned how to
do the following in Microsoft Expression Blend:
Set property triggers. Property triggers are very useful because they can be used
on most objects, not just controls.
Set event triggers. Event triggers are very useful because they can be used on most
objects, not just controls.
Create animations.
Miscellaneous: create gradients, add BitmapEffects, use transforms, and set basic
properties of objects.
See also
Create a Button by Using XAML
Styling and Templating
Animation Overview
Painting with Solid Colors and Gradients Overview
Bitmap Effects Overview
Walkthrough: Create a Button by Using
XAML
Article • 02/06/2023
The objective of this walkthrough is to learn how to create an animated button for use
in a Windows Presentation Foundation (WPF) application. This walkthrough uses styles
and a template to create a customized button resource that allows reuse of code and
separation of button logic from the button declaration. This walkthrough is written
entirely in Extensible Application Markup Language (XAML).
) Important
This walkthrough guides you through the steps for creating the application by
typing or copying and pasting Extensible Application Markup Language (XAML)
into Visual Studio. If you would prefer to learn how to use a designer to create the
same application, see Create a Button by Using Microsoft Expression Blend.
2. Create a new WPF project: On the File menu, point to New, and then click Project.
Find the Windows Application (WPF) template and name the project
"AnimatedButton". This will create the skeleton for the application.
3. Add basic default buttons: All the files you need for this walkthrough are provided
by the template. Open the Window1.xaml file by double clicking it in Solution
Explorer. By default, there is a Grid element in Window1.xaml. Remove the Grid
element and add a few buttons to the Extensible Application Markup Language
(XAML) page by typing or copy and pasting the following highlighted code to
Window1.xaml:
XAML
<Window x:Class="AnimatedButton.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AnimatedButton" Height="300" Width="300"
Background="Black">
<!-- Buttons arranged vertically inside a StackPanel. -->
<StackPanel HorizontalAlignment="Left">
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Window>
Press F5 to run the application; you should see a set of buttons that looks like the
following figure.
Now that you have created the basic buttons, you are finished working in the
Window1.xaml file. The rest of the walkthrough focuses on the app.xaml file,
defining styles and a template for the buttons.
XAML
<Application x:Class="AnimatedButton.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml"
>
<Application.Resources>
<!-- Resources for the entire application can be defined here. -->
</Application.Resources>
</Application>
2. Create a style and define basic property values with it: Add the following markup
to the Application.Resources block. This markup creates a Style that applies to all
buttons in the application, setting the Width of the buttons to 90 and the Margin
to 10:
XAML
<Application.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="90" />
<Setter Property="Margin" Value="10" />
</Style>
</Application.Resources>
The TargetType property specifies that the style applies to all objects of type
Button. Each Setter sets a different property value for the Style. Therefore, at this
point every button in the application has a width of 90 and a margin of 10. If you
press F5 to run the application, you see the following window.
There is much more you can do with styles, including a variety of ways to fine-tune
what objects are targeted, specifying complex property values, and even using
styles as input for other styles. For more information, see Styling and Templating.
3. Set a style property value to a resource: Resources enable a simple way to reuse
commonly defined objects and values. It is especially useful to define complex
values using resources to make your code more modular. Add the following
highlighted markup to app.xaml.
XAML
<Application.Resources>
<LinearGradientBrush x:Key="GrayBlueGradientBrush" StartPoint="0,0"
EndPoint="1,1">
<GradientStop Color="DarkGray" Offset="0" />
<GradientStop Color="#CCCCFF" Offset="0.5" />
<GradientStop Color="DarkGray" Offset="1" />
</LinearGradientBrush>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource
GrayBlueGradientBrush}" />
<Setter Property="Width" Value="80" />
<Setter Property="Margin" Value="10" />
</Style>
</Application.Resources>
So far, the control of how buttons look in the application has been confined to changing
properties of the button. What if you want to make more radical changes to the button's
appearance? Templates enable powerful control over the presentation of an object.
Because templates can be used within styles, you can apply a template to all objects that
the style applies to (in this walkthrough, the button).
XAML
<Application.Resources>
<LinearGradientBrush x:Key="GrayBlueGradientBrush"
StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="DarkGray" Offset="0" />
<GradientStop Color="#CCCCFF" Offset="0.5" />
<GradientStop Color="DarkGray" Offset="1" />
</LinearGradientBrush>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource
GrayBlueGradientBrush}" />
<Setter Property="Width" Value="80" />
<Setter Property="Margin" Value="10" />
<Setter Property="Template">
<Setter.Value>
<!-- The button template is defined here. -->
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
2. Alter button presentation: At this point, you need to define the template. Add the
following highlighted markup. This markup specifies two Rectangle elements with
rounded edges, followed by a DockPanel. The DockPanel is used to host the
ContentPresenter of the button. A ContentPresenter displays the content of the
button. In this walkthrough, the content is text ("Button 1", "Button 2", "Button 3").
All of the template components (the rectangles and the DockPanel) are laid out
inside of a Grid.
XAML
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding
Height}" ClipToBounds="True">
<!-- Outer Rectangle with rounded corners. -->
<Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />
<!-- Inner Rectangle with rounded corners. -->
<Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20"
Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />
<!-- Present Content (text) of the button. -->
<DockPanel Name="myContentPresenterDockPanel">
<ContentPresenter x:Name="myContentPresenter" Margin="20"
Content="{TemplateBinding Content}" TextBlock.Foreground="Black" />
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
3. Add a glasseffect to the template: Next you will add the glass. First you create
some resources that create a glass gradient effect. Add these gradient resources
anywhere within the Application.Resources block:
XAML
<Application.Resources>
<GradientStopCollection x:Key="MyGlassGradientStopsResource">
<GradientStop Color="WhiteSmoke" Offset="0.2" />
<GradientStop Color="Transparent" Offset="0.4" />
<GradientStop Color="WhiteSmoke" Offset="0.5" />
<GradientStop Color="Transparent" Offset="0.75" />
<GradientStop Color="WhiteSmoke" Offset="0.9" />
<GradientStop Color="Transparent" Offset="1" />
</GradientStopCollection>
<LinearGradientBrush x:Key="MyGlassBrushResource"
StartPoint="0,0" EndPoint="1,1" Opacity="0.75"
GradientStops="{StaticResource MyGlassGradientStopsResource}" />
<!-- Styles and other resources below here. -->
These resources are used as the Fill for a rectangle that we insert into the Grid of
the button template. Add the following highlighted markup to the template.
XAML
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding
Height}"
ClipToBounds="True">
Notice that the Opacity of the rectangle with the x:Name property of "glassCube" is
0, so when you run the sample, you do not see the glass rectangle overlaid on top.
This is because we will later add triggers to the template for when the user
interacts with the button. However, you can see what the button looks like now by
changing the Opacity value to 1 and running the application. See the following
figure. Before proceeding to the next step, change the Opacity back to 0.
An easy way to add interactivity (mouse-over, mouse-leave, click, and so on) is to define
triggers within your template or style. To create a Trigger, you define a property
"condition" such as: The button IsMouseOver property value is equal to true . You then
define setters (actions) that take place when the trigger condition is true.
XAML
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}" ClipToBounds="True">
XAML
<ControlTemplate.Triggers>
<!-- Set properties when mouse pointer is over the button. -->
<Trigger Property="IsMouseOver" Value="True"> <!-- Below are three
property settings that occur when the condition is met (user
mouses over button). --> <!-- Change the color of the outer
rectangle when user mouses over it. --> <Setter Property
="Rectangle.Stroke" TargetName="outerRectangle" Value="
{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" /> <!-
- Sets the glass opacity to 1, therefore, the glass "appears"
when user mouses over it. --> <Setter Property="Rectangle.Opacity"
Value="1" TargetName="glassCube" /> <!-- Makes the text slightly
blurry as though you were looking at it through blurry glass.
--> <Setter Property="ContentPresenter.BitmapEffect"
TargetName="myContentPresenter"> <Setter.Value>
<BlurBitmapEffect Radius="1" /> </Setter.Value> </Setter>
</Trigger>
<ControlTemplate.Triggers/>
Press F5 to run the application and see the effect as you run the mouse pointer
over the buttons.
3. Add a focus trigger: Next, we'll add some similar setters to handle the case when
the button has focus (for example, after the user clicks it).
XAML
<ControlTemplate.Triggers>
<!-- Set properties when mouse pointer is over the button. -->
<Trigger Property="IsMouseOver" Value="True">
<!-- Below are three property settings that occur when the
condition is met (user mouses over button). -->
<!-- Change the color of the outer rectangle when user
mouses over it. -->
<Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static
SystemColors.HighlightBrushKey}}" />
</ControlTemplate.Triggers>
Press F5 to run the application and click on one of the buttons. Notice that the
button stays highlighted after you click it because it still has focus. If you click
another button, the new button gains focus while the last one loses it.
4. Add animations for MouseEnter and MouseLeave : Next we add some animations
to the triggers. Add the following markup anywhere inside of the
ControlTemplate.Triggers block.
XAML
<!-- Animations that start when mouse enters and leaves button. -->
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard Name="mouseEnterBeginStoryboard">
<Storyboard>
<!-- This animation makes the glass rectangle shrink in the X
direction. -->
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].
(ScaleTransform.ScaleX)"
By="-0.1" Duration="0:0:0.5" />
<!-- This animation makes the glass rectangle shrink in the Y
direction. -->
<DoubleAnimation
Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].
(ScaleTransform.ScaleY)"
By="-0.1" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<!-- Stopping the storyboard sets all animated properties back to
default. -->
<StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />
</EventTrigger.Actions>
</EventTrigger>
The glass rectangle shrinks when the mouse pointer moves over the button and
returns back to normal size when the pointer leaves.
There are two animations that are triggered when the pointer goes over the button
(MouseEnter event is raised). These animations shrink the glass rectangle along the
X and Y axis. Notice the properties on the DoubleAnimation elements — Duration
and By. The Duration specifies that the animation occurs over half a second, and By
specifies that the glass shrinks by 10%.
The second event trigger (MouseLeave) simply stops the first one. When you stop
a Storyboard, all the animated properties return to their default values. Therefore,
when the user moves the pointer off the button, the button goes back to the way it
was before the mouse pointer moved over the button. For more information about
animations, see Animation Overview.
5. Add an animation for when the button is clicked: The final step is to add a trigger
for when the user clicks the button. Add the following markup anywhere inside of
the ControlTemplate.Triggers block:
XAML
Press F5 to run the application, and click one of the buttons. When you click a
button, the glass rectangle spins around.
Summary
In this walkthrough, you performed the following exercises:
Controlled basic properties of the buttons in the entire application using the Style.
Created resources like gradients to use for property values of the Style setters.
See also
Create a Button by Using Microsoft Expression Blend
Styling and Templating
Animation Overview
Painting with Solid Colors and Gradients Overview
Bitmap Effects Overview