Advance DWP Fare As
Advance DWP Fare As
In This Section
WPF Architecture
XAML in WPF
Base Element Classes
Element Tree and Serialization
WPF Property System
Events in WPF
Input
Drag and Drop
Resources
Documents
Globalization and Localization
Layout
Types migrated from WPF to System.Xaml
Migration and Interoperability
Performance
Threading Model
Unmanaged WPF API Reference
       WPF Architecture
      11/21/2022 • 15 minutes to read • Edit Online
This topic provides a guided tour of the Windows Presentation Foundation (WPF) class hierarchy. It covers most
of the major subsystems of WPF, and describes how they interact. It also details some of the choices made by
the architects of WPF.
System.Object
The primary WPF programming model is exposed through managed code. Early in the design phase of WPF
there were a number of debates about where the line should be drawn between the managed components of
the system and the unmanaged ones. The CLR provides a number of features that make development more
productive and robust (including memory management, error handling, common type system, etc.) but they
come at a cost.
The major components of WPF are illustrated in the figure below. The red sections of the diagram
(PresentationFramework, PresentationCore, and milcore) are the major code portions of WPF. Of these, only one
is an unmanaged component – milcore. Milcore is written in unmanaged code in order to enable tight
integration with DirectX. All display in WPF is done through the DirectX engine, allowing for efficient hardware
and software rendering. WPF also required fine control over memory and execution. The composition engine in
milcore is extremely performance sensitive, and required giving up many advantages of the CLR to gain
performance.
Communication between the managed and unmanaged portions of WPF is discussed later in this topic. The
remainder of the managed programming model is described below.
System.Threading.DispatcherObject
Most objects in WPF derive from DispatcherObject, which provides the basic constructs for dealing with
concurrency and threading. WPF is based on a messaging system implemented by the dispatcher. This works
much like the familiar Win32 message pump; in fact, the WPF dispatcher uses User32 messages for performing
cross thread calls.
There are really two core concepts to understand when discussing concurrency in WPF – the dispatcher and
thread affinity.
During the design phase of WPF, the goal was to move to a single thread of execution, but a non-thread
"affinitized" model. Thread affinity happens when a component uses the identity of the executing thread to store
some type of state. The most common form of this is to use the thread local store (TLS) to store state. Thread
affinity requires that each logical thread of execution be owned by only one physical thread in the operating
system, which can become memory intensive. In the end, WPF’s threading model was kept in sync with the
existing User32 threading model of single threaded execution with thread affinity. The primary reason for this
was interoperability – systems like OLE 2.0, the clipboard, and Internet Explorer all require single thread affinity
(STA) execution.
Given that you have objects with STA threading, you need a way to communicate between threads, and validate
that you are on the correct thread. Herein lies the role of the dispatcher. The dispatcher is a basic message
dispatching system, with multiple prioritized queues. Examples of messages include raw input notifications
(mouse moved), framework functions (layout), or user commands (execute this method). By deriving from
DispatcherObject, you create a CLR object that has STA behavior, and will be given a pointer to a dispatcher at
creation time.
System.Windows.DependencyObject
One of the primary architectural philosophies used in building WPF was a preference for properties over
methods or events. Properties are declarative and allow you to more easily specify intent instead of action. This
also supported a model driven, or data driven, system for displaying user interface content. This philosophy had
the intended effect of creating more properties that you could bind to, in order to better control the behavior of
an application.
In order to have more of the system driven by properties, a richer property system than what the CLR provides
was needed. A simple example of this richness is change notifications. In order to enable two way binding, you
need both sides of the bind to support change notification. In order to have behavior tied to property values,
you need to be notified when the property value changes. The Microsoft .NET Framework has an interface,
INotifyProper tyChange , which allows an object to publish change notifications, however it is optional.
WPF provides a richer property system, derived from the DependencyObject type. The property system is truly a
"dependency" property system in that it tracks dependencies between property expressions and automatically
revalidates property values when dependencies change. For example, if you have a property that inherits (like
FontSize), the system is automatically updated if the property changes on a parent of an element that inherits
the value.
The foundation of the WPF property system is the concept of a property expression. In this first release of WPF,
the property expression system is closed, and the expressions are all provided as part of the framework.
Expressions are why the property system doesn’t have data binding, styling, or inheritance hard coded, but
rather provided by later layers within the framework.
The property system also provides for sparse storage of property values. Because objects can have dozens (if
not hundreds) of properties, and most of the values are in their default state (inherited, set by styles, etc.), not
every instance of an object needs to have the full weight of every property defined on it.
The final new feature of the property system is the notion of attached properties. WPF elements are built on the
principle of composition and component reuse. It is often the case that some containing element (like a Grid
layout element) needs additional data on child elements to control its behavior (like the Row/Column
information). Instead of associating all of these properties with every element, any object is allowed to provide
property definitions for any other object. This is similar to the "expando" features of JavaScript.
System.Windows.Media.Visual
With a system defined, the next step is getting pixels drawn to the screen. The Visual class provides for building
a tree of visual objects, each optionally containing drawing instructions and metadata about how to render
those instructions (clipping, transformation, etc.). Visual is designed to be extremely lightweight and flexible, so
most of the features have no public API exposure and rely heavily on protected callback functions.
Visual is really the entry point to the WPF composition system. Visual is the point of connection between these
two subsystems, the managed API and the unmanaged milcore.
WPF displays data by traversing the unmanaged data structures managed by the milcore. These structures,
called composition nodes, represent a hierarchical display tree with rendering instructions at each node. This
tree, illustrated on the right hand side of the figure below, is only accessible through a messaging protocol.
When programming WPF, you create Visual elements, and derived types, which internally communicate to the
composition tree through this messaging protocol. Each Visual in WPF may create one, none, or several
composition nodes.
There is a very important architectural detail to notice here – the entire tree of visuals and drawing instructions
is cached. In graphics terms, WPF uses a retained rendering system. This enables the system to repaint at high
refresh rates without the composition system blocking on callbacks to user code. This helps prevent the
appearance of an unresponsive application.
Another important detail that isn’t really noticeable in the diagram is how the system actually performs
composition.
In User32 and GDI, the system works on an immediate mode clipping system. When a component needs to be
rendered, the system establishes a clipping bounds outside of which the component isn’t allowed to touch the
pixels, and then the component is asked to paint pixels in that box. This system works very well in memory
constrained systems because when something changes you only have to touch the affected component – no
two components ever contribute to the color of a single pixel.
WPF uses a "painter's algorithm" painting model. This means that instead of clipping each component, each
component is asked to render from the back to the front of the display. This allows each component to paint
over the previous component's display. The advantage of this model is that you can have complex, partially
transparent shapes. With today’s modern graphics hardware, this model is relatively fast (which wasn’t the case
when User32/ GDI were created).
As mentioned previously, a core philosophy of WPF is to move to a more declarative, "property centric" model
of programming. In the visual system, this shows up in a couple of interesting places.
First, if you think about the retained mode graphic system, this is really moving away from an imperative
DrawLine/DrawLine type model, to a data oriented model – new Line()/new Line(). This move to data driven
rendering allows complex operations on the drawing instructions to be expressed using properties. The types
deriving from Drawing are effectively the object model for rendering.
Second, if you evaluate the animation system, you'll see that it is almost completely declarative. Instead of
requiring a developer to compute the next location, or next color, you can express animations as a set of
properties on an animation object. These animations can then express the intent of the developer or designer
(move this button from here to there in 5 seconds), and the system can determine the most efficient way to
accomplish that.
System.Windows.UIElement
UIElement defines core subsystems including Layout, Input, and Events.
Layout is a core concept in WPF. In many systems there is either a fixed set of layout models (HTML supports
three models for layout; flow, absolute, and tables) or no model for layout (User32 really only supports absolute
positioning). WPF started with the assumption that developers and designers wanted a flexible, extensible layout
model, which could be driven by property values rather than imperative logic. At the UIElement level, the basic
contract for layout is introduced – a two phase model with Measure and Arrange passes.
Measure allows a component to determine how much size it would like to take. This is a separate phase from
Arrange because there are many situations where a parent element will ask a child to measure several times to
determine its optimal position and size. The fact that parent elements ask child elements to measure
demonstrates another key philosophy of WPF – size to content. All controls in WPF support the ability to size to
the natural size of their content. This makes localization much easier, and allows for dynamic layout of elements
as things resize. The Arrange phase allows a parent to position and determine the final size of each child.
A lot of time is often spent talking about the output side of WPF – Visual and related objects. However there is a
tremendous amount of innovation on the input side as well. Probably the most fundamental change in the input
model for WPF is the consistent model by which input events are routed through the system.
Input originates as a signal on a kernel mode device driver and gets routed to the correct process and thread
through an intricate process involving the Windows kernel and User32. Once the User32 message
corresponding to the input is routed to WPF, it is converted into a WPF raw input message and sent to the
dispatcher. WPF allows for raw input events to be converted to multiple actual events, enabling features like
"MouseEnter" to be implemented at a low level of the system with guaranteed delivery.
Each input event is converted to at least two events – a "preview" event and the actual event. All events in WPF
have a notion of routing through the element tree. Events are said to "bubble" if they traverse from a target up
the tree to the root, and are said to "tunnel" if they start at the root and traverse down to a target. Input preview
events tunnel, enabling any element in the tree an opportunity to filter or take action on the event. The regular
(non-preview) events then bubble from the target up to the root.
This split between the tunnel and bubble phase makes implementation of features like keyboard accelerators
work in a consistent fashion in a composite world. In User32 you would implement keyboard accelerators by
having a single global table containing all the accelerators you wanted to support (Ctrl+N mapping to "New"). In
the dispatcher for your application you would call TranslateAccelerator which would sniff the input messages
in User32 and determine if any matched a registered accelerator. In WPF this wouldn’t work because the system
is fully "composable" – any element can handle and use any keyboard accelerator. Having this two phase model
for input allows components to implement their own "TranslateAccelerator".
To take this one step further, UIElement also introduces the notion of CommandBindings. The WPF command
system allows developers to define functionality in terms of a command end point – something that implements
ICommand. Command bindings enable an element to define a mapping between an input gesture (Ctrl+N) and
a command (New). Both the input gestures and command definitions are extensible, and can be wired together
at usage time. This makes it trivial, for example, to allow an end user to customize the key bindings that they
want to use within an application.
To this point in the topic, "core" features of WPF – features implemented in the PresentationCore assembly, have
been the focus. When building WPF, a clean separation between foundational pieces (like the contract for layout
with Measure and Arrange ) and framework pieces (like the implementation of a specific layout like Grid) was
the desired outcome. The goal was to provide an extensibility point low in the stack that would allow external
developers to create their own frameworks if needed.
System.Windows.FrameworkElement
FrameworkElement can be looked at in two different ways. It introduces a set of policies and customizations on
the subsystems introduced in lower layers of WPF. It also introduces a set of new subsystems.
The primary policy introduced by FrameworkElement is around application layout. FrameworkElement builds on
the basic layout contract introduced by UIElement and adds the notion of a layout "slot" that makes it easier for
layout authors to have a consistent set of property driven layout semantics. Properties like HorizontalAlignment,
VerticalAlignment, MinWidth, and Margin (to name a few) give all components derived from FrameworkElement
consistent behavior inside of layout containers.
FrameworkElement also provides easier API exposure to many features found in the core layers of WPF. For
example, FrameworkElement provides direct access to animation through the BeginStoryboard method. A
Storyboard provides a way to script multiple animations against a set of properties.
The two most critical things that FrameworkElement introduces are data binding and styles.
The data binding subsystem in WPF should be relatively familiar to anyone that has used Windows Forms or
ASP.NET for creating an application user interface (UI). In each of these systems, there is a simple way to express
that you want one or more properties from a given element to be bound to a piece of data. WPF has full support
for property binding, transformation, and list binding.
One of the most interesting features of data binding in WPF is the introduction of data templates. Data
templates allow you to declaratively specify how a piece of data should be visualized. Instead of creating a
custom user interface that can be bound to data, you can instead turn the problem around and let the data
determine the display that will be created.
Styling is really a lightweight form of data binding. Using styling you can bind a set of properties from a shared
definition to one or more instances of an element. Styles get applied to an element either by explicit reference
(by setting the Style property) or implicitly by associating a style with the CLR type of the element.
System.Windows.Controls.Control
Control’s most significant feature is templating. If you think about WPF’s composition system as a retained
mode rendering system, templating allows a control to describe its rendering in a parameterized, declarative
manner. A ControlTemplate is really nothing more than a script to create a set of child elements, with bindings to
properties offered by the control.
Control provides a set of stock properties, Foreground, Background, Padding, to name a few, which template
authors can then use to customize the display of a control. The implementation of a control provides a data
model and interaction model. The interaction model defines a set of commands (like Close for a window) and
bindings to input gestures (like clicking the red X in the upper corner of the window). The data model provides a
set of properties to either customize the interaction model or customize the display (determined by the
template).
This split between the data model (properties), interaction model (commands and events), and display model
(templates) enables complete customization of a control’s look and behavior.
A common aspect of the data model of controls is the content model. If you look at a control like Button, you will
see that it has a property named "Content" of type Object. In Windows Forms and ASP.NET, this property would
typically be a string – however that limits the type of content you can put in a button. Content for a button can
either be a simple string, a complex data object, or an entire element tree. In the case of a data object, the data
template is used to construct a display.
Summary
WPF is designed to allow you to create dynamic, data driven presentation systems. Every part of the system is
designed to create objects through property sets that drive behavior. Data binding is a fundamental part of the
system, and is integrated at every layer.
Traditional applications create a display and then bind to some data. In WPF, everything about the control, every
aspect of the display, is generated by some type of data binding. The text found inside a button is displayed by
creating a composed control inside of the button and binding its display to the button’s content property.
When you begin developing WPF based applications, it should feel very familiar. You can set properties, use
objects, and data bind in much the same way that you can using Windows Forms or ASP.NET. With a deeper
investigation into the architecture of WPF, you'll find that the possibility exists for creating much richer
applications that fundamentally treat data as the core driver of the application.
See also
   Visual
   UIElement
   ICommand
   FrameworkElement
   DispatcherObject
   CommandBinding
   Control
   Data Binding Overview
   Layout
   Animation Overview
       XAML in WPF
      11/21/2022 • 2 minutes to read • Edit Online
WPF types are implemented such that they can provide the required type backing for a XAML representation. In
general, you can create the majority of your WPF application UI in XAML markup.
In This Section
XAML in WPF
XAML Syntax In Detail
Code-Behind and XAML in WPF
XAML and Custom Classes for WPF
Markup Extensions and WPF XAML
XAML Namespaces and Namespace Mapping for WPF XAML
WPF XAML Namescopes
Inline Styles and Templates
White-space Processing in XAML
TypeConverters and XAML
XML Character Entities and XAML
XAML Namespace (x:) Language Features
WPF XAML Extensions
Markup Compatibility (mc:) Language Features
Related Sections
WPF Architecture
Base Elements
Element Tree and Serialization
Properties
Events
Input
Resources
Styling and Templating
Threading Model
       XAML overview in WPF
       11/21/2022 • 26 minutes to read • Edit Online
This article describes the features of the XAML language and demonstrates how you can use XAML to write
Windows Presentation Foundation (WPF) apps. This article specifically describes XAML as implemented by WPF.
XAML itself is a larger language concept than WPF.
What is XAML
XAML is a declarative markup language. As applied to the .NET Core programming model, XAML simplifies
creating a UI for a .NET Core app. You can create visible UI elements in the declarative XAML markup, and then
separate the UI definition from the run-time logic by using code-behind files that are joined to the markup
through partial class definitions. XAML directly represents the instantiation of objects in a specific set of backing
types defined in assemblies. This is unlike most other markup languages, which are typically an interpreted
language without such a direct tie to a backing type system. XAML enables a workflow where separate parties
can work on the UI and the logic of an app, using potentially different tools.
When represented as text, XAML files are XML files that generally have the     .xaml   extension. The files can be
encoded by any XML encoding, but encoding as UTF-8 is typical.
The following example shows how you might create a button as part of a UI. This example is intended to give
you a flavor of how XAML represents common UI programming metaphors (it is not a complete sample).
   <StackPanel>
     <Button Content="Click Me"/>
   </StackPanel>
This specifies two object elements: <StackPanel> (with content, and a closing tag later), and <Button .../> (the
self-closing form, with several attributes). The object elements StackPanel and Button each map to the name
of a class that is defined by WPF and is part of the WPF assemblies. When you specify an object element tag,
you create an instruction for XAML processing to create a new instance of the underlying type. Each instance is
created by calling the parameterless constructor of the underlying type when parsing and loading the XAML.
Attribute syntax (properties)
Properties of an object can often be expressed as attributes of the object element. The attribute syntax names
the object property that is being set, followed by the assignment operator (=). The value of an attribute is always
specified as a string that is contained within quotation marks.
Attribute syntax is the most streamlined property setting syntax and is the most intuitive syntax to use for
developers who have used markup languages in the past. For example, the following markup creates a button
that has red text and a blue background in addition to display text specified as Content .
   <Button>
     <Button.Background>
       <SolidColorBrush Color="Blue"/>
     </Button.Background>
     <Button.Foreground>
       <SolidColorBrush Color="Red"/>
     </Button.Foreground>
     <Button.Content>
       This is a button
     </Button.Content>
   </Button>
Collection syntax
The XAML language includes some optimizations that produce more human-readable markup. One such
optimization is that if a particular property takes a collection type, then items that you declare in markup as
child elements within that property's value become part of the collection. In this case a collection of child object
elements is the value being set to the collection property.
The following example shows collection syntax for setting values of the GradientStops property.
   <LinearGradientBrush>
     <LinearGradientBrush.GradientStops>
       <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
       <GradientStop Offset="0.0" Color="Red" />
       <GradientStop Offset="1.0" Color="Blue" />
     </LinearGradientBrush.GradientStops>
   </LinearGradientBrush>
   <Border>
     <TextBox Width="300"/>
   </Border>
   <!--explicit equivalent-->
   <Border>
     <Border.Child>
       <TextBox Width="300"/>
     </Border.Child>
   </Border>
As a rule of the XAML language, the value of a XAML content property must be given either entirely before or
entirely after any other property elements on that object element. For instance, the following markup does not
compile.
   <Button>I am a
     <Button.Background>Blue</Button.Background>
     blue button</Button>
For more information about the specifics of XAML syntax, see XAML Syntax In Detail.
Text content
A small number of XAML elements can directly process text as their content. To enable this, one of the following
cases must be true:
   The class must declare a content property, and that content property must be of a type assignable to a
   string (the type could be Object). For instance, any ContentControl uses Content as its content property
   and it is type Object, and this supports the following usage on a ContentControl such as a Button:
    <Button>Hello</Button> .
   The type must declare a type converter, in which case the text content is used as initialization text for that
   type converter. For example, <Brush>Blue</Brush> converts the content value of Blue into a brush. This
   case is less common in practice.
   The type must be a known XAML language primitive.
Content properties and collection syntax combined
Consider this example.
   <StackPanel>
     <Button>First Button</Button>
     <Button>Second Button</Button>
   </StackPanel>
Here, each Button is a child element of StackPanel. This is a streamlined and intuitive markup that omits two tags
for two different reasons.
   Omitted StackPanel.Children proper ty element: StackPanel derives from Panel. Panel defines
   Panel.Children as its XAML content property.
   Omitted UIElementCollection object element: The Panel.Children property takes the type
   UIElementCollection, which implements IList. The collection's element tag can be omitted, based on the
   XAML rules for processing collections such as IList. (In this case, UIElementCollection actually cannot be
   instantiated because it does not expose a parameterless constructor, and that is why the
   UIElementCollection object element is shown commented out).
   <StackPanel>
     <StackPanel.Children>
       <!--<UIElementCollection>-->
       <Button>First Button</Button>
       <Button>Second Button</Button>
       <!--</UIElementCollection>-->
     </StackPanel.Children>
   </StackPanel>
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="ExampleNamespace.ExamplePage">
     <Button Click="Button_Click" >Click Me!</Button>
   </Page>
There is more to events and XAML in WPF than just this example of the attribute syntax. For example, you might
wonder what the ClickHandler referenced here represents and how it is defined. This will be explained in the
upcoming Events and XAML code-behind section of this article.
Markup extensions
Markup extensions are a XAML language concept. When used to provide the value of an attribute syntax, curly
braces ( { and } ) indicate a markup extension usage. This usage directs the XAML processing to escape from
the general treatment of attribute values as either a literal string or a string-convertible value.
The most common markup extensions used in WPF app programming are Binding , used for data binding
expressions, and the resource references StaticResource and DynamicResource . By using markup extensions,
you can use attribute syntax to provide values for properties even if that property does not support an attribute
syntax in general. Markup extensions often use intermediate expression types to enable features such as
deferring values or referencing other objects that are only present at run-time.
For example, the following markup sets the value of the Style property using attribute syntax. The Style property
takes an instance of the Style class, which by default could not be instantiated by an attribute syntax string. But
in this case, the attribute references a particular markup extension, StaticResource . When that markup
extension is processed, it returns a reference to a style that was previously instantiated as a keyed resource in a
resource dictionary.
   <Page.Resources>
     <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
     <Style TargetType="Border" x:Key="PageBackground">
       <Setter Property="Background" Value="Blue"/>
     </Style>
   </Page.Resources>
   <StackPanel>
     <Border Style="{StaticResource PageBackground}">
     </Border>
   </StackPanel>
For a reference listing of all markup extensions for XAML implemented specifically in WPF, see WPF XAML
Extensions. For a reference listing of the markup extensions that are defined by System.Xaml and are more
widely available for .NET Core XAML implementations, see XAML Namespace (x:) Language Features. For more
information about markup extension concepts, see Markup Extensions and WPF XAML.
Type converters
In the XAML Syntax in Brief section, it was stated that the attribute value must be able to be set by a string. The
basic, native handling of how strings are converted into other object types or primitive values is based on the
String type itself, in addition to native processing for certain types such as DateTime or Uri. But many WPF types
or members of those types extend the basic string attribute processing behavior in such a way that instances of
more complex object types can be specified as strings and attributes.
The Thickness structure is an example of a type that has a type conversion enabled for XAML usages. Thickness
indicates measurements within a nested rectangle and is used as the value for properties such as Margin. By
placing a type converter on Thickness, all properties that use a Thickness are easier to specify in XAML because
they can be specified as attributes. The following example uses a type conversion and attribute syntax to provide
a value for a Margin:
The previous attribute syntax example is equivalent to the following more verbose syntax example, where the
Margin is instead set through property element syntax containing a Thickness object element. The four key
properties of Thickness are set as attributes on the new instance:
  NOTE
  There are also a limited number of objects where the type conversion is the only public way to set a property to that type
  without involving a subclass, because the type itself does not have a parameterless constructor. An example is Cursor.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Page>
The root element also contains the attributes xmlns and xmlns:x . These attributes indicate to a XAML
processor which XAML namespaces contain the type definitions for backing types that the markup will reference
as elements. The xmlns attribute specifically indicates the default XAML namespace. Within the default XAML
namespace, object elements in the markup can be specified without a prefix. For most WPF app scenarios, and
for almost all of the examples given in the WPF sections of the SDK, the default XAML namespace is mapped to
the WPF namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation . The xmlns:x attribute
indicates an additional XAML namespace, which maps the XAML language namespace
 http://schemas.microsoft.com/winfx/2006/xaml .
This usage of xmlns to define a scope for usage and mapping of a namescope is consistent with the XML 1.0
specification. XAML namescopes are different from XML namescopes only in that a XAML namescope also
implies something about how the namescope's elements are backed by types when it comes to type resolution
and parsing the XAML.
The   xmlns   attributes are only strictly necessary on the root element of each XAML file.        xmlns   definitions will
apply to all descendant elements of the root element (this behavior is again consistent with the XML 1.0
specification for xmlns .) xmlns attributes are also permitted on other elements underneath the root, and would
apply to any descendant elements of the defining element. However, frequent definition or redefinition of XAML
namespaces can result in a XAML markup style that is difficult to read.
The WPF implementation of its XAML processor includes an infrastructure that has awareness of the WPF core
assemblies. The WPF core assemblies are known to contain the types that support the WPF mappings to the
default XAML namespace. This is enabled through configuration that is part of your project build file and the
WPF build and project systems. Therefore, declaring the default XAML namespace as the default xmlns is all
that is necessary in order to reference XAML elements that come from WPF assemblies.
The x: prefix
In the previous root element example, the prefix x: was used to map the XAML namespace
 http://schemas.microsoft.com/winfx/2006/xaml , which is the dedicated XAML namespace that supports XAML
language constructs. This x: prefix is used for mapping this XAML namespace in the templates for projects, in
examples, and in documentation throughout this SDK. The XAML namespace for the XAML language contains
several programming constructs that you will use frequently in your XAML. The following is a listing of the most
common x: prefix programming constructs you will use:
   x:Key: Sets a unique key for each resource in a ResourceDictionary (or similar dictionary concepts in other
   frameworks). x:Key will probably account for 90 percent of the x: usages you will see in a typical WPF
   app's markup.
   x:Class: Specifies the CLR namespace and class name for the class that provides code-behind for a XAML
   page. You must have such a class to support code-behind per the WPF programming model, and
   therefore you almost always see x: mapped, even if there are no resources.
   x:Name: Specifies a run-time object name for the instance that exists in run-time code after an object
   element is processed. In general, you will frequently use a WPF-defined equivalent property for x:Name.
   Such properties map specifically to a CLR backing property and are thus more convenient for app
   programming, where you frequently use run-time code to find the named elements from initialized
   XAML. The most common such property is FrameworkElement.Name. You might still use x:Name when
   the equivalent WPF framework-level Name property is not supported in a particular type. This occurs in
   certain animation scenarios.
   x:Static: Enables a reference that returns a static value that is not otherwise a XAML-compatible property.
   x:Type: Constructs a Type reference based on a type name. This is used to specify attributes that take Type,
   such as Style.TargetType, although frequently the property has native string-to-Type conversion in such a
   way that the x:Type markup extension usage is optional.
There are additional programming constructs in the x: prefix/XAML namespace, which are not as common. For
details, see XAML Namespace (x:) Language Features.
   <Page
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
       >
     <StackPanel Name="LayoutRoot">
       <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
   ...
     </StackPanel>
   </Page>
For more information about custom types in XAML, see XAML and Custom Classes for WPF.
For more information about how XML namespaces and code namespaces in assemblies are related, see XAML
Namespaces and Namespace Mapping for WPF XAML.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="ExampleNamespace.ExamplePage">
     <Button Click="Button_Click" >Click Me!</Button>
   </Page>
   namespace ExampleNamespace
   {
     public partial class ExamplePage
     {
       void Button_Click(object sender, RoutedEventArgs e)
       {
         Button b = e.Source as Button;
         b.Foreground = Brushes.Red;
       }
     }
   }
   Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
       Dim b As Button = e.Source
       b.Foreground = Brushes.Red
   End Sub
Notice that the code-behind file uses the CLR namespace ExampleNamespace and declares ExamplePage as a
partial class within that namespace. This parallels the x:Class attribute value of ExampleNamespace . ExamplePage
that was provided in the markup root. The WPF markup compiler will create a partial class for any compiled
XAML file, by deriving a class from the root element type. When you provide code-behind that also defines the
same partial class, the resulting code is combined within the same namespace and class of the compiled app.
For more information about requirements for code-behind programming in WPF, see Code-behind, Event
Handler, and Partial Class Requirements in WPF.
If you do not want to create a separate code-behind file, you can also inline your code in a XAML file. However,
inline code is a less versatile technique that has substantial limitations. For more informaiton, see Code-Behind
and XAML in WPF.
Routed events
A particular event feature that is fundamental to WPF is a routed event. Routed events enable an element to
handle an event that was raised by a different element, as long as the elements are connected through a tree
relationship. When specifying event handling with a XAML attribute, the routed event can be listened for and
handled on any element, including elements that do not list that particular event in the class members table.
This is accomplished by qualifying the event name attribute with the owning class name. For instance, the parent
 StackPanel in the ongoing StackPanel / Button example could register a handler for the child element
button's Click event by specifying the attribute Button.Click on the StackPanel object element, with your
handler name as the attribute value. For more information, see Routed Events Overview.
   <StackPanel Name="buttonContainer">
     <Button Click="RemoveThis">Click to remove this button</Button>
   </StackPanel>
Just like a variable, the XAML name for an instance is governed by a concept of scope, so that names can be
enforced to be unique within a certain scope that is predictable. The primary markup that defines a page
denotes one unique XAML namescope, with the XAML namescope boundary being the root element of that
page. However, other markup sources can interact with a page at run-time, such as styles or templates within
styles, and such markup sources often have their own XAML namescopes that do not necessarily connect with
the XAML namescope of the page. For more information on x:Name and XAML namescopes, see Name, x:Name
Directive, or WPF XAML Namescopes.
In WPF, most or all the attached properties are also implemented as dependency properties. For more
information, see Attached Properties Overview.
Attached events use a similar ownerType.eventName form of attribute syntax. Just like the non-attached events,
the attribute value for an attached event in XAML specifies the name of the handler method that is invoked
when the event is handled on the element. Attached event usages in WPF XAML are less common. For more
information, see Attached Events Overview.
XAML security
XAML is a markup language that directly represents object instantiation and execution. Therefore, elements
created in XAML have the same ability to interact with system resources (network access, file system IO, for
example) as the equivalent generated code does. XAML loaded in to a fully trusted app has the same access to
the system resources as the hosting app does.
Code Access Security (CAS ) in WPF
WPF for .NET Framework supports Code Access Security (CAS). This means that WPF content running in the
internet zone has reduced execution permissions. "Loose XAML" (pages of noncompiled XAML interpreted at
load time by a XAML viewer) and XBAP are usually run in this internet zone and use the same permission set.
However, XAML loaded in to a fully trusted application has the same access to the system resources as the
hosting application does. For more information, see WPF Partial Trust Security.
See also
   XAML Syntax In Detail
   XAML and Custom Classes for WPF
   XAML Namespace (x:) Language Features
   WPF XAML Extensions
   Base Elements Overview
   Trees in WPF
       XAML Syntax In Detail
       11/21/2022 • 27 minutes to read • Edit Online
This topic defines the terms that are used to describe the elements of XAML syntax. These terms are used
frequently throughout the remainder of this documentation, both for WPF documentation specifically and for
the other frameworks that use XAML or the basic XAML concepts enabled by the XAML language support at the
System.Xaml level. This topic expands on the basic terminology introduced in the topic XAML in WPF.
<Button Name="CheckoutButton"/>
The following example is object element syntax that also includes XAML content property syntax. The inner text
contained within will be used to set the TextBox XAML content property, Text.
Content Models
A class might support a usage as a XAML object element in terms of the syntax, but that element will only
function properly in an application or page when it is placed in an expected position of an overall content model
or element tree. For example, a MenuItem should typically only be placed as a child of a MenuBase derived class
such as Menu. Content models for specific elements are documented as part of the remarks on the class pages
for controls and other WPF classes that can be used as XAML elements.
In order to be set through attribute syntax, a property must be public and must be writeable. The value of the
property in the backing type system must be a value type, or must be a reference type that can be instantiated
or referenced by a XAML processor when accessing the relevant backing type.
For WPF XAML events, the event that is referenced as the attribute name must be public and have a public
delegate.
The property or event must be a member of the class or structure that is instantiated by the containing object
element.
Processing of Attribute Values
The string value contained within the opening and closing quotation marks is processed by a XAML processor.
For properties, the default processing behavior is determined by the type of the underlying CLR property.
The attribute value is filled by one of the following, using this processing order:
1. If the XAML processor encounters a curly brace, or an object element that derives from MarkupExtension,
   then the referenced markup extension is evaluated first rather than processing the value as a string, and
   the object returned by the markup extension is used as the value. In many cases the object returned by a
   markup extension will be a reference to an existing object, or an expression that defers evaluation until
   run time, and is not a newly instantiated object.
2. If the property is declared with an attributed TypeConverter, or the value type of that property is declared
   with an attributed TypeConverter, the string value of the attribute is submitted to the type converter as a
   conversion input, and the converter will return a new object instance.
3. If there is no TypeConverter, a direct conversion to the property type is attempted. This final level is a
   direct conversion at the parser-native value between XAML language primitive types, or a check for the
   names of named constants in an enumeration (the parser then accesses the matching values).
Enumeration Attribute Values
Enumerations in XAML are processed intrinsically by XAML parsers, and the members of an enumeration should
be specified by specifying the string name of one of the enumeration's named constants.
For nonflag enumeration values, the native behavior is to process the string of an attribute value and resolve it
to one of the enumeration values. You do not specify the enumeration in the format Enumeration.Value, as you
do in code. Instead, you specify only Value, and Enumeration is inferred by the type of the property you are
setting. If you specify an attribute in the Enumeration.Value form, it will not resolve correctly.
For flagwise enumerations, the behavior is based on the Enum.Parse method. You can specify multiple values for
a flagwise enumeration by separating each value with a comma. However, you cannot combine enumeration
values that are not flagwise. For instance, you cannot use the comma syntax to attempt to create a Trigger that
acts on multiple conditions of a nonflag enumeration:
   <!--This will not compile, because Visibility is not a flagwise enumeration.-->
   ...
   <Trigger Property="Visibility" Value="Collapsed,Hidden">
     <Setter ... />
   </Trigger>
   ...
Flagwise enumerations that support attributes that are settable in XAML are rare in WPF. However, one such
enumeration is StyleSimulations. You could, for instance, use the comma-delimited flagwise attribute syntax to
modify the example provided in the Remarks for the Glyphs class; StyleSimulations = "BoldSimulation" could
become StyleSimulations = "BoldSimulation,ItalicSimulation" . KeyBinding.Modifiers is another property where
more than one enumeration value can be specified. However, this property happens to be a special case,
because the ModifierKeys enumeration supports its own type converter. The type converter for modifiers uses a
plus sign (+) as a delimiter rather than a comma (,). This conversion supports the more traditional syntax to
represent key combinations in Microsoft Windows programming, such as "Ctrl+Alt".
Properties and Event Member Name References
When specifying an attribute, you can reference any property or event that exists as a member of the CLR type
you instantiated for the containing object element.
Or, you can reference an attached property or attached event, independent of the containing object element.
(Attached properties are discussed in an upcoming section.)
You can also name any event from any object that is accessible through the default namespace by using a
typeName.event partially qualified name; this syntax supports attaching handlers for routed events where the
handler is intended to handle events routing from child elements, but the parent element does not also have
that event in its members table. This syntax resembles an attached event syntax, but the event here is not a true
attached event. Instead, you are referencing an event with a qualified name. For more information, see Routed
Events Overview.
For some scenarios, property names are sometimes provided as the value of an attribute, rather than the
attribute name. That property name can also include qualifiers, such as the property specified in the form
ownerType.dependencyPropertyName. This scenario is common when writing styles or templates in XAML. The
processing rules for property names provided as an attribute value are different, and are governed by the type
of the property being set or by the behaviors of particular WPF subsystems. For details, see Styling and
Templating.
Another usage for property names is when an attribute value describes a property-property relationship. This
feature is used for data binding and for storyboard targets, and is enabled by the PropertyPath class and its type
converter. For a more complete description of the lookup semantics, see PropertyPath XAML Syntax.
   <Button>
     <Button.ContextMenu>
       <ContextMenu>
         <MenuItem Header="1">First item</MenuItem>
         <MenuItem Header="2">Second item</MenuItem>
       </ContextMenu>
     </Button.ContextMenu>
     Right-click me!</Button>
The value within a property element can also be given as inner text, in cases where the property type being
specified is a primitive value type, such as String, or an enumeration where a name is specified. These two
usages are somewhat uncommon, because each of these cases could also use a simpler attribute syntax. One
scenario for filling a property element with a string is for properties that are not the XAML content property but
still are used for representation of UI text, and particular white-space elements such as linefeeds are required to
appear in that UI text. Attribute syntax cannot preserve linefeeds, but property element syntax can, so long as
significant white-space preservation is active (for details, see White space processing in XAML). Another
scenario is so that x:Uid Directive can be applied to the property element and thus mark the value within as a
value that should be localized in the WPF output BAML or by other techniques.
A property element is not represented in the WPF logical tree. A property element is just a particular syntax for
setting a property, and is not an element that has an instance or object backing it. (For details on the logical tree
concept, see Trees in WPF.)
For properties where both attribute and property element syntax are supported, the two syntaxes generally
have the same result, although subtleties such as white-space handling can vary slightly between syntaxes.
Collection Syntax
The XAML specification requires XAML processor implementations to identify properties where the value type is
a collection. The general XAML processor implementation in .NET is based on managed code and the CLR, and it
identifies collection types through one of the following:
   Type implements IList.
   Type implements IDictionary.
   Type derives from Array (for more information about arrays in XAML, see x:Array Markup Extension.)
If the type of a property is a collection, then the inferred collection type does not need to be specified in the
markup as an object element. Instead, the elements that are intended to become the items in the collection are
specified as one or more child elements of the property element. Each such item is evaluated to an object during
loading and added to the collection by calling the Add method of the implied collection. For example, the
Triggers property of Style takes the specialized collection type TriggerCollection, which implements IList. It is not
necessary to instantiate a TriggerCollection object element in the markup. Instead, you specify one or more
Trigger items as elements within the Style.Triggers property element, where Trigger (or a derived class) is the
type expected as the item type for the strongly typed and implicit TriggerCollection.
   <Style x:Key="SpecialButton" TargetType="{x:Type Button}">
     <Style.Triggers>
       <Trigger Property="Button.IsMouseOver" Value="true">
         <Setter Property = "Background" Value="Red"/>
       </Trigger>
       <Trigger Property="Button.IsPressed" Value="true">
         <Setter Property = "Foreground" Value="Green"/>
       </Trigger>
     </Style.Triggers>
   </Style>
A property may be both a collection type and the XAML content property for that type and derived types, which
is discussed in the next section of this topic.
An implicit collection element creates a member in the logical tree representation, even though it does not
appear in the markup as an element. Usually the constructor of the parent type performs the instantiation for
the collection that is one of its properties, and the initially empty collection becomes part of the object tree.
  NOTE
  The generic list and dictionary interfaces (IList<T> and IDictionary<TKey,TValue>) are not supported for collection
  detection. However, you can use the List<T> class as a base class, because it implements IList directly, or
  Dictionary<TKey,TValue> as a base class, because it implements IDictionary directly.
In the .NET Reference pages for collection types, this syntax with the deliberate omission of the object element
for a collection is occasionally noted in the XAML syntax sections as Implicit Collection Syntax.
With the exception of the root element, every object element in a XAML file that is nested as a child element of
another element is really an element that is one or both of the following cases: a member of an implicit
collection property of its parent element, or an element that specifies the value of the XAML content property
for the parent element (XAML content properties will be discussed in an upcoming section). In other words, the
relationship of parent elements and child elements in a markup page is really a single object at the root, and
every object element beneath the root is either a single instance that provides a property value of the parent, or
one of the items within a collection that is also a collection-type property value of the parent. This single-root
concept is common with XML, and is frequently reinforced in the behavior of APIs that load XAML such as Load.
The following example is a syntax with the object element for a collection (GradientStopCollection) specified
explicitly.
   <LinearGradientBrush>
     <LinearGradientBrush.GradientStops>
       <GradientStopCollection>
         <GradientStop Offset="0.0" Color="Red" />
         <GradientStop Offset="1.0" Color="Blue" />
       </GradientStopCollection>
     </LinearGradientBrush.GradientStops>
   </LinearGradientBrush>
Note that it is not always possible to explicitly declare the collection. For instance, attempting to declare
TriggerCollection explicitly in the previously shown Triggers example would fail. Explicitly declaring the collection
requires that the collection class must support a parameterless constructor, and TriggerCollection does not have
a parameterless constructor.
   <Button>I am a
     <Button.Background>Blue</Button.Background>
     blue button</Button>
This is illegal essentially because if this syntax were made explicit by using property element syntax for the
content property, then the content property would be set twice:
   <Button>
     <Button.Content>I am a </Button.Content>
     <Button.Background>Blue</Button.Background>
     <Button.Content> blue button</Button.Content>
   </Button>
A similarly illegal example is if the content property is a collection, and child elements are interspersed with
property elements:
   <StackPanel>
     <Button>This example</Button>
     <StackPanel.Resources>
       <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
     </StackPanel.Resources>
     <Button>... is illegal XAML</Button>
   </StackPanel>
Note that neither the property element for Children nor the element for the UIElementCollection is required in
the markup. This is a design feature of XAML so that recursively contained elements that define a UI are more
intuitively represented as a tree of nested elements with immediate parent-child element relationships, without
intervening property element tags or collection objects. In fact, UIElementCollection cannot be specified
explicitly in markup as an object element, by design. Because its only intended use is as an implicit collection,
UIElementCollection does not expose a public parameterless constructor and thus cannot be instantiated as an
object element.
Mixing Property Elements and Object Elements in an Object with a Content Property
The XAML specification declares that a XAML processor can enforce that object elements that are used to fill the
XAML content property within an object element must be contiguous, and must not be mixed. This restriction
against mixing property elements and content is enforced by the WPF XAML processors.
You can have a child object element as the first immediate markup within an object element. Then you can
introduce property elements. Or, you can specify one or more property elements, then content, then more
property elements. But once a property element follows content, you cannot introduce any further content, you
can only add property elements.
This content / property element order requirement does not apply to inner text used as content. However, it is
still a good markup style to keep inner text contiguous, because significant white space will be difficult to detect
visually in the markup if property elements are interspersed with inner text.
XAML Namespaces
None of the preceding syntax examples specified a XAML namespace other than the default XAML namespace.
In typical WPF applications, the default XAML namespace is specified to be the WPF namespace. You can specify
XAML namespaces other than the default XAML namespace and still use similar syntax. But then, anywhere
where a class is named that is not accessible within the default XAML namespace, that class name must be
preceded with the prefix of the XAML namespace as mapped to the corresponding CLR namespace. For
example, <custom:Example/> is object element syntax to instantiate an instance of the Example class, where the
CLR namespace containing that class (and possibly the external assembly information that contains backing
types) was previously mapped to the custom prefix.
For more information about XAML namespaces, see XAML Namespaces and Namespace Mapping for WPF
XAML.
Markup Extensions
XAML defines a markup extension programming entity that enables an escape from the normal XAML processor
handling of string attribute values or object elements, and defers the processing to a backing class. The
character that identifies a markup extension to a XAML processor when using attribute syntax is the opening
curly brace ({), followed by any character other than a closing curly brace (}). The first string following the
opening curly brace must reference the class that provides the particular extension behavior, where the
reference may omit the substring "Extension" if that substring is part of the true class name. Thereafter, a single
space may appear, and then each succeeding character is used as input by the extension implementation, up
until the closing curly brace is encountered.
The .NET XAML implementation uses the MarkupExtension abstract class as the basis for all of the markup
extensions supported by WPF as well as other frameworks or technologies. The markup extensions that WPF
specifically implements are often intended to provide a means to reference other existing objects, or to make
deferred references to objects that will be evaluated at run time. For example, a simple WPF data binding is
accomplished by specifying the {Binding} markup extension in place of the value that a particular property
would ordinarily take. Many of the WPF markup extensions enable an attribute syntax for properties where an
attribute syntax would not otherwise be possible. For example, a Style object is a relatively complex type that
contains a nested series of objects and properties. Styles in WPF are typically defined as a resource in a
ResourceDictionary, and then referenced through one of the two WPF markup extensions that request a
resource. The markup extension defers the evaluation of the property value to a resource lookup and enables
providing the value of the Style property, taking type Style, in attribute syntax as in the following example:
<Button Style="{StaticResource MyStyle}">My button</Button>
Here, StaticResource identifies the StaticResourceExtension class providing the markup extension
implementation. The next string MyStyle is used as the input for the non-default StaticResourceExtension
constructor, where the parameter as taken from the extension string declares the requested ResourceKey.
 MyStyle is expected to be the x:Key value of a Style defined as a resource. The StaticResource Markup Extension
usage requests that the resource be used to provide the Style property value through static resource lookup
logic at load time.
For more information about markup extensions, see Markup Extensions and WPF XAML. For a reference of
markup extensions and other XAML programming features enabled in the general .NET XAML implementation,
see XAML Namespace (x:) Language Features. For WPF-specific markup extensions, see WPF XAML Extensions.
Attached Properties
Attached properties are a programming concept introduced in XAML whereby properties can be owned and
defined by a particular type, but set as attributes or property elements on any element. The primary scenario
that attached properties are intended for is to enable child elements in a markup structure to report information
to a parent element without requiring an extensively shared object model across all elements. Conversely,
attached properties can be used by parent elements to report information to child elements. For more
information on the purpose of attached properties and how to create your own attached properties, see
Attached Properties Overview.
Attached properties use a syntax that superficially resembles property element syntax, in that you also specify a
typeName.propertyName combination. There are two important differences:
   You can use the typeName.propertyName combination even when setting an attached property through
   attribute syntax. Attached properties are the only case where qualifying the property name is a
   requirement in an attribute syntax.
   You can also use property element syntax for attached properties. However, for typical property element
   syntax, the typeName you specify is the object element that contains the property element. If you are
   referring to an attached property, then the typeName is the class that defines the attached property, not
   the containing object element.
Attached Events
Attached events are another programming concept introduced in XAML where events can be defined by a
specific type, but handlers may be attached on any object element. In the WOF implementation, often the type
that defines an attached event is a static type that defines a service, and sometimes those attached events are
exposed by a routed event alias in types that expose the service. Handlers for attached events are specified
through attribute syntax. As with attached events, the attribute syntax is expanded for attached events to allow a
typeName.eventName usage, where typeName is the class that provides Add and Remove event handler
accessors for the attached event infrastructure, and eventName is the event name.
   >                                                         End of object element for the root. Object is not closed yet
                                                             because the element contains child elements
   <Button Background="Blue">Background</Button>
   <Button Button.Background="Blue">Button.Background</Button>
   <Button Control.Background="Blue">Control.Background</Button>
Button.Background  works because the qualified lookup for that property on Button is successful (Background
was inherited from Control) and Button is the class of the object element or a base class. Control.Background
works because the Control class actually defines Background and Control is a Button base class.
However, the following typeName.memberName form example does not work and is thus shown commented:
Label is another derived class of Control, and if you had specified Label.Background within a Label object
element, this usage would have worked. However, because Label is not the class or base class of Button, the
specified XAML processor behavior is to then process Label.Background as an attached property.
 Label.Background is not an available attached property, and this usage fails.
   <Button>Control.Background PE
     <Control.Background>
       <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
         <GradientStop Color="Yellow" Offset="0.0" />
         <GradientStop Color="LimeGreen" Offset="1.0" />
       </LinearGradientBrush>
       </Control.Background>
   </Button>
Here, the property element was given as   Control.Background   even though the property element was contained
in Button .
But just like typeName.memberName form for attributes, baseTypeName.memberName is poor style in markup,
and you should avoid it.
See also
   XAML in WPF
   XAML Namespace (x:) Language Features
   WPF XAML Extensions
   Dependency Properties Overview
   TypeConverters and XAML
   XAML and Custom Classes for WPF
       Code-Behind and XAML in WPF
       11/21/2022 • 3 minutes to read • Edit Online
Code-behind is a term used to describe the code that is joined with markup-defined objects, when a XAML page
is markup-compiled. This topic describes requirements for code-behind as well as an alternative inline code
mechanism for code in XAML.
This topic contains the following sections:
   Prerequisites
   Code-Behind and the XAML Language
   Code-behind, Event Handler, and Partial Class Requirements in WPF
   x:Code
   Inline Code Limitations
Prerequisites
This topic assumes that you have read the XAML in WPF and have some basic knowledge of the CLR and object-
oriented programming.
x:Code
x:Code is a directive element defined in WPF schema) will not try to interpret the contents literally as XML.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="MyNamespace.MyCanvasCodeInline"
   >
     <Button Name="button1" Click="Clicked">Click Me!</Button>
     <x:Code><![CDATA[
       void Clicked(object sender, RoutedEventArgs e)
       {
           button1.Content = "Hello World";
       }
     ]]></x:Code>
   </Page>
See also
   XAML in WPF
   x:Code Intrinsic XAML Type
   Building a WPF Application
   XAML Syntax In Detail
       XAML and Custom Classes for WPF
       11/21/2022 • 11 minutes to read • Edit Online
XAML as implemented in common language runtime (CLR) frameworks supports the ability to define a custom
class or structure in any common language runtime (CLR) language, and then access that class using XAML
markup. You can use a mixture of Windows Presentation Foundation (WPF)-defined types and your custom
types within the same markup file, typically by mapping the custom types to a XAML namespace prefix. This
topic discusses the requirements that a custom class must satisfy to be usable as a XAML element.
   <Button>Hallo!
     <Button.Language>
       de-DE
     </Button.Language>
   </Button>
<Button Language="de-DE">Hallo!</Button>
Examples of properties where attribute syntax is allowed but property element syntax that contains an object
element is disallowed through XAML are various properties that take the Cursor type. The Cursor class has a
dedicated type converter CursorConverter, but does not expose a parameterless constructor, so the Cursor
property can only be set through attribute syntax even though the actual Cursor type is a reference type.
Per-Property Type Converters
Alternatively, the property itself may declare a type converter at the property level. This enables a "mini
language" that instantiates objects of the type of the property inline, by processing incoming string values of the
attribute as input for a ConvertFrom operation based on the appropriate type. Typically this is done to provide a
convenience accessor, and not as the sole means to enable setting a property in XAML. However, it is also
possible to use type converters for attributes where you want to use existing CLR types that do not supply either
a parameterless constructor or an attributed type converter. Examples from the WPF API are certain properties
that take the CultureInfo type. In this case, WPF used the existing Microsoft .NET Framework CultureInfo type to
better address compatibility and migration scenarios that were used in earlier versions of frameworks, but the
CultureInfo type did not support the necessary constructors or type-level type conversion to be usable as a
XAML property value directly.
Whenever you expose a property that has a XAML usage, particularly if you are a control author, you should
strongly consider backing that property with a dependency property. This is particularly true if you use the
existing Windows Presentation Foundation (WPF) implementation of the XAML processor, because you can
improve performance by using DependencyProperty backing. A dependency property will expose property
system features for your property that users will come to expect for a XAML accessible property. This includes
features such as animation, data binding, and style support. For more information, see Custom Dependency
Properties and XAML Loading and Dependency Properties.
Writing and Attributing a Type Converter
You occasionally will need to write a custom TypeConverter derived class to provide type conversion for your
property type. For instructions on how to derive from and create a type converter that can support XAML
usages, and how to apply the TypeConverterAttribute, see TypeConverters and XAML.
  NOTE
  It is possible to register handlers directly for routed events using AddHandler, and to deliberately not define a CLR event
  that exposes the routed event. This is not generally recommended because the event will not enable XAML attribute
  syntax for attaching handlers, and your resulting class will offer a less transparent XAML view of that type's capabilities.
  NOTE
  The generic List and Dictionary interfaces (IList<T> and IDictionary<TKey,TValue>) are not supported for collection
  detection by the WPF XAML processor. However, you can use the List<T> class as a base class, because it implements
  IList directly, or Dictionary<TKey,TValue> as a base class, because it implements IDictionary directly.
When you declare a property that takes a collection, be cautious about how that property value is initialized in
new instances of the type. If you are not implementing the property as a dependency property, then having the
property use a backing field that calls the collection type constructor is adequate. If your property is a
dependency property, then you may need to initialize the collection property as part of the default type
constructor. This is because a dependency property takes its default value from metadata, and you typically do
not want the initial value of a collection property to be a static, shared collection. There should be a collection
instance per each containing type instance. For more information, see Custom Dependency Properties.
You can implement a custom collection type for your collection property. Because of implicit collection property
treatment, the custom collection type does not need to provide a parameterless constructor in order to be used
in XAML implicitly. However, you can optionally provide a parameterless constructor for the collection type. This
can be a worthwhile practice. Unless you do provide a parameterless constructor, you cannot explicitly declare
the collection as an object element. Some markup authors might prefer to see the explicit collection as a matter
of markup style. Also, a parameterless constructor can simplify the initialization requirements when you create
new objects that use your collection type as a property value.
See also
   XAML in WPF
   Custom Dependency Properties
   Control Authoring Overview
   Base Elements Overview
   XAML Loading and Dependency Properties
       Markup Extensions and WPF XAML
       11/21/2022 • 10 minutes to read • Edit Online
This topic introduces the concept of markup extensions for XAML, including their syntax rules, purpose, and the
class object model that underlies them. Markup extensions are a general feature of the XAML language and of
the .NET implementation of XAML services. This topic specifically details markup extensions for use in WPF
XAML.
  NOTE
  The x: prefix is used for the typical XAML namespace mapping of the XAML language intrinsics, in the root element of a
  XAML file or production. For example, the Visual Studio templates for WPF applications initiate a XAML file using this x:
  mapping. You could choose a different prefix token in your own XAML namespace mapping, but this documentation will
  assume the default x: mapping as a means of identifying those entities that are a defined part of the XAML namespace
  for the XAML language, as opposed to the WPF default namespace or other XAML namespaces not related to a specific
  framework.
    StaticResource  provides a value for a property by substituting the value of an already defined resource.
   A StaticResource evaluation is ultimately made at XAML load time and does not have access to the
   object graph at run time. For details, see StaticResource Markup Extension.
    DynamicResource provides a value for a property by deferring that value to be a run-time reference to a
   resource. A dynamic resource reference forces a new lookup each time that such a resource is accessed
   and has access to the object graph at run time. In order to get this access, DynamicResource concept is
   supported by dependency properties in the WPF property system, and evaluated expressions. Therefore
   you can only use DynamicResource for a dependency property target. For details, see DynamicResource
   Markup Extension.
    Binding  provides a data bound value for a property, using the data context that applies to the parent
   object at run time. This markup extension is relatively complex, because it enables a substantial inline
   syntax for specifying a data binding. For details, see Binding Markup Extension.
    RelativeSource   provides source information for a Binding that can navigate several possible
   relationships in the run-time object tree. This provides specialized sourcing for bindings that are created
   in multi-use templates or created in code without full knowledge of the surrounding object tree. For
   details, see RelativeSource MarkupExtension.
    TemplateBinding  enables a control template to use values for templated properties that come from
   object-model-defined properties of the class that will use the template. In other words, the property
   within the template definition can access a context that only exists once the template is applied. For
   details, see TemplateBinding Markup Extension. For more information on the practical use of
    TemplateBinding , see Styling with ControlTemplates Sample.
     NOTE
     A XAML processor must call the constructor that matches the argument count of the number of pairs. For this
     reason, if you are implementing a custom markup extension, do not provide multiple constructors with the same
     argument count. The behavior for how a XAML processor behaves if more than one markup extension constructor
     path with the same parameter count exists is not defined, but you should anticipate that a XAML processor is
     permitted to throw an exception on usage if this situation exists in the markup extension type definitions.
   If the individual separated tokens contain equals signs, then a XAML processor first calls the
   parameterless constructor for the markup extension. Then, each name=value pair is interpreted as a
   property name that exists on the markup extension, and a value to assign to that property.
   If there is a parallel result between the constructor behavior and the property setting behavior in a
   markup extension, it does not matter which behavior you use. It is more common usage to use the
   property = value pairs for markup extensions that have more than one settable property, if only because
   it makes your markup more intentional and you are less likely to accidentally transpose constructor
   parameters. (When you specify property=value pairs, those properties may be in any order.) Also, there is
   no guarantee that a markup extension supplies a constructor parameter that sets every one of its settable
   properties. For example, Binding is a markup extension, with many properties that are settable through
   the extension in property = value form, but Binding only supports two constructors: a parameterless
   constructor, and one that sets an initial path.
   A literal comma cannot be passed to a markup extension without escapement.
   <Setter Property="Background"
     Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
In this usage, the x:Static statement is evaluated first and returns a string. That string is then used as the
argument for DynamicResource .
See also
   XAML in WPF
   XAML Namespace (x:) Language Features
WPF XAML Extensions
StaticResource Markup Extension
Binding Markup Extension
DynamicResource Markup Extension
x:Type Markup Extension
       XAML Namespaces and Namespace Mapping for
       WPF XAML
       11/21/2022 • 7 minutes to read • Edit Online
This topic further explains the presence and purpose of the two XAML namespace mappings as often found in
the root tag of a WPF XAML file. It also describes how to produce similar mappings for using elements that are
defined in your own code, and/or within separate assemblies.
The second declaration maps a separate XAML namespace, mapping it (typically) to the      x:   prefix.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
The relationship between these declarations is that the x: prefix mapping supports the intrinsics that are part
of the XAML language definition, and WPF is one implementation that uses XAML as a language and defines a
vocabulary of its objects for XAML. Because the WPF vocabulary's usages will be far more common than the
XAML intrinsics usages, the WPF vocabulary is mapped as the default.
The x: prefix convention for mapping the XAML language intrinsics support is followed by project templates,
sample code, and the documentation of language features within this SDK. The XAML namespace defines many
commonly-used features that are necessary even for basic WPF applications. For instance, in order to join any
code-behind to a XAML file through a partial class, you must name that class as the x:Class attribute in the
root element of the relevant XAML file. Or, any element as defined in a XAML page that you wish to access as a
keyed resource should have the x:Key attribute set on the element in question. For more information on these
and other aspects of XAML see XAML in WPF or XAML Syntax In Detail.
   namespace SDKSample {
       public class ExampleClass : ContentControl {
           public ExampleClass() {
           ...
           }
       }
   }
   Namespace SDKSample
       Public Class ExampleClass
           Inherits ContentControl
            ...
           Public Sub New()
           End Sub
       End Class
   End Namespace
This custom class is then compiled into a library, which per the project settings (not shown) is named
 SDKSampleLibrary .
In order to reference this custom class, you also need to include it as a reference for your current project, which
you would typically do using the Solution Explorer UI in Visual Studio.
Now that you have a library containing a class, and a reference to it in project settings, you can add the
following prefix mapping as part of your root element in XAML:
xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary"
To put it all together, the following is XAML that includes the custom mapping along with the typical default and
x: mappings in the root tag, then uses a prefixed reference to instantiate ExampleClass in that UI:
   <Page x:Class="WPFApplication1.MainPage"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary">
     ...
     <custom:ExampleClass/>
   ...
   </Page>
Custom classes cannot be used as the root element of a page if defined in the same assembly. Partial classes do
not need to be mapped; only classes that are not the partial class of a page in your application need to be
mapped if you intend to reference them as elements in XAML.
The XmlnsDefinitionAttribute takes two parameters: the XML/XAML namespace name, and the CLR namespace
name. More than one XmlnsDefinitionAttribute can exist to map multiple CLR namespaces to the same XML
namespace. Once mapped, members of those namespaces can also be referenced without full qualification if
desired by providing the appropriate using statement in the partial-class code-behind page. For more details,
see XmlnsDefinitionAttribute.
See also
   Understanding XML Namespaces
   XAML in WPF
       WPF XAML Namescopes
       11/21/2022 • 8 minutes to read • Edit Online
XAML namescopes are a concept that identifies objects that are defined in XAML. The names in a XAML
namescope can be used to establish relationships between the XAML-defined names of objects and their
instance equivalents in an object tree. Typically, XAML namescopes in WPF managed code are created when
loading the individual XAML page roots for a XAML application. XAML namescopes as the programming object
are defined by the INameScope interface and are also implemented by the practical class NameScope.
  NOTE
  WPF build actions create a XAML namescope for a XAML production even if no   Name   or   x:Name   attributes are defined
  on any elements in the XAML markup.
If you try to use the same name twice in any XAML namescope, an exception is raised. For WPF XAML that has
code-behind and is part of a compiled application, the exception is raised at build time by WPF build actions,
when creating the generated class for the page during the initial markup compile. For XAML that is not markup-
compiled by any build action, exceptions related to XAML namescope issues might be raised when the XAML is
loaded. XAML designers might also anticipate XAML namescope issues at design time.
Adding Objects to Runtime Object Trees
The moment that XAML is parsed represents the moment in time that a WPF XAML namescope is created and
defined. If you add an object to an object tree at a point in time after the XAML that produced that tree was
parsed, a Name or x:Name value on the new object does not automatically update the information in a XAML
namescope. To add a name for an object into a WPF XAML namescope after XAML is loaded, you must call the
appropriate implementation of RegisterName on the object that defines the XAML namescope, which is typically
the XAML page root. If the name is not registered, the added object cannot be referenced by name through
methods such as FindName, and you cannot use that name for animation targeting.
The most common scenario for application developers is that you will use RegisterName to register names into
the XAML namescope on the current root of the page. RegisterName is part of an important scenario for
storyboards that target objects for animations. For more information, see Storyboards Overview.
If you call RegisterName on an object other than the object that defines the XAML namescope, the name is still
registered to the XAML namescope that the calling object is held within, as if you had called RegisterName on
the XAML namescope defining object.
XAML Namescopes in Code
You can create and then use XAML namescopes in code. The APIs and the concepts involved in XAML
namescope creation are the same even for a pure code usage, because the XAML processor for WPF uses these
APIs and concepts when it processes XAML itself. The concepts and API exist mainly for the purpose of being
able to find objects by name within an object tree that is typically defined partially or entirely in XAML.
For applications that are created programmatically, and not from loaded XAML, the object that defines a XAML
namescope must implement INameScope, or be a FrameworkElement or FrameworkContentElement derived
class, in order to support creation of a XAML namescope on its instances.
Also, for any element that is not loaded and processed by a XAML processor, the XAML namescope for the object
is not created or initialized by default. You must explicitly create a new XAML namescope for any object that you
intend to register names into subsequently. To create a XAML namescope, you call the static SetNameScope
method. Specify the object that will own it as the dependencyObject parameter, and a new NameScope
constructor call as the value parameter.
If the object provided as dependencyObject for SetNameScope is not a INameScope implementation,
FrameworkElement or FrameworkContentElement, calling RegisterName on any child elements will have no
effect. If you fail to create the new XAML namescope explicitly, then calls to RegisterName will raise an exception.
For an example of using XAML namescope APIs in code, see Define a Name Scope.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     >
     <Page.Resources>
       <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
         <Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
           <ContentPresenter/>
         </Border>
       </ControlTemplate>
     </Page.Resources>
     <StackPanel>
       <Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
       <Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
     </StackPanel>
   </Page>
Here, the same template is applied to two different buttons. If templates did not have discrete XAML
namescopes, the TheBorder name used in the template would cause a name collision in the XAML namescope.
Each instantiation of the template has its own XAML namescope, so in this example each instantiated template's
XAML namescope would contain exactly one name.
Styles also define their own XAML namescope, mostly so that parts of storyboards can have particular names
assigned. These names enable control specific behaviors that will target elements of that name, even if the
template was re-defined as part of control customization.
Because of the separate XAML namescopes, finding named elements in a template is more challenging than
finding a non-templated named element in a page. You first need to determine the applied template, by getting
the Template property value of the control where the template is applied. Then, you call the template version of
FindName, passing the control where the template was applied as the second parameter.
If you are a control author and you are generating a convention where a particular named element in an applied
template is the target for a behavior that is defined by the control itself, you can use the GetTemplateChild
method from your control implementation code. The GetTemplateChild method is protected, so only the control
author has access to it.
If you are working from within a template, and need to get to the XAML namescope where the template is
applied, get the value of TemplatedParent, and then call FindName there. An example of working within the
template would be if you are writing the event handler implementation where the event will be raised from an
element in an applied template.
See also
  XAML Namespaces and Namespace Mapping for WPF XAML
  x:Name Directive
        Inline Styles and Templates
        11/21/2022 • 2 minutes to read • Edit Online
XAML that take the types Style and FrameworkTemplate almost always make resource references to existing
styles and templates rather than define new ones inline.
The attribute usage is much more common. A style that is defined inline and not defined in resources is
necessarily scoped to the containing element only, and cannot be re-used as easily because it has no resource
key. In general a resource-defined style is more versatile and useful, and is more in keeping with the general
Windows Presentation Foundation (WPF) programming model principle of separating program logic in code
from design in markup.
Usually there is no reason to set a style or template inline, even if you only intend to use that style or template in
that location. Most elements that can take a style or template also support a content property and a content
model. If you are only using whatever logical tree you create through styling or templating once, it would be
even easier to just fill that content property with the equivalent child elements in direct markup. This would
bypass the style and template mechanisms altogether.
Other syntaxes enabled by markup extensions that return an object are also possible for styles and templates.
Two such extensions that have possible scenarios include TemplateBinding and Binding.
See also
     Styling and Templating
       TypeConverters and XAML
       11/21/2022 • 10 minutes to read • Edit Online
This topic introduces the purpose of type conversion from string as a general XAML language feature. In the
.NET Framework, the TypeConverter class serves a particular purpose as part of the implementation for a
managed custom class that can be used as a property value in XAML attribute usage. If you write a custom class,
and you want instances of your class to be usable as XAML settable attribute values, you might need to apply a
TypeConverterAttribute to your class, write a custom TypeConverter class, or both.
   <LinearGradientBrush>
     <LinearGradientBrush.StartPoint>
       <Point X="0" Y="0"/>
     </LinearGradientBrush.StartPoint>
     <LinearGradientBrush.EndPoint>
       <Point X="1" Y="1"/>
     </LinearGradientBrush.EndPoint>
   </LinearGradientBrush>
Whether to use the type conversion string or a more verbose equivalent syntax is generally a coding style
choice. Your XAML tooling workflow might also influence how values are set. Some XAML tools tend to emit the
most verbose form of the markup because it is easier to round-trip to designer views or its own serialization
mechanism.
Existing type converters can generally be discovered on WPF and .NET Framework types by checking a class (or
property) for the presence of an applied TypeConverterAttribute. This attribute will name the class that is the
supporting type converter for values of that type, for XAML purposes as well as potentially other purposes.
Type Converters and Markup Extensions
Markup extensions and type converters fill orthogonal roles in terms of XAML processor behavior and the
scenarios that they are applied to. Although context is available for markup extension usages, type conversion
behavior of properties where a markup extension provides a value is generally is not checked in the markup
extension implementations. In other words, even if a markup extension returns a text string as its ProvideValue
output, type conversion behavior on that string as applied to a specific property or property value type is not
invoked, Generally, the purpose of a markup extension is to process a string and return an object without any
type converter involved.
One common situation where a markup extension is necessary rather than a type converter is to make a
reference to an object that already exists. At best, a stateless type converter could only generate a new instance,
which might not be desirable. For more information on markup extensions, see Markup Extensions and WPF
XAML.
Native Type Converters
In the WPF and .NET Framework implementation of the XAML parser, there are certain types that have native
type conversion handling, yet are not types that might conventionally be thought of as primitives. An example of
such a type is DateTime. The reason for this is based on how the .NET Framework architecture works: the type
DateTime is defined in mscorlib, the most basic library in .NET. DateTime is not permitted to be attributed with
an attribute that comes from another assembly that introduces a dependency (TypeConverterAttribute is from
System) so the usual type converter discovery mechanism by attributing cannot be supported. Instead, the
XAML parser has a list of types that need such native processing and processes these similarly to how the true
primitives are processed. (In the case of DateTime this involves a call to Parse.)
  NOTE
  Do not use the curly brace characters, particularly {, as a possible element of your string format. These characters are
  reserved as the entry and exit for a markup extension sequence.
Implementing ConvertTo
ConvertTo is potentially used for serialization support. Serialization support through ConvertTo for your custom
type and its type converter is not an absolute requirement. However, if you are implementing a control, or using
serialization of as part of the features or design of your class, you should implement ConvertTo.
To be usable as a TypeConverter implementation that supports XAML, the ConvertTo method for that converter
must accept an instance of the type (or a value) being supported as the value parameter. When the
 destinationType parameter is the type String, then the returned object must be able to be cast as String. The
returned string must represent a serialized value of value . Ideally, the serialization format you choose should
be capable of generating the same value if that string were passed to the ConvertFrom implementation of the
same converter, without significant loss of information.
If the value cannot be serialized, or the converter does not support serialization, the ConvertTo implementation
must return null , and is permitted to throw an exception in this case. But if you do throw exceptions, you
should report the inability to use that conversion as part of your CanConvertTo implementation so that the best
practice of checking with CanConvertTo first to avoid exceptions is supported.
If destinationType parameter is not of type String, you can choose your own converter handling. Typically, you
would revert to base implementation handling, which in the basemost ConvertTo raises a specific exception.
Implementing CanConvertTo
Your CanConvertTo implementation should return      true   for    destinationType    of type String, and otherwise
defer to the base implementation.
Implementing CanConvertFrom
Your CanConvertFrom implementation should return       true      for   sourceType   of type String, and otherwise defer
to the base implementation.
See also
   TypeConverter
   XAML in WPF
   Markup Extensions and WPF XAML
   XAML Syntax In Detail
      WPF XAML Extensions
     11/21/2022 • 2 minutes to read • Edit Online
In This Section
Binding Markup Extension
ColorConvertedBitmap Markup Extension
ComponentResourceKey Markup Extension
DynamicResource Markup Extension
RelativeSource MarkupExtension
StaticResource Markup Extension
TemplateBinding Markup Extension
ThemeDictionary Markup Extension
PropertyPath XAML Syntax
PresentationOptions:Freeze Attribute
          Binding Markup Extension
          11/21/2022 • 8 minutes to read • Edit Online
Defers a property value to be a data-bound value, creating an intermediate expression object and interpreting
the data context that applies to the element and its binding at run time.
Syntax Notes
In these syntaxes, the [] and * are not literals. They are part of a notation to indicate that zero or more
bindProp = value pairs can be used, with a , separator between them and preceding bindProp = value pairs.
Any of the properties listed in the "Binding Properties That Can Be Set with the Binding Extension" section could
instead be set using attributes of a Binding object element. However, that is not truly the markup extension
usage of Binding, it is just the general XAML processing of attributes that set properties of the CLR Binding class.
In other words, <Binding bindProp1 =" value1 "[ bindPropN =" valueN "]*/> is an equivalent syntax for
attributes of Binding object element usage instead of a Binding expression usage. To learn about the XAML
attribute usage of specific properties of Binding, see the "XAML Attribute Usage" section of the relevant property
of Binding in the .NET Framework Class Library.
XAML Values
  VA L UE                                                     DESC RIP T IO N
   bindProp1, bindPropN                                       The name of the Binding or BindingBase property to set. Not
                                                              all Binding properties can be set with the Binding
                                                              extension, and some properties are settable within a
                                                               Binding expression only by using further nested markup
                                                              extensions. See "Binding Properties That Can Be Set with the
                                                              Binding Extension" section.
   value1, valueN                                             The value to set the property to. The handling of the
                                                              attribute value is ultimately specific to the type and logic of
                                                              the specific Binding property being set.
   path                                                       The path string that sets the implicit Binding.Path property.
                                                              See also PropertyPath XAML Syntax.
Unqualified {Binding}
The {Binding} usage shown in "Binding Expression Usage" creates a Binding object with default values, which
includes an initial Binding.Path of null . This is still useful in many scenarios, because the created Binding might
be relying on key data binding properties such as Binding.Path and Binding.Source being set in the run-time
data context. For more information on the concept of data context, see Data Binding.
Implicit Path
The Binding markup extension uses Binding.Path as a conceptual "default property", where Path= does not
need to appear in the expression. If you specify a Binding expression with an implicit path, the implicit path
must appear first in the expression, prior to any other bindProp = value pairs where the Binding property is
specified by name. For example: {Binding PathString} , where PathString is a string that is evaluated to be the
value of Binding.Path in the Binding created by the markup extension usage. You can append an implicit path
with other named properties after the comma separator, for example, {Binding LastName, Mode=TwoWay} .
Remarks
  IMPORTANT
  In terms of dependency property precedence, a Binding expression is equivalent to a locally set value. If you set a local
  value for a property that previously had a Binding expression, the Binding is completely removed. For details, see
  Dependency Property Value Precedence.
Describing data binding at a basic level is not covered in this topic. See Data Binding Overview.
  NOTE
  MultiBinding and PriorityBinding do not support a XAML extension syntax. You would instead use property elements. See
  reference topics for MultiBinding and PriorityBinding.
Boolean values for XAML are case insensitive. For example you could specify either
 {Binding NotifyOnValidationError=true} or {Binding NotifyOnValidationError=True} .
Bindings that involve data validation are typically specified by an explicit Binding element rather than as a
 {Binding ...} expression, and setting ValidatesOnDataErrors or ValidatesOnExceptions in an expression is
uncommon. This is because the companion property ValidationRules cannot be readily set in the expression
form. For more information, see Implement Binding Validation.
Binding  is a markup extension. Markup extensions are typically implemented when there is a requirement to
escape attribute values to be other than literal values or handler names, and the requirement is more global
than type converters attributed on certain types or properties. All markup extensions in XAML use the { and
 } characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a
markup extension must process the string contents. For more information, see Markup Extensions and WPF
XAML.
Binding  is an atypical markup extension in that the Binding class that implements the extension functionality
for WPF's XAML implementation also implements several other methods and properties that are not related to
XAML. The other members are intended to make Binding a more versatile and self-contained class that can
address many data binding scenarios in addition to functioning as a XAML markup extension.
See also
   Binding
   Data Binding Overview
   XAML in WPF
   Markup Extensions and WPF XAML
        ColorConvertedBitmap Markup Extension
        11/21/2022 • 2 minutes to read • Edit Online
Provides a way to specify a bitmap source that does not have an embedded profile. Color contexts / profiles are
specified by URI, as is the image source URI.
XAML Values
  VA L UE                                                   DESC RIP T IO N
Remarks
This markup extension is intended to fill a related set of image-source property values such as UriSource.
Attribute syntax is the most common syntax used with this markup extension. ColorConvertedBitmap (or
 ColorConvertedBitmapExtension ) cannot be used in property element syntax, because the values can only be set
as values on the initial constructor, which is the string following the extension identifier.
ColorConvertedBitmap    is a markup extension. Markup extensions are typically implemented when there is a
requirement to escape attribute values to be other than literal values or handler names, and the requirement is
more global than just putting type converters on certain types or properties. All markup extensions in XAML use
the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes
that a markup extension must process the attribute. For more information, see Markup Extensions and WPF
XAML.
See also
   UriSource
   Markup Extensions and WPF XAML
   Imaging Overview
        ComponentResourceKey Markup Extension
        11/21/2022 • 3 minutes to read • Edit Online
Defines and references keys for resources that are loaded from external assemblies. This enables a resource
lookup to specify a target type in an assembly, rather than an explicit resource dictionary in an assembly or on a
class.
XAML Values
  VA L UE                                                    DESC RIP T IO N
   targetID                                                  The key for the resource. When resources are looked up,
                                                              targetID will be analogous to the x:Key Directive of the
                                                             resource.
Remarks
As seen in the usages above, a { ComponentResourceKey } markup extension usage is found in two places:
   The definition of a key within a theme resource dictionary, as provided by a control author.
   Accessing a theme resource from the assembly, when you are retemplating the control but want to use
   property values that come from resources provided by the control's themes.
For referencing component resources that come from themes, it is generally recommended that you use
{DynamicResource}  rather than {StaticResource} . This is shown in the usages. {DynamicResource} is
recommended because the theme itself can be changed by the user. If you want the component resource that
most closely matches the control author's intent for supporting a theme, you should enable your component
resource reference to be dynamic also.
The TypeInTargetAssembly identifies a type that exists in the target assembly where the resource is actually
defined. A ComponentResourceKey can be defined and used independently of knowing exactly where the
TypeInTargetAssembly is defined, but eventually must resolve the type through referenced assemblies.
A common usage for ComponentResourceKey is to define keys that are then exposed as members of a class. For
this usage, you use the ComponentResourceKey class constructor, not the markup extension. For more
information, see ComponentResourceKey, or the "Defining and Referencing Keys for Theme Resources" section
of the topic Control Authoring Overview.
For both establishing keys and referencing keyed resources, attribute syntax is commonly used for the
 ComponentResourceKey markup extension.
The compact syntax shown relies on the ComponentResourceKey constructor signature and positional
parameter usage of a markup extension. The order in which the targetTypeName and targetID are given is
important. The verbose syntax relies on the ComponentResourceKey parameterless constructor, and then sets
the TypeInTargetAssembly and ResourceId in a way that is analogous to a true attribute syntax on an object
element. In the verbose syntax, the order in which the properties are set is not important. The relationship and
mechanisms of these two alternatives (compact and verbose) is described in more detail in the topic Markup
Extensions and WPF XAML.
Technically, the value for targetID can be any object, it does not have to be a string. However, the most
common usage in WPF is to align the targetID value with forms that are strings, and where such strings are
valid in the XamlName Grammar.
ComponentResourceKey can be used in object element syntax. In this case, specifying the value of both the
TypeInTargetAssembly and ResourceId properties is required to properly initialize the extension.
In the WPF XAML reader implementation, the handling for this markup extension is defined by the
ComponentResourceKey class.
ComponentResourceKey    is a markup extension. Markup extensions are typically implemented when there is a
requirement to escape attribute values to be other than literal values or handler names, and the requirement is
more global than just putting type converters on certain types or properties. All markup extensions in XAML use
the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes
that a markup extension must process the attribute. For more information, see Markup Extensions and WPF
XAML.
See also
   ComponentResourceKey
   ControlTemplate
   Control Authoring Overview
   XAML in WPF
   Markup Extensions and WPF XAML
       DateTime XAML Syntax
       11/21/2022 • 3 minutes to read • Edit Online
Some controls, such as Calendar and DatePicker, have properties that use the DateTime type. Although you
typically specify an initial date or time for these controls in the code-behind at run time, you can specify an initial
date or time in XAML. The WPF XAML parser handles parsing of DateTime values using a built-in XAML text
syntax. This topic describes the specifics of the DateTime XAML text syntax.
  IMPORTANT
  The DateTime XAML syntax always uses en-us as the CultureInfo for its native conversion. This is not influenced by
  Language value or xml:lang value in the XAML, because XAML attribute-level type conversion acts without that
  context. Do not attempt to interpolate the format strings shown here due to cultural variations, such as the order in
  which day and month appear. The format strings shown here are the exact format strings used when parsing the XAML
  regardless of other culture settings.
The following sections describe some of the common DateTime format strings.
Short Date Pattern ("d")
The following shows the short date format for a DateTime in XAML:
M/d/YYYY
This is the simplest form that specifies all necessary information for typical usages by WPF controls, and cannot
be influenced by accidental time zone offsets versus a time component, and is therefore recommended over the
other formats.
For example, to specify the date of June 1, 2010, use the following string:
3/1/2010
For example, to specify the date of June 1, 2010, use the following string (time components are all entered as 0):
2010-06-01T000:00:00
For example, to specify the date of June 1, 2010, use the following string (time components are all entered as 0):
Mon, 01 Jun 2010 00:00:00 UTC
See also
   XAML in WPF
         DynamicResource Markup Extension
         11/21/2022 • 3 minutes to read • Edit Online
Provides a value for any XAML property attribute by deferring that value to be a reference to a defined resource.
Lookup behavior for that resource is analogous to run-time lookup.
XAML Values
  VA L UE                                                        DESC RIP T IO N
   key                                                           The key for the requested resource. This key was initially
                                                                 assigned by the x:Key Directive if a resource was created in
                                                                 markup, or was provided as the key parameter when
                                                                 calling ResourceDictionary.Add if the resource was created in
                                                                 code.
Remarks
A DynamicResource will create a temporary expression during the initial compilation and thus defer lookup for
resources until the requested resource value is actually required in order to construct an object. This may
potentially be after the XAML page is loaded. The resource value will be found based on key search against all
active resource dictionaries starting from the current page scope, and is substituted for the placeholder
expression from compilation.
  IMPORTANT
  In terms of dependency property precedence, a DynamicResource expression is equivalent to the position where the
  dynamic resource reference is applied. If you set a local value for a property that previously had a DynamicResource
  expression as the local value, the DynamicResource is completely removed. For details, see Dependency Property Value
  Precedence.
Certain resource access scenarios are particularly appropriate for DynamicResource as opposed to a
StaticResource Markup Extension. See XAML Resources for a discussion about the relative merits and
performance implications of DynamicResource and StaticResource .
The specified ResourceKey should correspond to an existing resource determined by x:Key Directive at some
level in your page, application, the available control themes and external resources, or system resources, and the
resource lookup will happen in that order. For more information about resource lookup for static and dynamic
resources, see XAML Resources.
A resource key may be any string defined in the XamlName Grammar. A resource key may also be other object
types, such as a Type. A Type key is fundamental to how controls can be styled by themes. For more information,
see Control Authoring Overview.
APIs for lookup of resource values, such as FindResource, follow the same resource lookup logic as used by
 DynamicResource .
The verbose usage is often useful for extensions that have more than one settable property, or if some
properties are optional. Because DynamicResource has only one settable property, which is required, this verbose
usage is not typical.
In the WPF XAML processor implementation, the handling for this markup extension is defined by the
DynamicResourceExtension class.
DynamicResource   is a markup extension. Markup extensions are typically implemented when there is a
requirement to escape attribute values to be other than literal values or handler names, and the requirement is
more global than just putting type converters on certain types or properties. All markup extensions in XAML use
the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes
that a markup extension must process the attribute. For more information, see Markup Extensions and WPF
XAML.
See also
   XAML Resources
   Resources and Code
   x:Key Directive
   XAML in WPF
   Markup Extensions and WPF XAML
   StaticResource Markup Extension
   Markup Extensions and WPF XAML
        RelativeSource MarkupExtension
        11/21/2022 • 4 minutes to read • Edit Online
Specifies properties of a RelativeSource binding source, to be used within a Binding Markup Extension, or when
setting the RelativeSource property of a Binding element established in XAML.
-or-
   <Binding>
     <Binding.RelativeSource>
       <RelativeSource
          Mode="FindAncestor"
          AncestorType="{x:Type typeName}"
          AncestorLevel="intLevel"
       />
     </Binding.RelativeSource>
   </Binding>
XAML Values
  VA L UE                                                  DESC RIP T IO N
  VA L UE                                                    DESC RIP T IO N
Remarks
{RelativeSource TemplatedParent}    binding usages are a key technique that addresses a larger concept of the
separation of a control's UI and a control's logic. This enables binding from within the template definition to the
templated parent (the run time object instance where the template is applied). For this case, the TemplateBinding
Markup Extension is in fact a shorthand for the following binding expression:
 {Binding RelativeSource={RelativeSource TemplatedParent}} . TemplateBinding or
 {RelativeSource TemplatedParent} usages are both only relevant within the XAML that defines a template. For
more information, see TemplateBinding Markup Extension.
{RelativeSource FindAncestor}    is mainly used in control templates or predictable self-contained UI
compositions, for cases where a control is always expected to be in a visual tree of a certain ancestor type. For
example, items of an items control might use FindAncestor usages to bind to properties of their items control
parent ancestor. Or, elements that are part of control composition in a template can use FindAncestor bindings
to the parent elements in that same composition structure.
In the object element syntax for FindAncestor mode shown in the XAML Syntax sections, the second object
element syntax is used specifically for FindAncestor mode. FindAncestor mode requires an AncestorType value.
You must set AncestorType as an attribute using an x:Type Markup Extension reference to the type of ancestor to
look for. The AncestorType value is used when the binding request is processed at run-time.
For FindAncestor mode, the optional property AncestorLevel can help disambiguate the ancestor lookup in
cases where there is possibly more than one ancestor of that type existing in the element tree.
For more information on how to use the    FindAncestor   mode, see RelativeSource.
{RelativeSource Self}     is useful for scenarios where one property of an instance should depend on the value of
another property of the same instance, and no general dependency property relationship (such as coercion)
already exists between those two properties. Although it is rare that two properties exist on an object such that
the values are literally identical (and are identically typed), you can also apply a Converter parameter to a
binding that has {RelativeSource Self} , and use the converter to convert between source and target types.
Another scenario for {RelativeSource Self} is as part of a MultiDataTrigger.
For example, the following XAML defines a Rectangle element such that no matter what value is entered for
Width, the Rectangle is always a square:
<Rectangle Width="200" Height="{Binding RelativeSource={RelativeSource Self}, Path=Width}" .../>
 {RelativeSource PreviousData} is useful either in data templates, or in cases where bindings are using a
collection as the data source. You can use {RelativeSource PreviousData} to highlight relationships between
adjacent data items in the collection. A related technique is to establish a MultiBinding between the current and
previous items in the data source, and use a converter on that binding to determine the difference between the
two items and their properties.
In the following example, the first TextBlock in the items template displays the current number. The second
TextBlock binding is a MultiBinding that nominally has two Binding constituents: the current record, and a
binding that deliberately uses the previous data record by using {RelativeSource PreviousData} . Then, a
converter on the MultiBinding calculates the difference and returns it to the binding.
   <ListBox Name="fibolist">
       <ListBox.ItemTemplate>
           <DataTemplate>
               <StackPanel Orientation="Horizontal">
               <TextBlock Text="{Binding}"/>
               <TextBlock>, difference = </TextBlock>
                   <TextBlock>
                       <TextBlock.Text>
                           <MultiBinding Converter="{StaticResource DiffConverter}">
                                <Binding/>
                                <Binding RelativeSource="{RelativeSource PreviousData}"/>
                           </MultiBinding>
                       </TextBlock.Text>
                   </TextBlock>
               </StackPanel>
           </DataTemplate>
       </ListBox.ItemTemplate>
   </ListBox>
Describing data binding as a concept is not covered here, see Data Binding Overview.
In the WPF XAML processor implementation, the handling for this markup extension is defined by the
RelativeSource class.
 RelativeSource is a markup extension. Markup extensions are typically implemented when there is a
requirement to escape attribute values to be other than literal values or handler names, and the requirement is
more global than just putting type converters on certain types or properties. All markup extensions in XAML use
the { and } characters in their attribute syntax, which is the convention by which a XAML processor
recognizes that a markup extension must process the attribute. For more information, see Markup Extensions
and WPF XAML.
See also
   Binding
   Styling and Templating
   XAML in WPF
   Markup Extensions and WPF XAML
   Data Binding Overview
   Binding Declarations Overview
x:Type Markup Extension
         StaticResource Markup Extension
         11/21/2022 • 2 minutes to read • Edit Online
Provides a value for any XAML property attribute by looking up a reference to an already defined resource.
Lookup behavior for that resource is analogous to load-time lookup, which will look for resources that were
previously loaded from the markup of the current XAML page as well as other application sources, and will
generate that resource value as the property value in the run-time objects.
XAML Values
  VA L UE                                                          DESC RIP T IO N
   key                                                             The key for the requested resource. This key was initially
                                                                   assigned by the x:Key Directive if a resource was created in
                                                                   markup, or was provided as the key parameter when
                                                                   calling ResourceDictionary.Add if the resource was created in
                                                                   code.
Remarks
  IMPORTANT
  A StaticResource must not attempt to make a forward reference to a resource that is defined lexically further within
  the XAML file. Attempting to do so is not supported, and even if such a reference does not fail, attempting the forward
  reference will incur a load time performance penalty when the internal hash tables representing a ResourceDictionary are
  searched. For best results, adjust the composition of your resource dictionaries such that forward references can be
  avoided. If you cannot avoid a forward reference, use DynamicResource Markup Extension instead.
The specified ResourceKey should correspond to an existing resource, identified with an x:Key Directive at some
level in your page, application, the available control themes and external resources, or system resources. The
resource lookup occurs in that order. For more information about resource lookup behavior for static and
dynamic resources, see XAML Resources.
A resource key can be any string defined in the XamlName Grammar. A resource key can also be other object
types, such as a Type. A Type key is fundamental to how controls can be styled by themes, through an implicit
style key. For more information, see Control Authoring Overview.
The alternative declarative means of referencing a resource is as a DynamicResource Markup Extension.
Attribute syntax is the most common syntax used with this markup extension. The string token provided after
the StaticResource identifier string is assigned as the ResourceKey value of the underlying
StaticResourceExtension extension class.
StaticResource   can be used in object element syntax. In this case, specifying the value of the ResourceKey
property is required.
StaticResource can also be used in a verbose attribute usage that specifies the ResourceKey property as a
property=value pair:
The verbose usage is often useful for extensions that have more than one settable property, or if some
properties are optional. Because StaticResource has only one settable property, which is required, this verbose
usage is not typical.
In the WPF XAML processor implementation, the handling for this markup extension is defined by the
StaticResourceExtension class.
StaticResource   is a markup extension. Markup extensions are typically implemented when there is a
requirement to escape attribute values to be other than literal values or handler names, and the requirement is
more global than just putting type converters on certain types or properties. All markup extensions in XAML use
the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes
that a markup extension must process the attribute. For more information, see Markup Extensions and WPF
XAML.
See also
   Styling and Templating
   XAML in WPF
   Markup Extensions and WPF XAML
   XAML Resources
   Resources and Code
        TemplateBinding Markup Extension
        11/21/2022 • 2 minutes to read • Edit Online
Links the value of a property in a control template to be the value of another property on the templated control.
XAML Values
  VA L UE                                                     DESC RIP T IO N
- or -
Remarks
A TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding
constructed with {Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay} . A TemplateBinding is
always a one-way binding, even if properties involved default to two-way binding. Both properties involved
must be dependency properties. In order to achieve two-way binding to a templated parent use the following
binding statement instead
 {Binding RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, Path=MyDependencyProperty} .
RelativeSource is another markup extension that is sometimes used in conjunction with or instead of
 TemplateBinding in order to perform relative property binding within a template.
Describing control templates as a concept is not covered here; for more information, see Control Styles and
Templates.
Attribute syntax is the most common syntax used with this markup extension. The string token provided after
the TemplateBinding identifier string is assigned as the Property value of the underlying
TemplateBindingExtension extension class.
Object element syntax is possible, but it is not shown because it has no realistic application.    TemplateBinding    is
used to fill values within setters, using evaluated expressions, and using object element syntax for
 TemplateBinding to fill <Setter.Property> property element syntax is unnecessarily verbose.
TemplateBinding can also be used in a verbose attribute usage that specifies the Property property as a
property=value pair:
The verbose usage is often useful for extensions that have more than one settable property, or if some
properties are optional. Because TemplateBinding has only one settable property, which is required, this verbose
usage is not typical.
In the WPF XAML processor implementation, the handling for this markup extension is defined by the
TemplateBindingExtension class.
TemplateBinding   is a markup extension. Markup extensions are typically implemented when there is a
requirement to escape attribute values to be other than literal values or handler names, and the requirement is
more global than just putting type converters on certain types or properties. All markup extensions in XAML use
the { and } characters in their attribute syntax, which is the convention by which a XAML processor
recognizes that a markup extension must process the attribute. For more information, see Markup Extensions
and WPF XAML.
See also
   Style
   ControlTemplate
   Styling and Templating
   XAML in WPF
   Markup Extensions and WPF XAML
   RelativeSource MarkupExtension
   Binding Markup Extension
        ThemeDictionary Markup Extension
        11/21/2022 • 2 minutes to read • Edit Online
Provides a way for custom control authors or applications that integrate third-party controls to load theme-
specific resource dictionaries to use in styling the control.
XAML Values
  VA L UE                                                     DESC RIP T IO N
Remarks
This extension is intended to fill only one specific property value: a value for ResourceDictionary.Source.
By using this extension, you can specify a single resources-only assembly that contains some styles to use only
when the Windows Aero theme is applied to the user's system, other styles only when the Luna theme is active,
and so on. By using this extension, the contents of a control-specific resource dictionary can be automatically
invalidated and reloaded to be specific for another theme when required.
The assemblyUri string (AssemblyName property value) forms the basis of a naming convention that identifies
which dictionary applies for a particular theme. The ProvideValue logic for ThemeDictionary completes the
convention by generating a uniform resource identifier (URI) that points to a particular theme dictionary variant,
as contained within a precompiled resource assembly. Describing this convention, or theme interactions with
general control styling and page/application level styling as a concept, is not covered fully here. The basic
scenario for using ThemeDictionary is to specify the Source property of a ResourceDictionary declared at the
application level. When you provide a URI for the assembly through a ThemeDictionary extension rather than as
a direct URI, the extension logic will provide invalidation logic that applies whenever the system theme changes.
Attribute syntax is the most common syntax used with this markup extension. The string token provided after
the ThemeDictionary identifier string is assigned as the AssemblyName value of the underlying
ThemeDictionaryExtension extension class.
              may also be used in object element syntax. In this case, specifying the value of the
ThemeDictionary
AssemblyName property is required.
ThemeDictionary can also be used in a verbose attribute usage that specifies the Member property as a
property=value pair:
The verbose usage is often useful for extensions that have more than one settable property, or if some
properties are optional. Because ThemeDictionary has only one settable property, which is required, this verbose
usage is not typical.
In the WPF XAML processor implementation, the handling for this markup extension is defined by the
ThemeDictionaryExtension class.
ThemeDictionary   is a markup extension. Markup extensions are typically implemented when there is a
requirement to escape attribute values to be other than literal values or handler names, and the requirement is
more global than just putting type converters on certain types or properties. All markup extensions in XAML use
the { and } characters in their attribute syntax, which is the convention by which a XAML processor recognizes
that a markup extension must process the attribute. For more information, see Markup Extensions and WPF
XAML.
See also
   Styling and Templating
   XAML in WPF
   Markup Extensions and WPF XAML
   WPF Application Resource, Content, and Data Files
       PropertyPath XAML Syntax
       11/21/2022 • 10 minutes to read • Edit Online
The PropertyPath object supports a complex inline XAML syntax for setting various properties that take the
PropertyPath type as their value. This topic documents the PropertyPath syntax as applied to binding and
animation syntaxes.
propertyName must resolve to be the name of a property that is in the current DataContext for a Path usage. If
your binding updates the source, that property must be read/write and the source object must be mutable.
key   must be either the typed index to a dictionary or hash table, or the integer index of an array. Also, the value
of the key must be a type that is directly bindable to the property where it is applied. For instance, a hash table
that contains string keys and string values can be used this way to bind to Text for a TextBox. Or, if the key points
to a collection or subindex, you could use this syntax to bind to a target collection property. Otherwise, you need
to reference a specific property, through a syntax such as <Binding Path="[key].propertyName" .../> .
You can specify the type of the index if necessary. For details on this aspect of an indexed property path, see
Binding.Path.
propertyName   must resolve to be the name of a property that is the current DataContext. The path properties
 propertyName and propertyName2 can be any properties that exist in a relationship, where propertyName2 is a
property that exists on the type that is the value of propertyName .
The parentheses indicate that this property in a PropertyPath should be constructed using a partial qualification.
It can use an XML namespace to find the type with an appropriate mapping. The ownerType searches types that
a XAML processor has access to, through the XmlnsDefinitionAttribute declarations in each assembly. Most
applications have the default XML namespace mapped to the
 http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace, so a prefix is usually only necessary for
custom types or types otherwise outside that namespace. propertyName must resolve to be the name of a
property existing on the ownerType . This syntax is generally used for one of the following cases:
   The path is specified in XAML that is in a style or template that does not have a specified Target Type. A
   qualified usage is generally not valid for cases other than this, because in non-style, non-template cases,
   the property exists on an instance, not a type.
   The property is an attached property.
   You are binding to a static property.
For use as storyboard target, the property specified as   propertyName   must be a DependencyProperty.
The / in this syntax is used to navigate within a hierarchical data source object, and multiple steps into the
hierarchy with successive / characters are supported. The source traversal accounts for the current record
pointer position, which is determined by synchronizing the data with the UI of its view. For details on binding
with hierarchical data source objects, and the concept of current record pointer in data binding, see Use the
Master-Detail Pattern with Hierarchical Data or Data Binding Overview.
     NOTE
     Superficially, this syntax resembles XPath. A true XPath expression for binding to an XML data source is not used as a Path
     value and should instead be used for the mutually exclusive XPath property.
Collection Views
To reference a named collection view, prefix the collection view name with the hash character ( # ).
Current Record Pointer
To reference the current record pointer for a collection view or master detail data binding scenario, start the path
string with a forward slash ( / ). Any path past the forward slash is traversed starting from the current record
pointer.
Multiple Indexers
or
If a given object supports multiple indexers, those indexers can be specified in order, similar to an array
referencing syntax. The object in question can be either the current context or the value of a property that
contains a multiple index object.
By default, the indexer values are typed by using the characteristics of the underlying object. You can specify the
type of the index if necessary. For details on typing the indexers, see Binding.Path.
Mixing Syntaxes
Each of the syntaxes shown above can be interspersed. For instance, the following is an example that creates a
property path to the color at a particular x,y of a ColorGrid property that contains a pixel grid array of
SolidColorBrush objects:
  NOTE
  Technically, these escapes work for a storyboard property path also, but you are usually traversing object models for
  existing WPF objects, and escaping should be unnecessary.
propertyName    must resolve to be the name of a dependency property that exists on the specified TargetName
type.
propertyName   must be a property that is either a Freezable value type or a primitive, which exists on the
specified TargetName type.
propertyName2   must be the name of a dependency property that exists on the object that is the value of
propertyName . In other words, propertyName2 must exist as a dependency property on the type that is the
propertyName PropertyType.
Indirect targeting of animations is necessary because of applied styles and templates. In order to target an
animation, you need a TargetName on a target object, and that name is established by x:Name or Name.
Although template and style elements also can have names, those names are only valid within the namescope of
the style and template. (If templates and styles did share namescopes with application markup, names couldn't
be unique. The styles and templates are literally shared between instances and would perpetuate duplicate
names.) Thus, if the individual properties of an element that you might wish to animate came from a style or
template, you need to start with a named element instance that is not from a style template, and then target into
the style or template visual tree to arrive at the property you wish to animate.
For instance, the Background property of a Panel is a complete Brush (actually a SolidColorBrush) that came
from a theme template. To animate a Brush completely, there would need to be a BrushAnimation (probably one
for every Brush type) and there is no such type. To animate a Brush, you instead animate properties of a
particular Brush type. You need to get from SolidColorBrush to its Color to apply a ColorAnimation there. The
property path for this example would be Background.Color .
Attached Properties
The parentheses indicate that this property in a PropertyPath should be constructed using a partial qualification.
It can use an XML namespace to find the type. The ownerType searches types that a WPF attached properties are
implemented as dependency properties, so this issue is only of concern for custom attached properties.)
Indexers
Most dependency properties or Freezable types do not support an indexer. Therefore, the only usage for an
indexer in an animation path is at an intermediate position between the property that starts the chain on the
named target and the eventual animated property. In the provided syntax, that is propertyName2 . For instance,
an indexer usage might be necessary if the intermediate property is a collection such as TransformGroup, in a
property path such as RenderTransform.Children[1].Angle .
PropertyPath in Code
Code usage for PropertyPath, including how to construct a PropertyPath, is documented in the reference topic
for PropertyPath.
In general, PropertyPath is designed to use two different constructors, one for the binding usages and simplest
animation usages, and one for the complex animation usages. Use the PropertyPath(Object) signature for
binding usages, where the object is a string. Use the PropertyPath(Object) signature for one-step animation
paths, where the object is a DependencyProperty. Use the PropertyPath(String, Object[]) signature for complex
animations. This latter constructor uses a token string for the first parameter and an array of objects that fill
positions in the token string to define a property path relationship.
See also
   PropertyPath
   Data Binding Overview
   Storyboards Overview
        PresentationOptions:Freeze Attribute
        11/21/2022 • 2 minutes to read • Edit Online
Sets the IsFrozen state to true on the containing Freezable element. Default behavior for a Freezable without
the PresentationOptions:Freeze attribute specified is that IsFrozen is false at load time, and dependent on
general Freezable behavior at runtime.
XAML Values
  VA L UE                                                    DESC RIP T IO N
Remarks
The   Freeze   attribute is the only attribute or other programming element defined in the
 http://schemas.microsoft.com/winfx/2006/xaml/presentation/options XML namespace. The Freeze attribute
exists in this special namespace specifically so that it can be designated as ignorable, using mc:Ignorable
Attribute as part of the root element declarations. The reason that Freeze must be able to be ignorable is
because not all XAML processor implementations are able to freeze a Freezable at load time; this capability is
not part of the XAML specification.
The ability to process the Freeze attribute is specifically built in to the WPF XAML processor when processing
the Freeze attribute on Freezable elements at load time.
Any value for the Freeze attribute other than true (not case sensitive) generates a load time error. (Specifying
the Freeze attribute as false is not an error, but that is already the default, so setting to false does nothing).
See also
   Freezable
   Freezable Objects Overview
   mc:Ignorable Attribute
      Markup Compatibility (mc:) Language Features
      11/21/2022 • 2 minutes to read • Edit Online
In This Section
mc:Ignorable Attribute
mc:ProcessContent Attribute
        mc:Ignorable Attribute
        11/21/2022 • 2 minutes to read • Edit Online
Specifies which XML namespace prefixes encountered in a markup file may be ignored by a XAML processor.
The mc:Ignorable attribute supports markup compatibility both for custom namespace mapping and for XAML
versioning.
XAML Values
  VA L UE                                                   DESC RIP T IO N
ignorablePrefix, ignorablePrefix1, etc. Any valid prefix string, per the XML 1.0 specification.
  ignorableUri                                              Any valid URI for designating a namespace, per the XML 1.0
                                                            specification.
Remarks
The mc XML namespace prefix is the recommended prefix convention to use when mapping the XAML
compatibility namespace http://schemas.openxmlformats.org/markup-compatibility/2006 .
Elements or attributes where the prefix portion of the element name are identified as mc:Ignorable will not
raise errors when processed by a XAML processor. If that attribute could not be resolved to an underlying type
or programming construct, then that element is ignored. Note however that ignored elements might still
generate additional parsing errors for additional element requirements that are side effects of that element not
being processed. For instance, a particular element content model might require exactly one child element, but if
the specified child element was in an mc:Ignorable prefix, and the specified child element could not be resolved
to a type, then the XAML processor might raise an error.
mc:Ignorable  only applies to namespace mappings to identifier strings. mc:Ignorable does not apply to
namespace mappings into assemblies, which specify a CLR namespace and an assembly (or default to the
current executable as the assembly).
If you are implementing a XAML processor, your processor implementation must not raise parsing or processing
errors on type resolution for any element or attribute that is qualified by a prefix that is identified as
 mc:Ignorable . But your processor implementation can still raise exceptions that are a secondary result of an
element failing to load or be processed, such as the one-child element example given earlier.
By default, a XAML processor will ignore content within an ignored element. However, you can specify an
additional attribute, mc:ProcessContent Attribute, to require continued processing of content within an ignored
element by the next available parent element.
Multiple prefixes can be specified in the attribute, using one or more white-space characters as the separator, for
example: mc:Ignorable="ignore1 ignore2" .
The http://schemas.openxmlformats.org/markup-compatibility/2006 namespace defines other elements and
attributes that are not documented within this area of the SDK. For more information, see XML Markup
Compatibility Specification.
See also
   XamlReader
   PresentationOptions:Freeze Attribute
   XAML in WPF
   Documents in WPF
        mc:ProcessContent Attribute
        11/21/2022 • 2 minutes to read • Edit Online
Specifies which XAML elements should still have content processed by relevant parent elements, even if the
immediate parent element may be ignored by a XAML processor due to specifying mc:Ignorable Attribute. The
 mc:ProcessContent attribute supports markup compatibility both for custom namespace mapping and for XAML
versioning.
XAML Values
  VA L UE                                                     DESC RIP T IO N
ignorablePrefix Any valid prefix string, per the XML 1.0 specification.
  ignorableUri                                                Any valid URI for designating a namespace, per the XML 1.0
                                                              specification.
Remarks
By default, a XAML processor will ignore content within an ignored element. You can specify a specific element
by mc:ProcessContent , and a XAML processor will continue to process the content within the ignored element.
This would typically be used if the content is nested within several tags, at least one of which is ignorable and at
least one of which is not ignorable.
Multiple prefixes may be specified in the attribute, using a space separator, for example:
mc:ProcessContent="ignore:Element1 ignore:Element2" .
In This Section
Base Elements Overview
Freezable Objects Overview
Alignment, Margins, and Padding Overview
How-to Topics
Reference
UIElement
ContentElement
FrameworkElement
FrameworkContentElement
Related Sections
WPF Architecture
XAML in WPF
Element Tree and Serialization
Properties
Events
Input
Resources
Styling and Templating
Threading Model
       Base Elements Overview
       11/21/2022 • 6 minutes to read • Edit Online
A high percentage of classes in Windows Presentation Foundation (WPF) are derived from four classes which
are commonly referred to in the SDK documentation as the base element classes. These classes are UIElement,
FrameworkElement, ContentElement, and FrameworkContentElement. The DependencyObject class is also
related, because it is a common base class of both UIElement and ContentElement
See also
   Control
   Dependency Properties Overview
   Control Authoring Overview
   WPF Architecture
       Freezable Objects Overview
       11/21/2022 • 9 minutes to read • Edit Online
This topic describes how to effectively use and create Freezable objects, which provide special features that can
help improve application performance. Examples of freezable objects include brushes, pens, transformations,
geometries, and animations.
What Is a Freezable?
A Freezable is a special type of object that has two states: unfrozen and frozen. When unfrozen, a Freezable
appears to behave like any other object. When frozen, a Freezable can no longer be modified.
A Freezable provides a Changed event to notify observers of any modifications to the object. Freezing a
Freezable can improve its performance, because it no longer needs to spend resources on change notifications.
A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.
Although the Freezable class has many applications, most Freezable objects in Windows Presentation
Foundation (WPF) are related to the graphics sub-system.
The Freezable class makes it easier to use certain graphics system objects and can help improve application
performance. Examples of types that inherit from Freezable include the Brush, Transform, and Geometry classes.
Because they contain unmanaged resources, the system must monitor these objects for modifications, and then
update their corresponding unmanaged resources when there is a change to the original object. Even if you
don't actually modify a graphics system object, the system must still spend some of its resources monitoring the
object, in case you do change it.
For example, suppose you create a SolidColorBrush brush and use it to paint the background of a button.
When the button is rendered, the WPF graphics sub-system uses the information you provided to paint a group
of pixels to create the appearance of a button. Although you used a solid color brush to describe how the button
should be painted, your solid color brush doesn't actually do the painting. The graphics system generates fast,
low-level objects for the button and the brush, and it is those objects that actually appear on the screen.
If you were to modify the brush, those low-level objects would have to be regenerated. The freezable class is
what gives a brush the ability to find its corresponding generated, low-level objects and to update them when it
changes. When this ability is enabled, the brush is said to be "unfrozen."
A freezable's Freeze method enables you to disable this self-updating ability. You can use this method to make
the brush become "frozen," or unmodifiable.
  NOTE
  Not every Freezable object can be frozen. To avoid throwing an InvalidOperationException, check the value of the
  Freezable object's CanFreeze property to determine whether it can be frozen before attempting to freeze it.
   if (myBrush.CanFreeze)
   {
       // Makes the brush unmodifiable.
       myBrush.Freeze();
   }
   If myBrush.CanFreeze Then
       ' Makes the brush unmodifiable.
       myBrush.Freeze()
   End If
When you no longer need to modify a freezable, freezing it provides performance benefits. If you were to freeze
the brush in this example, the graphics system would no longer need to monitor it for changes. The graphics
system can also make other optimizations, because it knows the brush won't change.
  NOTE
  For convenience, freezable objects remain unfrozen unless you explicitly freeze them.
Using Freezables
Using an unfrozen freezable is like using any other type of object. In the following example, the color of a
SolidColorBrush is changed from yellow to red after it's used to paint the background of a button. The graphics
system works behind the scenes to automatically change the button from yellow to red the next time the screen
is refreshed.
Freezing a Freezable
To make a Freezable unmodifiable, you call its Freeze method. When you freeze an object that contains freezable
objects, those objects are frozen as well. For example, if you freeze a PathGeometry, the figures and segments it
contains would be frozen too.
A Freezable can't be frozen if any of the following are true:
   It has animated or data bound properties.
   It has properties set by a dynamic resource. (See the XAML Resources for more information about
   dynamic resources.)
   It contains Freezable sub-objects that can't be frozen.
If these conditions are false, and you don't intend to modify the Freezable, then you should freeze it to gain the
performance benefits described earlier.
Once you call a freezable's Freeze method, it can no longer be modified. Attempting to modify a frozen object
causes an InvalidOperationException to be thrown. The following code throws an exception, because we attempt
to modify the brush after it's been frozen.
   if (myBrush.CanFreeze)
   {
       // Makes the brush unmodifiable.
       myBrush.Freeze();
   }
myButton.Background = myBrush;
try {
   If myBrush.CanFreeze Then
       ' Makes the brush unmodifiable.
       myBrush.Freeze()
   End If
myButton.Background = myBrush
Try
To avoid throwing this exception, you can use the IsFrozen method to determine whether a Freezable is frozen.
   Button myButton = new Button();
   SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
   if (myBrush.CanFreeze)
   {
       // Makes the brush unmodifiable.
       myBrush.Freeze();
   }
myButton.Background = myBrush;
   If myBrush.CanFreeze Then
       ' Makes the brush unmodifiable.
       myBrush.Freeze()
   End If
myButton.Background = myBrush
In the preceding code example, a modifiable copy was made of a frozen object using the Clone method. The next
section discusses cloning in more detail.
  NOTE
  Because a frozen freezable cannot be animated, the animation system will automatically create modifiable clones of frozen
  Freezable objects when you try to animate them with a Storyboard. To eliminate the performance overhead caused by
  cloning, leave an object unfrozen if you intend to animate it. For more information about animating with storyboards, see
  the Storyboards Overview.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="PresentationOptions">
<Page.Resources>
<StackPanel>
     </StackPanel>
   </Page>
To use the   Freezeattribute, you must map to the presentation options namespace:
 http://schemas.microsoft.com/winfx/2006/xaml/presentation/options . PresentationOptions is the recommended
prefix for mapping this namespace:
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
Because not all XAML readers recognize this attribute, it's recommended that you use the mc:Ignorable Attribute
to mark the Presentation:Freeze attribute as ignorable:
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   mc:Ignorable="PresentationOptions"
myButton.Background = myBrush;
myButton.Background = myBrush
  NOTE
  Regardless of which clone method you use, animations are never copied to the new Freezable.
The Clone and CloneCurrentValue methods produce deep copies of the freezable. If the freezable contains other
frozen freezable objects, they are also cloned and made modifiable. For example, if you clone a frozen
PathGeometry to make it modifiable, the figures and segments it contains are also copied and made modifiable.
  NOTE
  It's very important that you begin each Freezable method you override with a call to the base implementation.
For an example of a custom Freezable class, see the Custom Animation Sample.
See also
 Freezable
 Custom Animation Sample
 Dependency Properties Overview
 Custom Dependency Properties
       Alignment, Margins, and Padding Overview
       11/21/2022 • 19 minutes to read • Edit Online
The FrameworkElement class exposes several properties that are used to precisely position child elements. This
topic discusses four of the most important properties: HorizontalAlignment, Margin, Padding, and
VerticalAlignment. The effects of these properties are important to understand, because they provide the basis
for controlling the position of elements in Windows Presentation Foundation (WPF) applications.
At first glance, the Button elements in this illustration may appear to be placed randomly. However, their
positions are actually precisely controlled by using a combination of margins, alignments, and padding.
The following example describes how to create the layout in the preceding illustration. A Border element
encapsulates a parent StackPanel, with a Padding value of 15 device independent pixels. This accounts for the
narrow LightBlue band that surrounds the child StackPanel. Child elements of the StackPanel are used to
illustrate each of the various positioning properties that are detailed in this topic. Three Button elements are
used to demonstrate both the Margin and HorizontalAlignment properties.
// Create the application's main Window.
mainWindow = new Window ();
mainWindow.Title = "Margins, Padding and Alignment Sample";
// Add a Border
myBorder = new Border();
myBorder.Background = Brushes.LightBlue;
myBorder.BorderBrush = Brushes.Black;
myBorder.Padding = new Thickness(15);
myBorder.BorderThickness = new Thickness(2);
   'Add a Border.
   Dim myBorder As New Border()
   myBorder.Background = Brushes.LightBlue
   myBorder.BorderBrush = Brushes.Black
   myBorder.Padding = New Thickness(15)
   myBorder.BorderThickness = New Thickness(2)
The following diagram provides a close-up view of the various positioning properties that are used in the
preceding sample. Subsequent sections in this topic describe in greater detail how to use each positioning
property.
Understanding Alignment Properties
The HorizontalAlignment and VerticalAlignment properties describe how a child element should be positioned
within a parent element's allocated layout space. By using these properties together, you can position child
elements precisely. For example, child elements of a DockPanel can specify four different horizontal alignments:
Left, Right, or Center, or to Stretch to fill available space. Similar values are available for vertical positioning.
  NOTE
  Explicitly-set Height and Width properties on an element take precedence over the Stretch property value. Attempting to
  set Height, Width, and a HorizontalAlignment value of Stretch results in the Stretch request being ignored.
HorizontalAlignment Property
The HorizontalAlignment property declares the horizontal alignment characteristics to apply to child elements.
The following table shows each of the possible values of the HorizontalAlignment property.
M EM B ER DESC RIP T IO N
  Left                                                            Child elements are aligned to the left of the parent element's
                                                                  allocated layout space.
  Stretch (Default)                                               Child elements are stretched to fill the parent element's
                                                                  allocated layout space. Explicit Width and Height values take
                                                                  precedence.
The following example shows how to apply the HorizontalAlignment property to Button elements. Each attribute
value is shown, to better illustrate the various rendering behaviors.
The preceding code yields a layout similar to the following image. The positioning effects of each
HorizontalAlignment value are visible in the illustration.
VerticalAlignment Property
The VerticalAlignment property describes the vertical alignment characteristics to apply to child elements. The
following table shows each of the possible values for the VerticalAlignment property.
M EM B ER DESC RIP T IO N
  Top                                                        Child elements are aligned to the top of the parent element's
                                                             allocated layout space.
  Stretch (Default)                                          Child elements are stretched to fill the parent element's
                                                             allocated layout space. Explicit Width and Height values take
                                                             precedence.
The following example shows how to apply the VerticalAlignment property to Button elements. Each attribute
value is shown, to better illustrate the various rendering behaviors. For purposes of this sample, a Grid element
with visible gridlines is used as the parent, to better illustrate the layout behavior of each property value.
TextBlock myTextBlock = new TextBlock();
myTextBlock.FontSize = 18;
myTextBlock.HorizontalAlignment = HorizontalAlignment.Center;
myTextBlock.Text = "VerticalAlignment Sample";
Grid.SetRow(myTextBlock, 0);
Button myButton1 = new Button();
myButton1.VerticalAlignment = VerticalAlignment.Top;
myButton1.Content = "Button 1 (Top)";
Grid.SetRow(myButton1, 1);
Button myButton2 = new Button();
myButton2.VerticalAlignment = VerticalAlignment.Bottom;
myButton2.Content = "Button 2 (Bottom)";
Grid.SetRow(myButton2, 2);
Button myButton3 = new Button();
myButton3.VerticalAlignment = VerticalAlignment.Center;
myButton3.Content = "Button 3 (Center)";
Grid.SetRow(myButton3, 3);
Button myButton4 = new Button();
myButton4.VerticalAlignment = VerticalAlignment.Stretch;
myButton4.Content = "Button 4 (Stretch)";
Grid.SetRow(myButton4, 4);
The preceding code yields a layout similar to the following image. The positioning effects of each
VerticalAlignment value are visible in the illustration.
  NOTE
  A non-zero margin applies space outside the element's ActualWidth and ActualHeight.
The following example shows how to apply uniform margins around a group of Button elements. The Button
elements are spaced evenly with a ten-pixel margin buffer in each direction.
   Button^ myButton7 = gcnew Button();
   myButton7->Margin = Thickness(10);
   myButton7->Content = "Button 7";
   Button^ myButton8 = gcnew Button();
   myButton8->Margin = Thickness(10);
   myButton8->Content = "Button 8";
   Button^ myButton9 = gcnew Button();
   myButton9->Margin = Thickness(10);
   myButton9->Content = "Button 9";
In many instances, a uniform margin is not appropriate. In these cases, non-uniform spacing can be applied. The
following example shows how to apply non-uniform margin spacing to child elements. Margins are described in
this order: left, top, right, bottom.
   <Border Background="LightBlue"
           BorderBrush="Black"
           BorderThickness="2"
           CornerRadius="45"
           Padding="25">
// Add the Border to the Window as Content and show the Window.
mainWindow->Content = myBorder;
mainWindow->Title = "Margin, Padding, and Alignment Sample";
mainWindow->Show();
// Add the Border to the Window as Content and show the Window.
mainWindow.Content = myBorder;
mainWindow.Title = "Margin, Padding, and Alignment Sample";
mainWindow.Show();
Dim myBorder As New Border
myBorder.Background = Brushes.LightBlue
myBorder.BorderBrush = Brushes.Black
myBorder.BorderThickness = New Thickness(2)
myBorder.CornerRadius = New CornerRadius(45)
myBorder.Padding = New Thickness(25)
When compiled, the preceding application yields a UI that looks like the following illustration. The effects of the
various property values are evident in the spacing between elements, and significant property values for
elements in each column are shown within TextBlock elements.
What's Next
Positioning properties defined by the FrameworkElement class enable fine control of element placement within
WPF applications. You now have several techniques you can use to better position elements using WPF.
Additional resources are available that explain WPF layout in greater detail. The Panels Overview topic contains
more detail about the various Panel elements. The topic Walkthrough: My first WPF desktop application
introduces advanced techniques that use layout elements to position components and bind their actions to data
sources.
See also
   FrameworkElement
   HorizontalAlignment
   VerticalAlignment
   Margin
   Panels Overview
   Layout
   WPF Layout Gallery Sample
      Base Elements How-to Topics
      11/21/2022 • 2 minutes to read • Edit Online
The topics in this section describe how to use the four WPF base elements: UIElement, ContentElement,
FrameworkElement, and FrameworkContentElement.
In This Section
Make a UIElement Transparent or Semi-Transparent
Animate the Size of a FrameworkElement
Determine Whether a Freezable Is Frozen
Handle a Loaded Event
Set Margins of Elements and Controls
Make a Freezable Read-Only
Obtain a Writable Copy of a Read-Only Freezable
Flip a UIElement Horizontally or Vertically
Use a ThicknessConverter Object
Handle the ContextMenuOpening Event
Reference
UIElement
ContentElement
FrameworkElement
FrameworkContentElement
Related Sections
Base Elements
       How to: Make a UIElement Transparent or Semi-
       Transparent
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to make a UIElement transparent or semi-transparent. To make an element transparent
or semi-transparent, you set its Opacity property. A value of 0.0 makes the element completely transparent,
while a value of 1.0 makes the element completely opaque. A value of 0.5 makes the element 50% opaque,
and so on. An element's Opacity is set to 1.0 by default.
Example
The following example sets the Opacity of a button to   0.25   , making it and its contents (in this case, the button's
text) 25% opaque.
   <!-- Both the button and its text are made 25% opaque. -->
   <Button Opacity="0.25">A Button</Button>
   //
   // Both the button and its text are made 25% opaque.
   //
   Button myTwentyFivePercentOpaqueButton = new Button();
   myTwentyFivePercentOpaqueButton.Opacity = new Double();
   myTwentyFivePercentOpaqueButton.Opacity = 0.25;
   myTwentyFivePercentOpaqueButton.Content = "A Button";
If an element's contents have their own Opacity settings, those values are multiplied against the containing
elements Opacity.
The following example sets a button's Opacity to 0.25 , and the Opacity of an Image control contained with in
the button to 0.5 . As a result, the image appears 12.5% opaque: 0.25 * 0.5 = 0.125.
Another way to control the opacity of an element is to set the opacity of the Brush that paints the element. This
approach enables you to selectively alter the opacity of portions of an element, and provides performance
benefits over using the element's Opacity property. The following example sets the Opacity of a SolidColorBrush
used to paint the button's Background is set to 0.25 . As a result, the brush's background is 25% opaque, but its
contents (the button's text) remain 100% opaque.
   //
   // This button's background is made 25% opaque,
   // but its text remains 100% opaque.
   //
   Button myOpaqueTextButton = new Button();
   SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Gray);
   mySolidColorBrush.Opacity = 0.25;
   myOpaqueTextButton.Background = mySolidColorBrush;
   myOpaqueTextButton.Content = "A Button";
You may also control the opacity of individual colors within a brush. For more information about colors and
brushes, see Painting with Solid Colors and Gradients Overview. For an example showing how to animate an
element's opacity, see Animate the Opacity of an Element or Brush.
       How to: Animate the Size of a FrameworkElement
      11/21/2022 • 2 minutes to read • Edit Online
To animate the size of a FrameworkElement, you can either animate its Width and Height properties or use an
animated ScaleTransform.
In the following example animates the size of two buttons using these two approaches. One button is resized by
animating its Width property and another is resized by animating a ScaleTransform applied to its
RenderTransform property. Each button contains some text. Initially, the text appears the same in both buttons,
but as the buttons are resized, the text in the second button becomes distorted.
Example
   <!-- AnimatingSizeExample.xaml
         This example shows two ways of animating the size
         of a framework element. -->
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="Microsoft.Samples.Animation.AnimatingSizeExample"
     WindowTitle="Animating Size Example">
     <Canvas Width="650" Height="400">
       <Button Name="AnimatedWidthButton"
         Canvas.Left="20" Canvas.Top="20"
         Width="200" Height="150"
         BorderBrush="Red" BorderThickness="5">
           Click Me
         <Button.Triggers>
       <Button
         Canvas.Left="20" Canvas.Top="200"
         Width="200" Height="150"
         BorderBrush="Black" BorderThickness="3">
           Click Me
         <Button.RenderTransform>
            <ScaleTransform x:Name="MyAnimatedScaleTransform"
             ScaleX="1" ScaleY="1" />
         </Button.RenderTransform>
         <Button.Triggers>
When you transform an element, the entire element and its contents are transformed. When you directly alter
the size of an element, as in the case of the first button, the element's contents are not resized unless their size
and position depend on the size of their parent element.
Animating the size of an element by applying an animated transform to its RenderTransform property provides
better performance than animated its Width and Height directly, because the RenderTransform property does
not trigger a layout pass.
For more information about animating properties, see the Animation Overview. For more information about
transforms, see the Transforms Overview.
       How to: Determine Whether a Freezable Is Frozen
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to determine whether a Freezable object is frozen. If you try to modify a frozen
Freezable object, it throws an InvalidOperationException. To avoid throwing this exception, use the IsFrozen
property of the Freezable object to determine whether it is frozen.
Example
The following example freezes a SolidColorBrush and then tests it by using the IsFrozen property to determine
whether it is frozen.
   if (myBrush.CanFreeze)
   {
       // Makes the brush unmodifiable.
       myBrush.Freeze();
   }
myButton.Background = myBrush;
   If myBrush.CanFreeze Then
       ' Makes the brush unmodifiable.
       myBrush.Freeze()
   End If
myButton.Background = myBrush
For more information about Freezable objects, see the Freezable Objects Overview.
See also
   Freezable
   IsFrozen
   Freezable Objects Overview
   How-to Topics
      How to: Handle a Loaded Event
      11/21/2022 • 2 minutes to read • Edit Online
This example shows how to handle the FrameworkElement.Loaded event, and an appropriate scenario for
handling that event. The handler creates a Button when the page loads.
Example
The following example uses Extensible Application Markup Language (XAML) together with a code-behind file.
   <StackPanel
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="SDKSample.FELoaded"
     Loaded="OnLoad"
     Name="root"
   >
   </StackPanel>
See also
   FrameworkElement
   Object Lifetime Events
   Routed Events Overview
   How-to Topics
       How to: Set Margins of Elements and Controls
      11/21/2022 • 2 minutes to read • Edit Online
This example describes how to set the Margin property, by changing any existing property value for the margin
in code-behind. The Margin property is a property of the FrameworkElement base element, and is thus inherited
by a variety of controls and other elements.
This example is written in XAML refers to. The code-behind is shown in both a C# and a Microsoft Visual Basic
version.
Example
   <Button Click="OnClick" Margin="10" Name="btn1">
   Click To See Change!!</Button>
This example shows how to make a Freezable read-only by calling its Freeze method.
You cannot freeze a Freezable object if any one of the following conditions is   true   about the object:
   It has animated or data bound properties.
   It has properties that are set by a dynamic resource. For more information about dynamic resources, see
   the XAML Resources.
   It contains Freezable sub-objects that cannot be frozen.
If these conditions are false for your Freezable object and you do not intend to modify it, consider freezing it
to gain performance benefits.
Example
The following example freezes a SolidColorBrush, which is a type of Freezable object.
   if (myBrush.CanFreeze)
   {
       // Makes the brush unmodifiable.
       myBrush.Freeze();
   }
myButton.Background = myBrush;
   If myBrush.CanFreeze Then
       ' Makes the brush unmodifiable.
       myBrush.Freeze()
   End If
myButton.Background = myBrush
For more information about Freezable objects, see the Freezable Objects Overview.
See also
   Freezable
   CanFreeze
   Freeze
   Freezable Objects Overview
   How-to Topics
        How to: Obtain a Writable Copy of a Read-Only
        Freezable
        11/21/2022 • 2 minutes to read • Edit Online
This example shows how to use the Clone method to create a writable copy of a read-only Freezable.
After a Freezable object is marked as read-only ("frozen"), you cannot modify it. However, you can use the Clone
method to create a modifiable clone of the frozen object.
Example
The following example creates a modifiable clone of a frozen SolidColorBrush object.
myButton.Background = myBrush;
myButton.Background = myBrush
For more information about Freezable objects, see the Freezable Objects Overview.
See also
   Freezable
   CloneCurrentValue
   Freezable Objects Overview
   How-to Topics
       How to: Flip a UIElement Horizontally or Vertically
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to use a ScaleTransform to flip a UIElement horizontally or vertically. In this example, a
Button control (a type of UIElement) is flipped by applying a ScaleTransform to its RenderTransform property.
See also
   Transforms Overview
       How to: Use a ThicknessConverter Object
       11/21/2022 • 2 minutes to read • Edit Online
Example
This example shows how to create an instance of ThicknessConverter and use it to change the thickness of a
border.
The example defines a custom method called changeThickness ; this method first converts the contents of a
ListBoxItem, as defined in a separate Extensible Application Markup Language (XAML) file, to an instance of
Thickness, and later converts the content into a String. This method passes the ListBoxItem to a
ThicknessConverter object, which converts the Content of a ListBoxItem to an instance of Thickness. This value is
then passed back as the value of the BorderThickness property of the Border.
This example does not run.
See also
   Thickness
   ThicknessConverter
   Border
   How to: Change the Margin Property
   How to: Convert a ListBoxItem to a new Data Type
   Panels Overview
       How to: Handle the ContextMenuOpening Event
       11/21/2022 • 5 minutes to read • Edit Online
The ContextMenuOpening event can be handled in an application to either adjust an existing context menu prior
to display or to suppress the menu that would otherwise be displayed by setting the Handled property to true
in the event data. The typical reason for setting Handled to true in the event data is to replace the menu
entirely with a new ContextMenu object, which sometimes requires canceling the operation and starting a new
open. If you write handlers for the ContextMenuOpening event, you should be aware of timing issues between a
ContextMenu control and the service that is responsible for opening and positioning context menus for controls
in general. This topic illustrates some of the code techniques for various context menu opening scenarios and
illustrates a case where the timing issue comes into play.
There are several scenarios for handling the ContextMenuOpening event:
   Adjusting the menu items before display.
   Replacing the entire menu before display.
   Completely suppressing any existing context menu and displaying no context menu.
Example
Adjusting the Menu Items Before Display
Adjusting the existing menu items is fairly simple and is probably the most common scenario. You might do this
in order to add or subtract context menu options in response to current state information in your application or
particular state information that is available as a property on the object where the context menu is requested.
The general technique is to get the source of the event, which is the specific control that was right-clicked, and
get the ContextMenu property from it. You typically want to check the Items collection to see what context menu
items already exist in the menu, and then add or remove appropriate new MenuItem items to or from the
collection.
   ContextMenu BuildMenu()
   {
       ContextMenu theMenu = new ContextMenu();
       MenuItem mia = new MenuItem();
       mia.Header = "Item1";
       MenuItem mib = new MenuItem();
       mib.Header = "Item2";
       MenuItem mic = new MenuItem();
       mic.Header = "Item3";
       theMenu.Items.Add(mia);
       theMenu.Items.Add(mib);
       theMenu.Items.Add(mic);
       return theMenu;
   }
However, if you use this style of handler for ContextMenuOpening, you can potentially expose a timing issue if
the object where you are setting the ContextMenu does not have a preexisting context menu. When a user right-
clicks a control, ContextMenuOpening is raised even if the existing ContextMenu is empty or null. But in this
case, whatever new ContextMenu you set on the source element arrives too late to be displayed. Also, if the user
happens to right-click a second time, this time your new ContextMenu appears, the value is non null, and your
handler will properly replace and display the menu when the handler runs a second time. This suggests two
possible workarounds:
1. Insure that ContextMenuOpening handlers always run against controls that have at least a placeholder
   ContextMenu available, which you intend to be replaced by the handler code. In this case, you can still use
   the handler shown in the previous example, but you typically want to assign a placeholder ContextMenu
   in the initial markup:
      <StackPanel>
        <Rectangle Fill="Yellow" Width="200" Height="100" ContextMenuOpening="HandlerForCMO">
          <Rectangle.ContextMenu>
            <ContextMenu>
              <MenuItem>Initial menu; this will be replaced ...</MenuItem>
            </ContextMenu>
          </Rectangle.ContextMenu>
        </Rectangle>
        <TextBlock>Right-click the rectangle above, context menu gets replaced</TextBlock>
      </StackPanel>
2. Assume that the initial ContextMenu value might be null, based on some preliminary logic. You could
   either check ContextMenu for null, or use a flag in your code to check whether your handler has been run
   at least once. Because you assume that the ContextMenu is about to be displayed, your handler then sets
   Handled to true in the event data. To the ContextMenuService that is responsible for context menu
   display, a true value for Handled in the event data represents a request to cancel the display for the
   context menu / control combination that raised the event.
Now that you have suppressed the potentially suspect context menu, the next step is to supply a new one, then
display it. Setting the new one is basically the same as the previous handler: you build a new ContextMenu and
set the control source's FrameworkElement.ContextMenu property with it. The additional step is that you must
now force the display of the context menu, because you suppressed the first attempt. To force the display, you
set the Popup.IsOpen property to true within the handler. Be careful when you do this, because opening the
context menu in the handler raises the ContextMenuOpening event again. If you reenter your handler, it
becomes infinitely recursive. This is why you always need to check for null or use a flag if you open a context
menu from within a ContextMenuOpening event handler.
See also
   ContextMenu
   FrameworkElement.ContextMenu
   Base Elements Overview
   ContextMenu Overview
       Element Tree and Serialization
       11/21/2022 • 2 minutes to read • Edit Online
WPF programming elements often exist in some form of tree relationship to each other. For instance, an
application UI created in XAML can be conceptualized as an object tree. The element tree can be further divided
into two discrete yet sometimes parallel trees: the logical tree and the visual tree. Serialization in WPF involves
saving the state of these two trees as well as application state and writing it to a file, potentially as XAML.
In This Section
Trees in WPF
Serialization Limitations of XamlWriter.Save
Initialization for Object Elements Not in an Object Tree
How-to Topics
Reference
System.Windows.Markup
LogicalTreeHelper
VisualTreeHelper
Related Sections
WPF Architecture
XAML in WPF
Base Elements
Properties
Events
Input
Resources
Styling and Templating
Threading Model
       Trees in WPF
       11/21/2022 • 10 minutes to read • Edit Online
In many technologies, elements and components are organized in a tree structure where developers directly
manipulate the object nodes in the tree to affect the rendering or behavior of an application. Windows
Presentation Foundation (WPF) also uses several tree structure metaphors to define relationships between
program elements. For the most part WPF developers can create an application in code or define portions of the
application in XAML while thinking conceptually about the object tree metaphor, but will be calling specific API
or using specific markup to do so rather than some general object tree manipulation API such as you might use
in XML DOM. WPF exposes two helper classes that provide a tree metaphor view, LogicalTreeHelper and
VisualTreeHelper. The terms visual tree and logical tree are also used in the WPF documentation because these
same trees are useful for understanding the behavior of certain key WPF features. This topic defines what the
visual tree and logical tree represent, discusses how such trees relate to an overall object tree concept, and
introduces LogicalTreeHelper and VisualTreeHelpers.
Trees in WPF
The most complete tree structure in WPF is the object tree. If you define an application page in WPF subsystems
and affect choices you make in markup or code.
Even though you do not always manipulate either the logical tree or the visual tree directly, understanding the
concepts of how the trees interact is useful for understanding WPF as a technology. Thinking of WPF as a tree
metaphor of some kind is also crucial to understanding how property inheritance and event routing work in
WPF.
  NOTE
  Because the object tree is more of a concept than an actual API, another way to think of the concept is as an object
  graph. In practice, there are relationships between objects at run time where the tree metaphor will break down.
  Nevertheless, particularly with XAML-defined UI, the tree metaphor is relevant enough that most WPF documentation
  will use the term object tree when referencing this general concept.
If you were to process this XAML as XML under a document object model, and if you had included the tags
commented out as implicit (which would have been legal), then the resulting XML DOM tree would have
included elements for <ListBox.Items> and the other implicit items. But XAML does not process that way when
you read the markup and write to objects, the resulting object graph does not literally include ListBox.Items . It
does however have a ListBox property named Items that contains a ItemCollection, and that ItemCollection is
initialized but empty when the ListBox XAML is processed. Then, each child object element that exists as content
for the ListBox is added to the ItemCollection by parser calls to ItemCollection.Add . This example of processing
XAML into an object tree is so far seemingly an example where the created object tree is basically the logical
tree.
However, the logical tree is not the entire object graph that exists for your application UI at run time, even with
the XAML implicit syntax items factored out. The main reason for this is visuals and templates. For example,
consider the Button. The logical tree reports the Button object and also its string Content . But there is more to
this button in the run-time object tree. In particular, the button only appears on screen the way it does because a
specific Button control template was applied. The visuals that come from an applied template (such as the
template-defined Border of dark gray around the visual button) are not reported in the logical tree, even if you
are looking at the logical tree during run time (such as handling an input event from the visible UI and then
reading the logical tree). To find the template visuals, you would instead need to examine the visual tree.
For more information about how XAML syntax maps to the created object graph, and implicit syntax in XAML,
see XAML Syntax In Detail or XAML in WPF.
Tree Traversal
The LogicalTreeHelper class provides the GetChildren, GetParent, and FindLogicalNode methods for logical tree
traversal. In most cases, you should not have to traverse the logical tree of existing controls, because these
controls almost always expose their logical child elements as a dedicated collection property that supports
collection access such as Add , an indexer, and so on. Tree traversal is mainly a scenario that is used by control
authors who choose not to derive from intended control patterns such as ItemsControl or Panel where collection
properties are already defined, and who intend to provide their own collection property support.
The visual tree also supports a helper class for visual tree traversal, VisualTreeHelper. The visual tree is not
exposed as conveniently through control-specific properties, so the VisualTreeHelper class is the recommended
way to traverse the visual tree if that is necessary for your programming scenario. For more information, see
WPF Graphics Rendering Overview.
  NOTE
  Sometimes it is necessary to examine the visual tree of an applied template. You should be careful when using this
  technique. Even if you are traversing a visual tree for a control where you define the template, consumers of your control
  can always change the template by setting the Template property on instances, and even the end user can influence the
  applied template by changing the system theme.
See also
   Input Overview
   WPF Graphics Rendering Overview
   Routed Events Overview
Initialization for Object Elements Not in an Object Tree
WPF Architecture
       Serialization Limitations of XamlWriter.Save
       11/21/2022 • 2 minutes to read • Edit Online
The API Save can be used to serialize the contents of a Windows Presentation Foundation (WPF) application as a
Extensible Application Markup Language (XAML) file. However, there are some notable limitations in exactly
what is serialized. These limitations and some general considerations are documented in this topic.
Serialization is Self-Contained
The serialized output of Save is self-contained; everything that is serialized is contained inside a XAML single
page, with a single root element, and no external references other than URIs. For instance, if your page
referenced resources from application resources, these will appear as if they were a component of the page
being serialized.
Some aspects of Windows Presentation Foundation (WPF) initialization are deferred to processes that typically
rely on that element being connected to either the logical tree or visual tree. This topic describes the steps that
may be necessary in order to initialize an element that is not connected to either tree.
    /*
     * Render effect at normal dpi, indicator is the original RED rectangle
     */
    RenderTargetBitmap image1 = Rasterize(e, paperSize.Width, paperSize.Height, 96, 96);
    Save(image1, "render1.png");
// now render the altered version, with the element built up and initialized
     '
     '             * Render effect at normal dpi, indicator is the original RED rectangle
     '
     Dim image1 As RenderTargetBitmap = Rasterize(e, paperSize.Width, paperSize.Height, 96, 96)
     Save(image1, "render1.png")
' now render the altered version, with the element built up and initialized
See also
 Trees in WPF
 WPF Graphics Rendering Overview
 XAML in WPF
       Element Tree and Serialization How-to Topics
      11/21/2022 • 2 minutes to read • Edit Online
The topics in this section describe how to use the WPF element tree.
In This Section
Find an Element by Its Name
Override the Logical Tree
Reference
LogicalTreeHelper
VisualTreeHelper
System.Windows.Markup
Related Sections
       How to: Find an Element by Its Name
       11/21/2022 • 2 minutes to read • Edit Online
This example describes how to use the FindName method to find an element by its Name value.
Example
In this example, the method to find a particular element by its name is written as the event handler of a button.
 stackPanel is the Name of the root FrameworkElement being searched, and the example method then visually
indicates the found element by casting it as TextBlock and changing one of the TextBlock visible UI properties.
Although it is not necessary in most cases, advanced control authors have the option to override the logical tree.
Example
This example describes how to subclass StackPanel to override the logical tree, in this case to enforce a behavior
that the panel may only have and will only render a single child element. This isn't necessarily a practically
desirable behavior, but is shown here as a means of illustrating the scenario for overriding an element's normal
logical tree.
       public SingletonPanel()
       {
       }
Windows Presentation Foundation (WPF) provides a set of services that can be used to extend the functionality
of a common language runtime (CLR) property. Collectively, these services are typically referred to as the WPF
property system. A property that is backed by the WPF property system is known as a dependency property.
In This Section
   Dependency Properties Overview
   Attached Properties Overview
   Custom Dependency Properties
   Dependency Property Metadata
   Dependency Property Callbacks and Validation
   Framework Property Metadata
   Dependency Property Value Precedence
   Read-Only Dependency Properties
   Property Value Inheritance
   Dependency Property Security
   Safe Constructor Patterns for DependencyObjects
   Collection-Type Dependency Properties
   XAML Loading and Dependency Properties
   How-to Topics
Reference
DependencyProperty
PropertyMetadata
FrameworkPropertyMetadata
DependencyObject
Related Sections
WPF Architecture
XAML in WPF
Base Elements
Element Tree and Serialization
Events
Input
Resources
WPF Content Model
Threading Model
       Dependency properties overview
       11/21/2022 • 13 minutes to read • Edit Online
Windows Presentation Foundation (WPF) provides a set of services that can be used to extend the functionality
of a type's property. Collectively, these services are typically referred to as the WPF property system. A property
that is backed by the WPF property system is known as a dependency property. This overview describes the
WPF property system and the capabilities of a dependency property. This includes how to use existing
dependency properties in XAML and in code. This overview also introduces specialized aspects of dependency
properties, such as dependency property metadata, and how to create your own dependency property in a
custom class.
Prerequisites
This topic assumes that you have some basic knowledge of the .NET type system and object-oriented
programming. In order to follow the examples in this topic, you should also understand XAML and know how to
write WPF applications. For more information, see Walkthrough: My first WPF desktop application.
The naming convention of the property and its backing DependencyProperty field is important. The name of the
field is always the name of the property, with the suffix Property appended. For more information about this
convention and the reasons for it, see Custom Dependency Properties.
XAML supports a variety of syntax forms for setting properties. Which syntax to use for a particular property
will depend on the value type that a property uses, as well as other factors such as the presence of a type
converter. For more information on XAML syntax for property setting, see XAML in WPF and XAML Syntax In
Detail.
As an example of non-attribute syntax, the following XAML example shows another button background. This
time rather than setting a simple solid color, the background is set to an image, with an element representing
that image and the source of that image specified as an attribute of the nested element. This is an example of
property element syntax.
   <Button Content="Button!">
     <Button.Background>
       <ImageBrush ImageSource="wavy.jpg"/>
     </Button.Background>
   </Button>
Getting a property value is also essentially a call to the get "wrapper" implementation:
   double whatWidth;
   whatWidth = myButton.Width;
You can also call the property system APIs GetValue and SetValue directly. This is not typically necessary if you
are using existing properties (the wrappers are more convenient, and provide better exposure of the property
for developer tools), but calling the APIs directly is appropriate for certain scenarios.
Properties can be also set in XAML and then accessed later in code, through code-behind. For details, see Code-
Behind and XAML in WPF.
   <DockPanel.Resources>
     <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
   </DockPanel.Resources>
Once the resource is defined, you can reference the resource and use it to provide a property value:
This particular resource is referenced as a DynamicResource Markup Extension (in WPF XAML, you can use
either a static or dynamic resource reference). To use a dynamic resource reference, you must be setting to a
dependency property, so it is specifically the dynamic resource reference usage that is enabled by the WPF
property system. For more information, see XAML Resources.
  NOTE
  Resources are treated as a local value, which means that if you set another local value, you will eliminate the resource
  reference. For more information, see Dependency Property Value Precedence.
Data binding
A dependency property can reference a value through data binding. Data binding works through a specific
markup extension syntax in XAML, or the Binding object in code. With data binding, the final property value
determination is deferred until run time, at which time the value is obtained from a data source.
The following example sets the Content property for a Button, using a binding declared in XAML. The binding
uses an inherited data context and an XmlDataProvider data source (not shown). The binding itself specifies the
desired source property by XPath within the data source.
  NOTE
  Bindings are treated as a local value, which means that if you set another local value, you will eliminate the binding. For
  details, see Dependency Property Value Precedence.
Dependency properties, or the DependencyObject class, do not natively support INotifyPropertyChanged for
purposes of producing notifications of changes in DependencyObject source property value for data binding
operations. For more information on how to create properties for use in data binding that can report changes to
a data binding target, see Data Binding Overview.
Styles
Styles and templates are two of the chief motivating scenarios for using dependency properties. Styles are
particularly useful for setting properties that define application user interface (UI). Styles are typically defined as
resources in XAML. Styles interact with the property system because they typically contain "setters" for
particular properties, as well as "triggers" that change a property value based on the real-time value for another
property.
The following example creates a simple style (which would be defined inside a Resources dictionary, not shown),
then applies that style directly to the Style property for a Button. The setter within the style sets the Background
property for a styled Button to green.
   <Style x:Key="GreenButtonStyle">
     <Setter Property="Control.Background" Value="Green"/>
   </Style>
   <Button>I am animated
     <Button.Background>
       <SolidColorBrush x:Name="AnimBrush"/>
     </Button.Background>
     <Button.Triggers>
       <EventTrigger RoutedEvent="Button.Loaded">
         <BeginStoryboard>
           <Storyboard>
             <ColorAnimation
               Storyboard.TargetName="AnimBrush"
               Storyboard.TargetProperty="(SolidColorBrush.Color)"
               From="Red" To="Green" Duration="0:0:5"
               AutoReverse="True" RepeatBehavior="Forever" />
           </Storyboard>
         </BeginStoryboard>
       </EventTrigger>
     </Button.Triggers>
   </Button>
For more information on animating properties, see Animation Overview and Storyboards Overview.
Metadata overrides
You can change certain behaviors of a dependency property by overriding the metadata for that property when
you derive from the class that originally registers the dependency property. Overriding metadata relies on the
DependencyProperty identifier. Overriding metadata does not require reimplementing the property. The
metadata change is handled natively by the property system; each class potentially holds individual metadata
for all properties that are inherited from base classes, on a per-type basis.
The following example overrides metadata for a dependency property DefaultStyleKey. Overriding this
particular dependency property metadata is part of an implementation pattern that creates controls that can use
default styles from themes.
   public class SpinnerControl : ItemsControl
   {
       static SpinnerControl()
       {
           DefaultStyleKeyProperty.OverrideMetadata(
               typeof(SpinnerControl),
               new FrameworkPropertyMetadata(typeof(SpinnerControl))
           );
       }
   }
For more information about overriding or obtaining property metadata, see Dependency Property Metadata.
Property value inheritance
An element can inherit the value of a dependency property from its parent in the object tree.
  NOTE
  Property value inheritance behavior is not globally enabled for all dependency properties, because the calculation time for
  inheritance does have some performance impact. Property value inheritance is typically only enabled for properties where
  a particular scenario suggests that property value inheritance is appropriate. You can determine whether a dependency
  property inherits by looking at the Dependency Proper ty Information section for that dependency property in the
  SDK reference.
The following example shows a binding, and sets the DataContext property that specifies the source of the
binding, which was not shown in the earlier binding example. Any subsequent bindings in child objects do not
need to specify the source, they can use the inherited value from DataContext in the parent StackPanel object.
(Alternatively, a child object could instead choose to directly specify its own DataContext or a Source in the
Binding, and to deliberately not use the inherited value for data context of its bindings.)
  NOTE
  The SDK documentation uses the terms "local value" or "locally set value" occasionally when discussing dependency
  properties. A locally set value is a property value that is set directly on an object instance in code, or as an attribute on an
  element in XAML.
In principle, for the first button, the property is set twice, but only one value applies: the value with the highest
precedence. A locally set value has the highest precedence (except for a running animation, but no animation
applies in this example) and thus the locally set value is used instead of the style setter value for the background
on the first button. The second button has no local value (and no other value with higher precedence than a style
setter) and thus the background in that button comes from the style setter.
   <StackPanel>
     <StackPanel.Resources>
       <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Red"/>
       </Style>
     </StackPanel.Resources>
     <Button Background="Green">I am NOT red!</Button>
     <Button>I am styled red</Button>
   </StackPanel>
  NOTE
  There are a number of properties defined on WPF elements that are not dependency properties. By and large, properties
  were implemented as dependency properties only when there were needs to support at least one of the scenarios
  enabled by the property system: data binding, styling, animation, default value support, inheritance, attached properties,
  or invalidation.
See also
 Custom Dependency Properties
 Read-Only Dependency Properties
 XAML in WPF
 WPF Architecture
       Attached Properties Overview
      11/21/2022 • 10 minutes to read • Edit Online
An attached property is a concept defined by XAML. An attached property is intended to be used as a type of
global property that is settable on any dependency object. In Windows Presentation Foundation (WPF), attached
properties are typically defined as a specialized form of dependency property that does not have the
conventional property "wrapper".
Prerequisites
This article assumes that you understand dependency properties from the perspective of a consumer of existing
dependency properties on Windows Presentation Foundation (WPF) classes, and have read the Dependency
Properties Overview. To follow the examples in this article, you should also understand XAML and know how to
write WPF applications.
   <DockPanel>
       <TextBox DockPanel.Dock="Top">Enter text</TextBox>
   </DockPanel>
The usage is somewhat similar to a static property; you always reference the type DockPanel that owns and
registers the attached property, rather than referring to any instance specified by name.
Also, because an attached property in XAML is an attribute that you set in markup, only the set operation has
any relevance. You cannot directly get a property in XAML, although there are some indirect mechanisms for
comparing values, such as triggers in styles (for details, see Styling and Templating).
Attached Property Implementation in WPF
In Windows Presentation Foundation (WPF), most of the UI-related attached properties on WPF types are
implemented as dependency properties. Attached properties are a XAML concept, whereas dependency
properties are a WPF concept. Because WPF attached properties are dependency properties, they support
dependency property concepts such as property metadata, and default values from that property metadata.
Similar to the XAML case, if myCheckBox had not already been added as a child element of myDockPanel by the
fourth line of code, the fifth line of code would not raise an exception, but the property value would not interact
with a DockPanel parent and thus would do nothing. Only a DockPanel.Dock value set on a child element
combined with the presence of a DockPanel parent element will cause an effective behavior in the rendered
application. (In this case, you could set the attached property, then attach to the tree. Or you could attach to the
tree then set the attached property. Either action order provides the same result.)
   The target object can be specified as a more specific type in your implementation. For example, the
   DockPanel.GetDock method types the parameter as UIElement, because the attached property is only
   intended to be set on UIElement instances.
   The return value can be specified as a more specific type in your implementation. For example, the
   GetDock method types it as Dock, because the value can only be set to that enumeration.
The Set Accessor
The signature for the Set Proper tyName accessor must be:
public static void SetPropertyName(object target, object value)
   The target object can be specified as a more specific type in your implementation. For example, the
   SetDock method types it as UIElement, because the attached property is only intended to be set on
   UIElement instances.
   The value object can be specified as a more specific type in your implementation. For example, the
   SetDock method types it as Dock, because the value can only be set to that enumeration. Remember that
   the value for this method is the input coming from the XAML loader when it encounters your attached
   property in an attached property usage in markup. That input is the value specified as a XAML attribute
   value in markup. Therefore there must be type conversion, value serializer, or markup extension support
   for the type you use, such that the appropriate type can be created from the attribute value (which is
   ultimately just a string).
The following example shows the dependency property registration (using the RegisterAttached method), as
well as the Get Proper tyName and Set Proper tyName accessors. In the example, the attached property name
is IsBubbleSource . Therefore, the accessors must be named GetIsBubbleSource and SetIsBubbleSource .
See also
   DependencyProperty
   Dependency Properties Overview
   Custom Dependency Properties
   XAML in WPF
   Register an Attached Property
       Custom Dependency Properties
       11/21/2022 • 14 minutes to read • Edit Online
This topic describes the reasons that Windows Presentation Foundation (WPF) application developers and
component authors might want to create custom dependency property, and describes the implementation steps
as well as some implementation options that can improve performance, usability, or versatility of the property.
Prerequisites
This topic assumes that you understand dependency properties from the perspective of a consumer of existing
dependency properties on WPF classes, and have read the Dependency Properties Overview topic. In order to
follow the examples in this topic, you should also understand WPF applications.
  NOTE
  Defining the dependency property in the class body is the typical implementation, but it is also possible to define a
  dependency property in the class static constructor. This approach might make sense if you need more than one line of
  code to initialize the dependency property.
Again, by convention, the name of the wrapper property must be the same as the name chosen and given as
first parameter of the Register call that registered the property. If your property does not follow the convention,
this does not necessarily disable all possible uses, but you will encounter several notable issues:
   Certain aspects of styles and templates will not work.
   Most tools and designers must rely on the naming conventions to properly serialize XAML, or to provide
   designer environment assistance at a per-property level.
   The current implementation of the WPF XAML loader bypasses the wrappers entirely, and relies on the
   naming convention when processing attribute values. For more information, see XAML Loading and
   Dependency Properties.
See also
   Dependency Properties Overview
   Dependency Property Metadata
   Control Authoring Overview
   Collection-Type Dependency Properties
   Dependency Property Security
XAML Loading and Dependency Properties
Safe Constructor Patterns for DependencyObjects
       Dependency Property Metadata
       11/21/2022 • 10 minutes to read • Edit Online
The Windows Presentation Foundation (WPF) property system includes a metadata reporting system that goes
beyond what can be reported about a property through reflection or general common language runtime (CLR)
characteristics. Metadata for a dependency property can also be assigned uniquely by the class that defines a
dependency property, can be changed when the dependency property is added to a different class, and can be
specifically overridden by all derived classes that inherit the dependency property from the defining base class.
Prerequisites
This topic assumes that you understand dependency properties from the perspective of a consumer of existing
dependency properties on WPF applications.
Metadata APIs
The type that reports most of the metadata information used by the property system is the PropertyMetadata
class. Metadata instances are optionally specified when dependency properties are registered with the property
system, and can be specified again for additional types that either add themselves as owners or override
metadata they inherit from the base class dependency property definition. (For cases where a property
registration does not specify metadata, a default PropertyMetadata is created with default values for that
class.)The registered metadata is returned as PropertyMetadata when you call the various GetMetadata
overloads that get metadata from a dependency property on a DependencyObject instance.
The PropertyMetadata class is then derived from to provide more specific metadata for architectural divisions
such as the WPF framework-level classes. UIPropertyMetadata adds animation reporting, and
FrameworkPropertyMetadata provides the WPF framework-level properties mentioned in the previous section.
When dependency properties are registered, they can be registered with these PropertyMetadata derived
classes. When the metadata is examined, the base PropertyMetadata type can potentially be cast to the derived
classes so that you can examine the more specific properties.
  NOTE
  The property characteristics that can be specified in FrameworkPropertyMetadata are sometimes referred to in this
  documentation as "flags". When you create new metadata instances for use in dependency property registrations or
  metadata overrides, you specify these values using the flagwise enumeration FrameworkPropertyMetadataOptions and
  then you supply possibly concatenated values of the enumeration to the FrameworkPropertyMetadata constructor.
  However, once constructed, these option characteristics are exposed within a FrameworkPropertyMetadata as a series of
  Boolean properties rather than the constructing enumeration value. The Boolean properties enable you to check each
  conditional, rather than requiring you to apply a mask to a flagwise enumeration value to get the information you are
  interested in. The constructor uses the concatenated FrameworkPropertyMetadataOptions in order to keep the length of
  the constructor signature reasonable, whereas the actual constructed metadata exposes the discrete properties to make
  querying the metadata more intuitive.
Overriding Metadata
The purpose of overriding metadata is primarily so that you have the opportunity to change the various
metadata-derived behaviors that are applied to the dependency property as it exists on your type. The reasons
for this are explained in more detail in the Metadata section. For more information including some code
examples, see Override Metadata for a Dependency Property.
Property metadata can be supplied for a dependency property during the registration call (Register). However, in
many cases, you might want to provide type-specific metadata for your class when it inherits that dependency
property. You can do this by calling the OverrideMetadata method. For an example from the WPF APIs, the
FrameworkElement class is the type that first registers the Focusable dependency property. But the Control class
overrides metadata for the dependency property to provide its own initial default value, changing it from false
to true , and otherwise re-uses the original Focusable implementation.
When you override metadata, the different metadata characteristics are either merged or replaced.
   PropertyChangedCallback is merged. If you add a new PropertyChangedCallback, that callback is stored
   in the metadata. If you do not specify a PropertyChangedCallback in the override, the value of
   PropertyChangedCallback is promoted as a reference from the nearest ancestor that specified it in
   metadata.
   The actual property system behavior for PropertyChangedCallback is that implementations for all
   metadata owners in the hierarchy are retained and added to a table, with order of execution by the
   property system being that the most derived class's callbacks are invoked first.
   DefaultValue is replaced. If you do not specify a DefaultValue in the override, the value of DefaultValue
   comes from the nearest ancestor that specified it in metadata.
   CoerceValueCallback implementations are replaced. If you add a new CoerceValueCallback, that callback
   is stored in the metadata. If you do not specify a CoerceValueCallback in the override, the value of
   CoerceValueCallback is promoted as a reference from the nearest ancestor that specified it in metadata.
   The property system behavior is that only the CoerceValueCallback in the immediate metadata is
   invoked. No references to other CoerceValueCallback implementations in the hierarchy are retained.
This behavior is implemented by Merge, and can be overridden on derived metadata classes.
Overriding Attached Property Metadata
In WPF, attached properties are implemented as dependency properties. This means that they also have
property metadata, which individual classes can override. The scoping considerations for an attached property
in WPF are generally that any DependencyObject can have an attached property set on them. Therefore, any
DependencyObject derived class can override the metadata for any attached property, as it might be set on an
instance of the class. You can override default values, callbacks, or WPF framework-level characteristic-reporting
properties. If the attached property is set on an instance of your class, those override property metadata
characteristics apply. For instance, you can override the default value, such that your override value is reported
as the value of the attached property on instances of your class, whenever the property is not otherwise set.
  NOTE
  The Inherits property is not relevant for attached properties.
See also
   PropertyMetadata
   DependencyObject
   DependencyProperty
   GetMetadata
   Dependency Properties Overview
   Framework Property Metadata
       Dependency Property Callbacks and Validation
       11/21/2022 • 7 minutes to read • Edit Online
This topic describes how to create dependency properties using alternative custom implementations for
property-related features such as validation determination, callbacks that are invoked whenever the property's
effective value is changed, and overriding possible outside influences on value determination. This topic also
discusses scenarios where expanding on the default property system behaviors by using these techniques is
appropriate.
Prerequisites
This topic assumes that you understand the basic scenarios of implementing a dependency property, and how
metadata is applied to a custom dependency property. See Custom Dependency Properties and Dependency
Property Metadata for context.
Validation Callbacks
Validation callbacks can be assigned to a dependency property when you first register it. The validation callback
is not part of property metadata; it is a direct input of the Register method. Therefore, once a validation callback
is created for a dependency property, it cannot be overridden by a new implementation.
The callbacks are implemented such that they are provided an object value. They return true if the provided
value is valid for the property; otherwise, they return false . It is assumed that the property is of the correct
type per the type registered with the property system, so checking type within the callbacks is not ordinarily
done. The callbacks are used by the property system in a variety of different operations. This includes the initial
type initialization by default value, programmatic change by invoking SetValue, or attempts to override
metadata with new default value provided. If the validation callback is invoked by any of these operations, and
returns false , then an exception will be raised. Application writers must be prepared to handle these
exceptions. A common use of validation callbacks is validating enumeration values, or constraining values of
integers or doubles when the property sets measurements that must be zero or greater.
Validation callbacks specifically are intended to be class validators, not instance validators. The parameters of the
callback do not communicate a specific DependencyObject on which the properties to validate are set. Therefore
the validation callbacks are not useful for enforcing the possible "dependencies" that might influence a property
value, where the instance-specific value of a property is dependent on factors such as instance-specific values of
other properties, or run-time state.
The following is example code for a very simple validation callback scenario: validating that a property that is
typed as the Double primitive is not PositiveInfinity or NegativeInfinity.
The property changed callback for Current is used to forward the change to other dependent properties, by
explicitly invoking the coerce value callbacks that are registered for those other properties:
The coerce value callback checks the values of properties that the current property is potentially dependent
upon, and coerces the current value if necessary:
  NOTE
  Default values of properties are not coerced. A property value equal to the default value might occur if a property value
  still has its initial default, or through clearing other values with ClearValue.
The coerce value and property changed callbacks are part of property metadata. Therefore, you can change the
callbacks for a particular dependency property as it exists on a type that you derive from the type that owns the
dependency property, by overriding the metadata for that property on your type.
See also
   Dependency Properties Overview
   Dependency Property Metadata
   Custom Dependency Properties
      Framework Property Metadata
      11/21/2022 • 5 minutes to read • Edit Online
Framework property metadata options are reported for the properties of object elements considered to be at
the WPF framework level in the WPF presentation APIs and executables. Framework property metadata is
queried by these systems to determine feature-specific characteristics of particular element properties.
Prerequisites
This topic assumes that you understand dependency properties from the perspective of a consumer of existing
dependency properties on Windows Presentation Foundation (WPF) classes, and have read the Dependency
Properties Overview. You should also have read Dependency Property Metadata.
     NOTE
     The term "inherits" in the context of property values means something specific for dependency properties; it
     means that child elements can inherit the actual dependency property value from parent elements because of a
     WPF framework-level capability of the WPF property system. It has nothing to do directly with managed code
     type and members inheritance through derived types. For details, see Property Value Inheritance.
Reading FrameworkPropertyMetadata
Each of the properties linked above are the specific properties that the FrameworkPropertyMetadata adds to its
immediate base class UIPropertyMetadata. Each of these properties will be false by default. A metadata
request for a property where knowing the value of these properties is important should attempt to cast the
returned metadata to FrameworkPropertyMetadata, and then check the values of the individual properties as
needed.
Specifying Metadata
When you create a new metadata instance for purposes of applying metadata to a new dependency property
registration, you have the choice of which metadata class to use: the base PropertyMetadata or some derived
class such as FrameworkPropertyMetadata. In general, you should use FrameworkPropertyMetadata,
particularly if your property has any interaction with property system and WPF functions such as layout and
data binding. Another option for more sophisticated scenarios is to derive from FrameworkPropertyMetadata to
create your own metadata reporting class with extra information carried in its members. Or you might use
PropertyMetadata or UIPropertyMetadata to communicate the degree of support for features of your
implementation.
For existing properties (AddOwner or OverrideMetadata call), you should always override with the metadata
type used by the original registration.
If you are creating a FrameworkPropertyMetadata instance, there are two ways to populate that metadata with
values for the specific properties that communicate the framework property characteristics:
1. Use the FrameworkPropertyMetadata constructor signature that allows a flags parameter. This
   parameter should be filled with all desired combined values of the FrameworkPropertyMetadataOptions
   enumeration flags.
2. Use one of the signatures without a flags parameter, and then set each reporting Boolean property on
   FrameworkPropertyMetadata to true for each desired characteristic change. If you do this, you must set
   these properties before any elements with this dependency property are constructed; the Boolean
   properties are read-write in order to allow this behavior of avoiding the flags parameter and still
   populate the metadata, but the metadata must become effectively sealed before property use. Thus,
   attempting to set the properties after metadata is requested will be an invalid operation.
See also
   GetMetadata
   Dependency Property Metadata
   Dependency Properties Overview
   Custom Dependency Properties
       Dependency Property Value Precedence
      11/21/2022 • 14 minutes to read • Edit Online
This topic explains how the workings of the Windows Presentation Foundation (WPF) property system can affect
the value of a dependency property, and describes the precedence by which aspects of the property system
apply to the effective value of a property.
Prerequisites
This topic assumes that you understand dependency properties from the perspective of a consumer of existing
dependency properties on WPF classes, and have read Dependency Properties Overview. To follow the
examples in this topic, you should also understand WPF applications.
   <StackPanel>
       <StackPanel.Resources>
           <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
                <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding
   BorderThickness}"
                        BorderBrush="{TemplateBinding BorderBrush}">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
           </ControlTemplate>
       </StackPanel.Resources>
 TemplatedParent
 TemplatedParent as a precedence item does not apply to any property of an element that you declare directly in
 standard application markup. The TemplatedParent concept exists only for child items within a visual tree that
 come into existence through the application of the template. When the property system searches the
 TemplatedParent template for a value, it is searching the template that created that element. The property values
 from the TemplatedParent template generally act as if they were set as a local value on the child element, but
 this lesser precedence versus the local value exists because the templates are potentially shared. For details, see
 TemplatedParent.
SetCurrentValue
The SetCurrentValue method is another way to set a property, but it is not in the order of precedence. Instead,
SetCurrentValue enables you to change the value of a property without overwriting the source of a previous
value. You can use SetCurrentValue any time that you want to set a value without giving that value the
precedence of a local value. For example, if a property is set by a trigger and then assigned another value via
SetCurrentValue, the property system still respects the trigger and the property will change if the trigger’s
action occurs. SetCurrentValue enables you to change the property’s value without giving it a source with a
higher precedence. Likewise, you can use SetCurrentValue to change the value of a property without
overwriting a binding.
Trigger Behaviors
Controls often define trigger behaviors as part of their default style in themes. Setting local properties on
controls might prevent the triggers from being able to respond to user-driven events either visually or
behaviorally. The most common use of a property trigger is for control or state properties such as IsSelected.
For example, by default when a Button is disabled (trigger for IsEnabled is false ) then the Foreground value in
the theme style is what causes the control to appear "grayed out". But if you have set a local Foreground value,
that normal gray-out color will be overruled in precedence by your local property set, even in this property-
triggered scenario. Be cautious of setting values for properties that have theme-level trigger behaviors and
make sure you are not unduly interfering with the intended user experience for that control.
See also
   DependencyObject
   DependencyProperty
   Dependency Properties Overview
   Custom Dependency Properties
   Dependency Property Callbacks and Validation
       Read-Only Dependency Properties
       11/21/2022 • 3 minutes to read • Edit Online
This topic describes read-only dependency properties, including existing read-only dependency properties and
the scenarios and techniques for creating a custom read-only dependency property.
Prerequisites
This topic assumes that you understand the basic scenarios of implementing a dependency property, and how
metadata is applied to a custom dependency property. See Custom Dependency Properties and Dependency
Property Metadata for context.
See also
   Dependency Properties Overview
   Custom Dependency Properties
   Styling and Templating
       Property Value Inheritance
       11/21/2022 • 4 minutes to read • Edit Online
Property value inheritance is a feature of the Windows Presentation Foundation (WPF) property system.
Property value inheritance enables child elements in a tree of elements to obtain the value of a particular
property from parent elements, inheriting that value as it was set anywhere in the nearest parent element. The
parent element might also have obtained its value through property value inheritance, so the system potentially
recurses all the way to the page root. Property value inheritance is not the default property system behavior; a
property must be established with a particular metadata setting in order to cause that property to initiate
property value inheritance on child elements.
  NOTE
  Although property value inheritance might appear to work for nonattached dependency properties, the inheritance
  behavior for a nonattached property through certain element boundaries in the run-time tree is undefined. Always use
  RegisterAttached to register properties where you specify Inherits in the metadata.
See also
   Dependency Property Metadata
   Attached Properties Overview
   Dependency Property Value Precedence
       Dependency Property Security
       11/21/2022 • 2 minutes to read • Edit Online
Dependency properties should generally be considered to be public properties. The nature of the Windows
Presentation Foundation (WPF) property system prevents the ability to make security guarantees about a
dependency property value.
  NOTE
  Declaring a DependencyProperty identifier field private is not forbidden, and it can conceivably be used to help reduce the
  immediately exposed namespace of a custom class, but such a property should not be considered "private" in the same
  sense as the common language runtime (CLR) language definitions define that access level, for reasons described in the
  next section.
See also
   Custom Dependency Properties
       Safe Constructor Patterns for DependencyObjects
       11/21/2022 • 5 minutes to read • Edit Online
Generally, class constructors should not call callbacks such as virtual methods or delegates, because
constructors can be called as base initialization of constructors for a derived class. Entering the virtual might be
done at an incomplete initialization state of any given object. However, the property system itself calls and
exposes callbacks internally, as part of the dependency property system. As simple an operation as setting a
dependency property value with SetValue call potentially includes a callback somewhere in the determination.
For this reason, you should be careful when setting dependency property values within the body of a
constructor, which can become problematic if your type is used as a base class. There is a particular pattern for
implementing DependencyObject constructors that avoids specific problems with dependency property states
and the inherent callbacks, which is documented here.
This is a rule that is part of the default public rule set for FXCop. What this rule might be reporting is a trace
through the dependency property system that eventually calls a dependency property system virtual method.
This rule violation might continue to appear even after following the recommended constructor patterns
documented in this topic, so you might need to disable or suppress that rule in your FXCop rule set
configuration.
Most Issues Come From Deriving Classes, Not Using Existing Classes
The issues reported by this rule occur when a class that you implement with virtual methods in its construction
sequence is then derived from. If you seal your class, or otherwise know or enforce that your class will not be
derived from, the considerations explained here and the issues that motivated the FXCop rule do not apply to
you. However, if you are authoring classes in such a way that they are intended to be used as base classes, for
instance if you are creating templates, or an expandable control library set, you should follow the patterns
recommended here for constructors.
Default Constructors Must Initialize All Values Requested By Callbacks
Any instance members that are used by your class overrides or callbacks (the callbacks from the list in the
Property System Virtuals section) must be initialized in your class parameterless constructor, even if some of
those values are filled by "real" values through parameters of the nonparameterless constructors.
The following example code (and subsequent examples) is a pseudo-C# example that violates this rule and
explains the problem:
   public class MyClass : DependencyObject
   {
       public MyClass() {}
       public MyClass(object toSetWobble)
           : this()
       {
           Wobble = toSetWobble; //this is backed by a DependencyProperty
           _myList = new ArrayList();     // this line should be in the default ctor
       }
       public static readonly DependencyProperty WobbleProperty =
           DependencyProperty.Register("Wobble", typeof(object), typeof(MyClass));
       public object Wobble
       {
           get { return GetValue(WobbleProperty); }
           set { SetValue(WobbleProperty, value); }
       }
       protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
       {
           int count = _myList.Count;     // null-reference exception
       }
       private ArrayList _myList;
   }
When application code calls new MyClass(objectvalue) , this calls the parameterless constructor and base class
constructors. Then it sets Property1 = object1 , which calls the virtual method OnPropertyChanged on the owning
 MyClass DependencyObject. The override refers to _myList , which has not been initialized yet.
One way to avoid these issues is to make sure that callbacks use only other dependency properties, and that
each such dependency property has an established default value as part of its registered metadata.
See also
   Custom Dependency Properties
   Dependency Properties Overview
   Dependency Property Security
       Collection-Type Dependency Properties
       11/21/2022 • 4 minutes to read • Edit Online
This topic provides guidance and suggested patterns for how to implement a dependency property where the
type of the property is a collection type.
  WARNING
  The following code does not behave correctly.
   public class Fish : FrameworkElement { }
   public class Aquarium : DependencyObject {
       private static readonly DependencyPropertyKey AquariumContentsPropertyKey =
           DependencyProperty.RegisterReadOnly(
              "AquariumContents",
              typeof(List<FrameworkElement>),
              typeof(Aquarium),
              new FrameworkPropertyMetadata(new List<FrameworkElement>())
           );
       public static readonly DependencyProperty AquariumContentsProperty =
           AquariumContentsPropertyKey.DependencyProperty;
       // ...
   }
' ...
End Class
However, if you just left the code as shown, that single list default value is shared for all instances of Aquarium . If
you ran the following test code, which is intended to show how you would instantiate two separate Aquarium
instances and add a single different Fish to each of them, you would see a surprising result:
Instead of each collection having a count of one, each collection has a count of two! This is because each
 Aquarium added its Fish to the default value collection, which resulted from a single constructor call in the
metadata and is therefore shared between all instances. This situation is almost never what you want.
To correct this problem, you must reset the collection dependency property value to a unique instance, as part of
the class constructor call. Because the property is a read-only dependency property, you use the
SetValue(DependencyPropertyKey, Object) method to set it, using the DependencyPropertyKey that is only
accessible within the class.
Now, if you ran that same test code again, you could see more expected results, where each       Aquarium
supported its own unique collection.
There would be a slight variation on this pattern if you chose to have your collection property be read-write. In
that case, you could call the public set accessor from the constructor to do the initialization, which would still be
calling the nonkey signature of SetValue(DependencyProperty, Object) within your set wrapper, using a public
DependencyProperty identifier.
See also
   FreezableCollection<T>
   XAML and Custom Classes for WPF
   Data Binding Overview
   Dependency Properties Overview
   Custom Dependency Properties
Dependency Property Metadata
       XAML Loading and Dependency Properties
       11/21/2022 • 2 minutes to read • Edit Online
The current WPF implementation of its WPF XAML processor uses property system methods for dependency
properties when loading binary XAML and processing attributes that are dependency properties. This effectively
bypasses the property wrappers. When you implement custom dependency properties, you must account for
this behavior and should avoid placing any other code in your property wrapper other than the property system
methods GetValue and SetValue.
Prerequisites
This topic assumes that you understand dependency properties both as consumer and author and have read
Dependency Properties Overview and Custom Dependency Properties. You should also have read XAML in WPF
and XAML Syntax In Detail.
The following example is a recommended dependency property definition with wrappers, where the property
identifier is stored as a public static readonly field, and the get and set definitions contain no code
beyond the necessary property system methods that define the dependency property backing.
 public static readonly DependencyProperty AquariumGraphicProperty = DependencyProperty.Register(
    "AquariumGraphic",
    typeof(Uri),
    typeof(AquariumObject),
    new FrameworkPropertyMetadata(null,
        FrameworkPropertyMetadataOptions.AffectsRender,
        new PropertyChangedCallback(OnUriChanged)
    )
 );
 public Uri AquariumGraphic
 {
    get { return (Uri)GetValue(AquariumGraphicProperty); }
    set { SetValue(AquariumGraphicProperty, value); }
 }
See also
 Dependency Properties Overview
 XAML in WPF
 Dependency Property Metadata
 Collection-Type Dependency Properties
 Dependency Property Security
 Safe Constructor Patterns for DependencyObjects
      Properties How-to Topics
      11/21/2022 • 2 minutes to read • Edit Online
In This Section
Implement a Dependency Property
Add an Owner Type for a Dependency Property
Register an Attached Property
Override Metadata for a Dependency Property
Reference
DependencyProperty
PropertyMetadata
FrameworkPropertyMetadata
DependencyObject
Related Sections
Properties
       How to: Implement a Dependency Property
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to back a common language runtime (CLR) property with a DependencyProperty field,
thus defining a dependency property. When you define your own properties and want them to support many
aspects of Windows Presentation Foundation (WPF) functionality, including styles, data binding, inheritance,
animation, and default values, you should implement them as a dependency property.
Example
The following example first registers a dependency property by calling the Register method. The name of the
identifier field that you use to store the name and characteristics of the dependency property must be the Name
you chose for the dependency property as part of the Register call, appended by the literal string Property . For
instance, if you register a dependency property with a Name of Location , then the identifier field that you
define for the dependency property must be named LocationProperty .
In this example, the name of the dependency property and its CLR accessor is State ; the identifier field is
 StateProperty ; the type of the property is Boolean; and the type that registers the dependency property is
 MyStateControl .
If you fail to follow this naming pattern, designers might not report your property correctly, and certain aspects
of property system style application might not behave as expected.
You can also specify default metadata for a dependency property. This example registers the default value of the
 State dependency property to be false .
See also
   Dependency Properties Overview
   How-to Topics
      How to: Add an Owner Type for a Dependency
      Property
      11/21/2022 • 2 minutes to read • Edit Online
This example shows how to add a class as an owner of a dependency property registered for a different type. By
doing this, the WPF XAML reader and property system are both able to recognize the class as an additional
owner of the property. Adding as owner optionally allows the adding class to provide type-specific metadata.
In the following example, StateProperty is a property registered by the MyStateControl class. The class
 UnrelatedStateControl adds itself as an owner of the StateProperty using the AddOwner method, specifically
using the signature that allows for new metadata for the dependency property as it exists on the adding type.
Notice that you should provide common language runtime (CLR) accessors for the property similar to the
example shown in the Implement a Dependency Property example, as well as re-expose the dependency
property identifier on the class being added as owner.
Without wrappers, the dependency property would still work from the perspective of programmatic access
using GetValue or SetValue. But you typically want to parallel this property-system behavior with the CLR
property wrappers. The wrappers make it easier to set the dependency property programmatically, and make it
possible to set the properties as XAML attributes.
To find out how to override default metadata, see Override Metadata for a Dependency Property.
Example
   public class MyStateControl : ButtonBase
   {
     public MyStateControl() : base() { }
     public Boolean State
     {
       get { return (Boolean)this.GetValue(StateProperty); }
       set { this.SetValue(StateProperty, value); }
     }
     public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
       "State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(false));
   }
See also
 Custom Dependency Properties
 Dependency Properties Overview
       How to: Register an Attached Property
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to register an attached property and provide public accessors so that you can use the
property in both WPF types are also implemented as dependency properties. You can use dependency
properties on any DependencyObject types.
Example
The following example shows how to register an attached property as a dependency property, by using the
RegisterAttached method. The provider class has the option of providing default metadata for the property that
is applicable when the property is used on another class, unless that class overrides the metadata. In this
example, the default value of the IsBubbleSource property is set to false .
The provider class for an attached property (even if it is not registered as a dependency property) must provide
static get and set accessors that follow the naming convention Set [AttachedPropertyName] and Get
[AttachedPropertyName]. These accessors are required so that the acting XAML reader can recognize the
property as an attribute in XAML and resolve the appropriate types.
See also
   DependencyProperty
   Dependency Properties Overview
   Custom Dependency Properties
   How-to Topics
       How to: Override Metadata for a Dependency
       Property
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to override default dependency property metadata that comes from an inherited class,
by calling the OverrideMetadata method and providing type-specific metadata.
Example
By defining its PropertyMetadata, a class can define the dependency property's behaviors, such as its default
value and property system callbacks. Many dependency property classes already have default metadata
established as part of their registration process. This includes the dependency properties that are part of the
WPF API. A class that inherits the dependency property through its class inheritance can override the original
metadata so that the characteristics of the property that can be altered through metadata will match any
subclass-specific requirements.
Overriding metadata on a dependency property must be done prior to that property being placed in use by the
property system (this equates to the time that specific instances of objects that register the property are
instantiated). Calls to OverrideMetadata must be performed within the static constructors of the type that
provides itself as the forType parameter of OverrideMetadata. If you attempt to change metadata once
instances of the owner type exist, this will not raise exceptions, but will result in inconsistent behaviors in the
property system. Also, metadata can only be overridden once per type. Subsequent attempts to override
metadata on the same type will raise an exception.
In the following example, the custom class MyAdvancedStateControl overrides the metadata provided for
 StateProperty by MyAdvancedStateControl with new property metadata. For instance, the default value of the
 StateProperty is now true when the property is queried on a newly constructed MyAdvancedStateControl
instance.
See also
 DependencyProperty
 Dependency Properties Overview
 Custom Dependency Properties
 How-to Topics
       Events (WPF)
      11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) introduces routed events that can invoke handlers that exist on
various listeners in the element tree of an application.
In This Section
Routed Events Overview
Attached Events Overview
Object Lifetime Events
Marking Routed Events as Handled, and Class Handling
Preview Events
Property Change Events
Visual Basic and WPF Event Handling
Weak Event Patterns
How-to Topics
Reference
RoutedEvent
EventManager
RoutingStrategy
Related Sections
WPF Architecture
XAML in WPF
Base Elements
Element Tree and Serialization
Properties
Input
Resources
Styling and Templating
WPF Content Model
Threading Model
       Routed Events Overview
       11/21/2022 • 23 minutes to read • Edit Online
This topic describes the concept of routed events in Windows Presentation Foundation (WPF). The topic defines
routed events terminology, describes how routed events are routed through a tree of elements, summarizes
how you handle routed events, and introduces how to create your own custom routed events.
Prerequisites
This topic assumes that you have basic knowledge of the common language runtime (CLR) and object-oriented
programming, as well as the concept of how the relationships between WPF elements can be conceptualized as
a tree. In order to follow the examples in this topic, you should also understand WPF applications or pages. For
more information, see Walkthrough: My first WPF desktop application and XAML in WPF.
In this simplified element tree, the source of a Click event is one of the Button elements, and whichever Button
was clicked is the first element that has the opportunity to handle the event. But if no handler attached to the
Button acts on the event, then the event will bubble upwards to the Button parent in the element tree, which is
the StackPanel. Potentially, the event bubbles to Border, and then beyond to the page root of the element tree
(not shown).
In other words, the event route for this Click event is:
Button-->StackPanel-->Border-->...
Top-level Scenarios for Routed Events
The following is a brief summary of the scenarios that motivated the routed event concept, and why a typical
CLR event was not adequate for these scenarios:
Control composition and encapsulation: Various controls in WPF have a rich content model. For example,
you can place an image inside of a Button, which effectively extends the visual tree of the button. However, the
added image must not break the hit-testing behavior that causes a button to respond to a Click of its content,
even if the user clicks on pixels that are technically part of the image.
Singular handler attachment points: In Windows Forms, you would have to attach the same handler
multiple times to process events that could be raised from multiple elements. Routed events enable you to
attach that handler only once, as was shown in the previous example, and use handler logic to determine where
the event came from if necessary. For instance, this might be the handler for the previously shown XAML:
Class handling: Routed events permit a static handler that is defined by the class. This class handler has the
opportunity to handle an event before any attached instance handlers can.
Referencing an event without reflection: Certain code and markup techniques require a way to identify a
specific event. A routed event creates a RoutedEvent field as an identifier, which provides a robust event
identification technique that does not require static or run-time reflection.
How Routed Events Are Implemented
A routed event is a CLR event that is backed by an instance of the RoutedEvent class and registered with the
WPF event system. The RoutedEvent instance obtained from registration is typically retained as a public
static     readonly field member of the class that registers and thus "owns" the routed event. The connection to
the identically named CLR event (which is sometimes termed the "wrapper" event) is accomplished by
overriding the add and remove implementations for the CLR event. Ordinarily, the add and remove are left as
an implicit default that uses the appropriate language-specific event syntax for adding and removing handlers of
that event. The routed event backing and connection mechanism is conceptually similar to how a dependency
property is a CLR property that is backed by the DependencyProperty class and registered with the WPF
property system.
The following example shows the declaration for a custom Tap routed event, including the registration and
exposure of the RoutedEvent identifier field and the add and remove implementations for the Tap CLR event.
<Button Click="b1SetColor">button</Button>
The XAML syntax for adding standard CLR event handlers is the same for adding routed event handlers, because
you are really adding handlers to the CLR event wrapper, which has a routed event implementation underneath.
For more information about adding event handlers in XAML, see XAML in WPF.
Routing Strategies
Routed events use one of three routing strategies:
   Bubbling: Event handlers on the event source are invoked. The routed event then routes to successive
   parent elements until reaching the element tree root. Most routed events use the bubbling routing
   strategy. Bubbling routed events are generally used to report input or state changes from distinct
   controls or other UI elements.
   Direct: Only the source element itself is given the opportunity to invoke handlers in response. This is
   analogous to the "routing" that Windows Forms uses for events. However, unlike a standard CLR event,
   direct routed events support class handling (class handling is explained in an upcoming section) and can
   be used by EventSetter and EventTrigger.
   Tunneling: Initially, event handlers at the element tree root are invoked. The routed event then travels a
   route through successive child elements along the route, towards the node element that is the routed
   event source (the element that raised the routed event). Tunneling routed events are often used or
   handled as part of the compositing for a control, such that events from composite parts can be
   deliberately suppressed or replaced by events that are specific to the complete control. Input events
   provided in WPF often come implemented as a tunneling/bubbling pair. Tunneling events are also
   sometimes referred to as Preview events, because of a naming convention that is used for the pairs.
b1SetColor   is the name of the implemented handler that contains the code that handles the Click event.
 b1SetColor must have the same signature as the RoutedEventHandler delegate, which is the event handler
delegate for the Click event. The first parameter of all routed event handler delegates specifies the element to
which the event handler is added, and the second parameter specifies the data for the event.
RoutedEventHandler is the basic routed event handler delegate. For routed events that are specialized for certain
controls or scenarios, the delegates to use for the routed event handlers also might become more specialized, so
that they can transmit specialized event data. For instance, in a common input scenario, you might handle a
DragEnter routed event. Your handler should implement the DragEventHandler delegate. By using the most
specific delegate, you can process the DragEventArgs in the handler and read the Data property, which contains
the clipboard payload of the drag operation.
For a complete example of how to add an event handler to an element using XAML, see Handle a Routed Event.
Adding a handler for a routed event in an application that is created in code is straightforward. Routed event
handlers can always be added through a helper method AddHandler (which is the same method that the
existing backing calls for add .) However, existing WPF routed events generally have backing implementations of
 add and remove logic that allow the handlers for routed events to be added by a language-specific event
syntax, which is more intuitive syntax than the helper method. The following is an example usage of the helper
method:
   void MakeButton()
    {
        Button b2 = new Button();
        b2.AddHandler(Button.ClickEvent, new RoutedEventHandler(Onb2Click));
    }
    void Onb2Click(object sender, RoutedEventArgs e)
    {
        //logic to handle the Click event
    }
The next example shows the C# operator syntax (Visual Basic has slightly different operator syntax because of its
handling of dereferencing):
   void MakeButton2()
   {
     Button b2 = new Button();
     b2.Click += new RoutedEventHandler(Onb2Click2);
   }
   void Onb2Click2(object sender, RoutedEventArgs e)
   {
     //logic to handle the Click event
   }
For an example of how to add an event handler in code, see Add an Event Handler Using Code.
If you are using Visual Basic, you can also use the Handles keyword to add handlers as part of the handler
declarations. For more information, see Visual Basic and WPF Event Handling.
In addition to the behavior that Handled state produces in routed events, the concept of Handled has
implications for how you should design your application and write the event handler code. You can
conceptualize Handled as being a simple protocol that is exposed by routed events. Exactly how you use this
protocol is up to you, but the conceptual design for how the value of Handled is intended to be used is as
follows:
   If a routed event is marked as handled, then it does not need to be handled again by other elements
   along that route.
   If a routed event is not marked as handled, then other listeners that were earlier along the route have
   chosen either not to register a handler, or the handlers that were registered chose not to manipulate the
   event data and set Handled to true . (Or, it is of course possible that the current listener is the first point
   in the route.) Handlers on the current listener now have three possible courses of action:
      Take no action at all; the event remains unhandled, and the event routes to the next listener.
      Execute code in response to the event, but make the determination that the action taken was not
      substantial enough to warrant marking the event as handled. The event routes to the next listener.
      Execute code in response to the event. Mark the event as handled in the event data passed to the
      handler, because the action taken was deemed substantial enough to warrant marking as handled.
      The event still routes to the next listener, but with Handled= true in its event data, so only
       handledEventsToo listeners have the opportunity to invoke further handlers.
This conceptual design is reinforced by the routing behavior mentioned earlier: it is more difficult (although still
possible in code or styles) to attach handlers for routed events that are invoked even if a previous handler along
the route has already set Handled to true .
For more information about Handled, class handling of routed events, and recommendations about when it is
appropriate to mark a routed event as Handled, see Marking Routed Events as Handled, and Class Handling.
In applications, it is quite common to just handle a bubbling routed event on the object that raised it, and not be
concerned with the event's routing characteristics at all. However, it is still a good practice to mark the routed
event as handled in the event data, to prevent unanticipated side effects just in case an element that is further up
the element tree also has a handler attached for that same routed event.
Class Handlers
If you are defining a class that derives in some way from DependencyObject, you can also define and attach a
class handler for a routed event that is a declared or inherited event member of your class. Class handlers are
invoked before any instance listener handlers that are attached to an instance of that class, whenever a routed
event reaches an element instance in its route.
Some WPF controls have inherent class handling for certain routed events. This might give the outward
appearance that the routed event is not ever raised, but in reality it is being class handled, and the routed event
can potentially still be handled by your instance handlers if you use certain techniques. Also, many base classes
and controls expose virtual methods that can be used to override class handling behavior. For more information
both on how to work around undesired class handling and on defining your own class handling in a custom
class, see Marking Routed Events as Handled, and Class Handling.
Here, the parent element listener where the handler is added is a StackPanel. However, it is adding a handler for
a routed event that was declared and will be raised by the Button class (ButtonBase actually, but available to
Button through inheritance). Button "owns" the event, but the routed event system permits handlers for any
routed event to be attached to any UIElement or ContentElement instance listener that could otherwise attach
listeners for a common language runtime (CLR) event. The default xmlns namespace for these qualified event
attribute names is typically the default WPF xmlns namespace, but you can also specify prefixed namespaces for
custom routed events. For more information about xmlns, see XAML Namespaces and Namespace Mapping for
WPF XAML.
A routed event handler delegate provides references to two objects: the object that raised the event and the
object where the handler was invoked. The object where the handler was invoked is the object reported by the
 sender parameter. The object where the event was first raised is reported by the Source property in the event
data. A routed event can still be raised and handled by the same object, in which case sender and Source are
identical (this is the case with Steps 3 and 4 in the event processing example list).
Because of tunneling and bubbling, parent elements receive input events where the Source is one of their child
elements. When it is important to know what the source element is, you can identify the source element by
accessing the Source property.
Usually, once the input event is marked Handled, further handlers are not invoked. Typically, you should mark
input events as handled as soon as a handler is invoked that addresses your application-specific logical handling
of the meaning of the input event.
The exception to this general statement about Handled state is that input event handlers that are registered to
deliberately ignore Handled state of the event data would still be invoked along either route. For more
information, see Preview Events or Marking Routed Events as Handled, and Class Handling.
The shared event data model between tunneling and bubbling events, and the sequential raising of first
tunneling then bubbling events, is not a concept that is generally true for all routed events. That behavior is
specifically implemented by how WPF input devices choose to raise and connect the input event pairs.
Implementing your own input events is an advanced scenario, but you might choose to follow that model for
your own input events also.
Certain classes choose to class-handle certain input events, usually with the intent of redefining what a
particular user-driven input event means within that control and raising a new event. For more information, see
Marking Routed Events as Handled, and Class Handling.
For more information on input and how input and events interact in typical application scenarios, see Input
Overview.
   <StackPanel
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="SDKSample.EventOvw2"
     Name="dpanel2"
     Initialized="PrimeHandledToo"
   >
     <StackPanel.Resources>
       <Style TargetType="{x:Type Button}">
         <EventSetter Event="Click" Handler="b1SetColor"/>
       </Style>
     </StackPanel.Resources>
     <Button>Click me</Button>
     <Button Name="ThisButton" Click="HandleThis">
       Raise event, handle it, use handled=true handler to get it anyway.
     </Button>
   </StackPanel>
The advantage gained here is that the style is likely to contain a great deal of other information that could apply
to any button in your application, and having the EventSetter be part of that style promotes code reuse even at
the markup level. Also, an EventSetter abstracts method names for handlers one step further away from the
general application and page markup.
Another specialized syntax that combines the routed event and animation features of WPF is an EventTrigger. As
with EventSetter, only routed events may be used for an EventTrigger. Typically, an EventTrigger is declared as
part of a style, but an EventTrigger can also be declared on page-level elements as part of the Triggers collection,
or in a ControlTemplate. An EventTrigger enables you to specify a Storyboard that runs whenever a routed event
reaches an element in its route that declares an EventTrigger for that event. The advantage of an EventTrigger
over just handling the event and causing it to start an existing storyboard is that an EventTrigger provides better
control over the storyboard and its run-time behavior. For more information, see Use Event Triggers to Control a
Storyboard After It Starts.
See also
   EventManager
   RoutedEvent
   RoutedEventArgs
Marking Routed Events as Handled, and Class Handling
Input Overview
Commanding Overview
Custom Dependency Properties
Trees in WPF
Weak Event Patterns
       Attached Events Overview
       11/21/2022 • 6 minutes to read • Edit Online
Extensible Application Markup Language (XAML) defines a language component and type of event called an
attached event. The concept of an attached event enables you to add a handler for a particular event to an
arbitrary element rather than to an element that actually defines or inherits the event. In this case, neither the
object potentially raising the event nor the destination handling instance defines or otherwise "owns" the event.
Prerequisites
This topic assumes that you have read Routed Events Overview and XAML in WPF.
Note the aqua: prefix; the prefix is necessary in this case because the attached event is a custom event that
comes from a custom mapped xmlns.
   A method Remove EventName Handler with two parameters. The first parameter is the instance from
   which the event handler is removed. The second parameter is the event handler to remove. The method
   must be public and static , with no return value.
The Add EventName Handler accessor method facilitates XAML processing when attached event handler
attributes are declared on an element. The Add EventName Handler and Remove EventName Handler
methods also enable code access to the event handler store for the attached event.
This general pattern is not yet precise enough for practical implementation in a framework, because any given
XAML reader implementation might have different schemes for identifying underlying events in the supporting
language and architecture. This is one of the reasons that WPF implements attached events as routed events; the
identifier to use for an event (RoutedEvent) is already defined by the WPF event system. Also, routing an event is
a natural implementation extension on the XAML language-level concept of an attached event.
The Add EventName Handler implementation for a WPF attached event consists of calling the AddHandler with
the routed event and handler as arguments.
This implementation strategy and the routed event system in general restrict handling for attached events to
either UIElement derived classes or ContentElement derived classes, because only those classes have
AddHandler implementations.
For example, the following code defines the NeedsCleaning attached event on the owner class       Aquarium   , using
the WPF attached event strategy of declaring the attached event as a routed event.
   public static readonly RoutedEvent NeedsCleaningEvent = EventManager.RegisterRoutedEvent("NeedsCleaning",
   RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));
   public static void AddNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
   {
       UIElement uie = d as UIElement;
       if (uie != null)
       {
           uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler);
       }
   }
   public static void RemoveNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
   {
       UIElement uie = d as UIElement;
       if (uie != null)
       {
           uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler);
       }
   }
Note that the method used to establish the attached event identifier field, RegisterRoutedEvent, is actually the
same method that is used to register a non-attached routed event. Attached events and routed events all are
registered to a centralized internal store. This event store implementation enables the "events as an interface"
conceptual consideration that is discussed in Routed Events Overview.
See also
   Routed Events Overview
   XAML Syntax In Detail
   XAML and Custom Classes for WPF
       Object Lifetime Events
       11/21/2022 • 3 minutes to read • Edit Online
This topic describes the specific WPF events that signify stages in an object lifetime of creation, use, and
destruction.
Prerequisites
This topic assumes that you understand dependency properties from the perspective of a consumer of existing
dependency properties on WPF applications.
  NOTE
  This behavior might superficially resemble tunneling for a routed event. However, no information is carried from event to
  event. Each element always has the opportunity to handle its Loaded event, and marking the event data as handled has
  no effect beyond that element.
Unloaded
Unloaded is raised last and is initiated by either the presentation source or the visual parent being removed.
When Unloaded is raised and handled, the element that is the event source parent (as determined by Parent
property) or any given element upwards in the logical or visual trees may have already been unset, meaning
that data binding, resource references, and styles may not be set to their normal or last known run-time value.
See also
   Dependency Property Value Precedence
   Routed Events Overview
       Marking Routed Events as Handled, and Class
       Handling
       11/21/2022 • 14 minutes to read • Edit Online
Handlers for a routed event can mark the event handled within the event data. Handling the event will effectively
shorten the route. Class handling is a programming concept that is supported by routed events. A class handler
has the opportunity to handle a particular routed event at a class level with a handler that is invoked before any
instance handler on any instance of the class.
Prerequisites
This topic elaborates on concepts introduced in the Routed Events Overview.
Adding Instance Handlers That Are Raised Even When Events Are
Marked Handled
The AddHandler method supplies a particular overload that allows you to add handlers that will be invoked by
the event system whenever an event reaches the handling element in the route, even if some other handler has
already adjusted the event data to mark that event as handled. This is not typically done. Generally, handlers can
be written to adjust all areas of application code that might be influenced by an event, regardless of where it was
handled in an element tree, even if multiple end results are desired. Also, typically there is really only one
element that needs to respond to that event, and the appropriate application logic had already happened. But
the handledEventsToo overload is available for the exceptional cases where some other element in an element
tree or control compositing has already marked an event as handled, but other elements either higher or lower
in the element tree (depending on route) still wish to have their own handlers invoked.
When to Mark Handled Events as Unhandled
Generally, routed events that are marked handled should not be marked unhandled (Handled set back to false
) even by handlers that act on handledEventsToo . However, some input events have high-level and lower-level
event representations that can overlap when the high-level event is seen at one position in the tree and the low-
level event at another position. For instance, consider the case where a child element listens to a high-level key
event such as TextInput while a parent element listens to a low-level event such as KeyDown. If the parent
element handles the low-level event, the higher-level event can be suppressed even in the child element that
intuitively should have first opportunity to handle the event.
In these situations it may be necessary to add handlers to both parent elements and child elements for the low-
level event. The child element handler implementation can mark the low-level event as handled, but the parent
element handler implementation would set it unhandled again so that further elements up the tree (as well as
the high-level event) can have the opportunity to respond. This situation is should be fairly rare.
See also
   EventManager
   Preview Events
   Create a Custom Routed Event
   Routed Events Overview
       Preview Events
       11/21/2022 • 3 minutes to read • Edit Online
Preview events, also known as tunneling events, are routed events where the direction of the route travels from
the application root towards the element that raised the event and is reported as the source in event data. Not
all event scenarios support or require preview events; this topic describes the situations where preview events
exist, how applications or components should handle them, and cases where creating preview events in custom
components or classes might be appropriate.
See also
Marking Routed Events as Handled, and Class Handling
Routed Events Overview
       Property Change Events
       11/21/2022 • 5 minutes to read • Edit Online
Windows Presentation Foundation (WPF) defines several events that are raised in response to a change in the
value of a property. Often the property is a dependency property. The event itself is sometimes a routed event
and is sometimes a standard common language runtime (CLR) event. The definition of the event varies
depending on the scenario, because some property changes are more appropriately routed through an element
tree, whereas other property changes are generally only of concern to the object where the property changed.
Property Triggers
A closely related concept to a property changed event is a property trigger. A property trigger is created within a
style or template and enables you to create a conditional behavior based on the value of the property where the
property trigger is assigned.
The property for a property trigger must be a dependency property. It can be (and frequently is) a read-only
dependency property. A good indicator for when a dependency property exposed by a control is at least
partially designed to be a property trigger is if the property name begins with "Is". Properties that have this
naming are often a read-only Boolean dependency property where the primary scenario for the property is
reporting control state that might have consequences to the real-time UI and is thus a property trigger
candidate.
Some of these properties also have a dedicated property changed event. For instance, the property
IsMouseCaptured has a property changed event IsMouseCapturedChanged. The property itself is read-only,
with its value adjusted by the input system, and the input system raises IsMouseCapturedChanged on each real-
time change.
Compared to a true property changed event, using a property trigger to act on a property change has some
limitations.
Property triggers work through an exact match logic. You specify a property and a value that indicates the
specific value for which the trigger will act. For instance:
 <Setter Property="IsMouseCaptured" Value="true"> ... </Setter> . Because of this limitation, the majority of
property trigger usages will be for Boolean properties, or properties that take a dedicated enumeration value,
where the possible value range is manageable enough to define a trigger for each case. Or property triggers
might exist only for special values, such as when an items count reaches zero, and there would be no trigger that
accounts for the cases when the property value changes away from zero again (instead of triggers for all cases,
you might need a code event handler here, or a default behavior that toggles back from the trigger state again
when the value is nonzero).
The property trigger syntax is analogous to an "if" statement in programming. If the trigger condition is true,
then the "body" of the property trigger is "executed". The "body" of a property trigger is not code, it is markup.
That markup is limited to using one or more Setter elements to set other properties of the object where the style
or template is being applied.
To offset the "if" condition of a property trigger that has a wide variety of possible values, it is generally
advisable to set that same property value to a default by using a Setter. This way, the Trigger contained setter
will have precedence when the trigger condition is true, and the Setter that is not within a Trigger will have
precedence whenever the trigger condition is false.
Property triggers are generally appropriate for scenarios where one or more appearance properties should
change, based on the state of another property on the same element.
To learn more about property triggers, see Styling and Templating.
See also
   Routed Events Overview
   Dependency Properties Overview
       Visual Basic and WPF Event Handling
      11/21/2022 • 3 minutes to read • Edit Online
For the Microsoft Visual Basic .NET language specifically, you can use the language-specific Handles keyword to
associate event handlers with instances, instead of attaching event handlers with attributes or using the
AddHandler method. However, the Handles technique for attaching handlers to instances does have some
limitations, because the Handles syntax cannot support some of the specific routed event features of the WPF
event system.
  NOTE
  Do not use the Handles syntax in Visual Basic code when you specify an event handler for the same event in XAML. In
  this case, the event handler is called twice.
  NOTE
  Within Visual Studio, IntelliSense can show you completion for which elements are available for a Handles reference in a
  page. However, this might take one compile pass so that the intermediate file can populate all the Friends references.
See also
   AddHandler
   Marking Routed Events as Handled, and Class Handling
   Routed Events Overview
   XAML in WPF
       Weak Event Patterns
       11/21/2022 • 6 minutes to read • Edit Online
In applications, it is possible that handlers that are attached to event sources will not be destroyed in
coordination with the listener object that attached the handler to the source. This situation can lead to memory
leaks. Windows Presentation Foundation (WPF) introduces a design pattern that can be used to address this
issue, by providing a dedicated manager class for particular events and implementing an interface on listeners
for that event. This design pattern is known as the weak event pattern.
This technique creates a strong reference from the event source to the event listener. Ordinarily, attaching an
event handler for a listener causes the listener to have an object lifetime that is influenced by the object lifetime
of the source (unless the event handler is explicitly removed). But in certain circumstances, you might want the
object lifetime of the listener to be controlled by other factors, such as whether it currently belongs to the visual
tree of the application, and not by the lifetime of the source. Whenever the source object lifetime extends
beyond the object lifetime of the listener, the normal event pattern leads to a memory leak: the listener is kept
alive longer than intended.
The weak event pattern is designed to solve this memory leak problem. The weak event pattern can be used
whenever a listener needs to register for an event, but the listener does not explicitly know when to unregister.
The weak event pattern can also be used whenever the object lifetime of the source exceeds the useful object
lifetime of the listener. (In this case, useful is determined by you.) The weak event pattern allows the listener to
register for and receive the event without affecting the object lifetime characteristics of the listener in any way. In
effect, the implied reference from the source does not determine whether the listener is eligible for garbage
collection. The reference is a weak reference, thus the naming of the weak event pattern and the related APIs.
The listener can be garbage collected or otherwise destroyed, and the source can continue without retaining
noncollectible handler references to a now destroyed object.
  Use an existing weak event manager class                        If the event you want to subscribe to has a corresponding
                                                                  WeakEventManager, use the existing weak event manager.
                                                                  For a list of weak event managers that are included with
                                                                  WPF, see the inheritance hierarchy in the
                                                                  WeakEventManager class. Because the included weak event
                                                                  managers are limited, you will probably need to choose one
                                                                  of the other approaches.
  Create a custom weak event manager class                        Create a custom WeakEventManager when an existing
                                                                  WeakEventManager is not available and you want the best
                                                                  efficiency. Using a custom WeakEventManager to subscribe
                                                                  to an event will be more efficient, but you do incur the cost
                                                                  of writing more code at the beginning.
  Use a third-party weak event manager                            NuGet has several weak event managers and many WPF
                                                                  frameworks also support the pattern (for instance, see
                                                                  Prism's documentation on loosely coupled event
                                                                  subscription).
The following sections describe how to implement the weak event pattern. For purposes of this discussion, the
event to subscribe to has the following characteristics.
   The event name is    SomeEvent   .
   The event is raised by the   EventSource   class.
   The event handler has type:      SomeEventEventHandler   (or   EventHandler<SomeEventEventArgs>     ).
   The event passes a parameter of type       SomeEventEventArgs    to the event handlers.
Using an Existing Weak Event Manager Class
1. Find an existing weak event manager.
   For a list of weak event managers that are included with WPF, see the inheritance hierarchy in the
   WeakEventManager class.
2. Use the new weak event manager instead of the normal event hookup.
   For example, if your code uses the following pattern to subscribe to an event:
Similarly, if your code uses the following pattern to unsubscribe from an event:
SomeEventWeakEventManager.RemoveHandler(source, OnSomeEvent);
          private SomeEventWeakEventManager()
          {
          }
          /// <summary>
          /// Add a handler for the given source's event.
          /// </summary>
          public static void AddHandler(EventSource source,
                                        EventHandler<SomeEventEventArgs> handler)
          {
              if (source == null)
                  throw new ArgumentNullException("source");
              if (handler == null)
                  throw new ArgumentNullException("handler");
              CurrentManager.ProtectedAddHandler(source, handler);
          }
          /// <summary>
          /// Remove a handler for the given source's event.
          /// </summary>
          public static void RemoveHandler(EventSource source,
                                           EventHandler<SomeEventEventArgs> handler)
          {
              if (source == null)
                  throw new ArgumentNullException("source");
              if (handler == null)
                  throw new ArgumentNullException("handler");
              CurrentManager.ProtectedRemoveHandler(source, handler);
               CurrentManager.ProtectedRemoveHandler(source, handler);
          }
          /// <summary>
          /// Get the event manager for the current thread.
          /// </summary>
          private static SomeEventWeakEventManager CurrentManager
          {
              get
              {
                  Type managerType = typeof(SomeEventWeakEventManager);
                  SomeEventWeakEventManager manager =
                      (SomeEventWeakEventManager)GetCurrentManager(managerType);
                     return manager;
               }
          }
          /// <summary>
          /// Return a new list to hold listeners to the event.
          /// </summary>
          protected override ListenerList NewListenerList()
          {
              return new ListenerList<SomeEventEventArgs>();
          }
          /// <summary>
          /// Listen to the given source for the event.
          /// </summary>
          protected override void StartListening(object source)
          {
              EventSource typedSource = (EventSource)source;
              typedSource.SomeEvent += new EventHandler<SomeEventEventArgs>(OnSomeEvent);
          }
          /// <summary>
          /// Stop listening to the given source for the event.
          /// </summary>
          protected override void StopListening(object source)
          {
              EventSource typedSource = (EventSource)source;
              typedSource.SomeEvent -= new EventHandler<SomeEventEventArgs>(OnSomeEvent);
          }
          /// <summary>
          /// Event handler for the SomeEvent event.
          /// </summary>
          void OnSomeEvent(object sender, SomeEventEventArgs e)
          {
              DeliverEvent(sender, e);
          }
      }
4. Set the visibility (public / internal / private) of the weak event manager class to the same visibility as
   event it manages.
5. Use the new weak event manager instead of the normal event hookup.
  For example, if your code uses the following pattern to subscribe to an event:
SomeEventWeakEventManager.AddHandler(source, OnSomeEvent);
SomeEventWeakEventManager.RemoveHandler(source, OnSomeEvent);
See also
  WeakEventManager
  IWeakEventListener
  Routed Events Overview
  Data Binding Overview
       Events How-to Topics
       11/21/2022 • 2 minutes to read • Edit Online
In This Section
Add an Event Handler Using Code
Handle a Routed Event
Create a Custom Routed Event
Find the Source Element in an Event Handler
Add Class Handling for a Routed Event
Reference
RoutedEvent
EventManager
RoutingStrategy
Related Sections
       How to: Add an Event Handler Using Code
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to add an event handler to an element by using code.
If you want to add an event handler to a XAML element, and the markup page that contains the element has
already been loaded, you must add the handler using code. Alternatively, if you are building up the element tree
for an application entirely using code and not declaring any elements using XAML, you can call specific methods
to add event handlers to the constructed element tree.
Example
The following example adds a new Button to an existing page that is initially defined in XAML. A code-behind file
implements an event handler method and then adds that method as a new event handler on the Button.
The C# example uses the += operator to assign a handler to an event. This is the same operator that is used to
assign a handler in the common language runtime (CLR) event handling model. Microsoft Visual Basic does not
support this operator as a means of adding event handlers. It instead requires one of two techniques:
   Use the AddHandler method, together with an     AddressOf   operator, to reference the event handler
   implementation.
   Use the Handles keyword as part of the event handler definition. This technique is not shown here; see
   Visual Basic and WPF Event Handling.
 NOTE
 Adding an event handler in the initially parsed XAML page is much simpler. Within the object element where you want to
 add the event handler, add an attribute that matches the name of the event that you want to handle. Then specify the
 value of that attribute as the name of the event handler method that you defined in the code-behind file of the XAML
 page. For more information, see XAML in WPF or Routed Events Overview.
See also
  Routed Events Overview
  How-to Topics
       How to: Handle a Routed Event
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how bubbling events work and how to write a handler that can process the routed event
data.
Example
In Windows Presentation Foundation (WPF), elements are arranged in an element tree structure. The parent
element can participate in the handling of events that are initially raised by child elements in the element tree.
This is possible because of event routing.
Routed events typically follow one of two routing strategies, bubbling or tunneling. This example focuses on the
bubbling event and uses the ButtonBase.Click event to show how routing works.
The following example creates two Button controls and uses XAML attribute syntax to attach an event handler to
a common parent element, which in this example is StackPanel. Instead of attaching individual event handlers
for each Button child element, the example uses attribute syntax to attach the event handler to the StackPanel
parent element. This event-handling pattern shows how to use event routing as a technique for reducing the
number of elements where a handler is attached. All the bubbling events for each Button route through the
parent element.
Note that on the parent StackPanel element, the Click event name specified as the attribute is partially qualified
by naming the Button class. The Button class is a ButtonBase derived class that has the Click event in its
members listing. This partial qualification technique for attaching an event handler is necessary if the event that
is being handled does not exist in the members listing of the element where the routed event handler is
attached.
   <StackPanel
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     x:Class="SDKSample.RoutedEventHandle"
     Name="dpanel"
     Button.Click="HandleClick"
   >
     <StackPanel.Resources>
         <Style TargetType="{x:Type Button}">
           <Setter Property="Height" Value="20"/>
           <Setter Property="Width" Value="250"/>
           <Setter Property="HorizontalAlignment" Value="Left"/>
         </Style>
     </StackPanel.Resources>
     <Button Name="Button1">Item 1</Button>
     <Button Name="Button2">Item 2</Button>
     <TextBlock Name="results"/>
   </StackPanel>
The following example handles the Click event. The example reports which element handles the event and which
element raises the event. The event handler is executed when the user clicks either button.
 public partial class RoutedEventHandle : StackPanel
 {
     StringBuilder eventstr = new StringBuilder();
     void HandleClick(object sender, RoutedEventArgs args)
     {
         // Get the element that handled the event.
         FrameworkElement fe = (FrameworkElement)sender;
         eventstr.Append("Event handled by element named ");
         eventstr.Append(fe.Name);
         eventstr.Append("\n");
         results.Text = eventstr.ToString();
     }
 }
     results.Text = eventstr.ToString()
 End Sub
See also
 RoutedEvent
 Input Overview
 Routed Events Overview
 How-to Topics
 XAML Syntax In Detail
       How to: Create a Custom Routed Event
       11/21/2022 • 2 minutes to read • Edit Online
For your custom event to support event routing, you need to register a RoutedEvent using the
RegisterRoutedEvent method. This example demonstrates the basics of creating a custom routed event.
Example
As shown in the following example, you first register a RoutedEvent using the RegisterRoutedEvent method. By
convention, the RoutedEvent static field name should end with the suffix Event . In this example, the name of the
event is Tap and the routing strategy of the event is Bubble. After the registration call, you can provide add-
and-remove common language runtime (CLR) event accessors for the event.
Note that even though the event is raised through the OnTap virtual method in this particular example, how you
raise your event or how your event responds to changes depends on your needs.
Note also that this example basically implements an entire subclass of Button; that subclass is built as a separate
assembly and then instantiated as a custom class on a separate Windows Presentation Foundation (WPF)
element does.
       ' For demonstration purposes we raise the event when the MyButtonSimple is clicked
       Protected Overrides Sub OnClick()
           Me.RaiseTapEvent()
       End Sub
End Class
   <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary"
       x:Class="SDKSample.RoutedEventCustomApp"
       >
       <Window.Resources>
         <Style TargetType="{x:Type custom:MyButtonSimple}">
           <Setter Property="Height" Value="20"/>
           <Setter Property="Width" Value="250"/>
           <Setter Property="HorizontalAlignment" Value="Left"/>
           <Setter Property="Background" Value="#808080"/>
         </Style>
       </Window.Resources>
       <StackPanel Background="LightGray">
           <custom:MyButtonSimple Name="mybtnsimple" Tap="TapHandler">Click to see Tap custom event
   work</custom:MyButtonSimple>
       </StackPanel>
   </Window>
Tunneling events are created the same way, but with RoutingStrategy set to Tunnel in the registration call. By
convention, tunneling events in WPF are prefixed with the word "Preview".
To see an example of how bubbling events work, see Handle a Routed Event.
See also
Routed Events Overview
Input Overview
Control Authoring Overview
       How to: Find the Source Element in an Event
       Handler
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to find the source element in an event handler.
Example
The following example shows a Click event handler that is declared in a code-behind file. When a user clicks the
button that the handler is attached to, the handler changes a property value. The handler code uses the Source
property of the routed event data that is reported in the event arguments to change the Width property value
on the Source element.
See also
   RoutedEventArgs
   Routed Events Overview
   How-to Topics
       How to: Add Class Handling for a Routed Event
       11/21/2022 • 2 minutes to read • Edit Online
Routed events can be handled either by class handlers or instance handlers on any given node in the route.
Class handlers are invoked first, and can be used by class implementations to suppress events from instance
handling or introduce other event specific behaviors on events that are owned by base classes. This example
illustrates two closely related techniques for implementing class handlers.
Example
This example uses a custom class based on the Canvas panel. The basic premise of the application is that the
custom class introduces behaviors on its child elements, including intercepting any left mouse button clicks and
marking them handled, before the child element class or any instance handlers on it will be invoked.
The UIElement class exposes a virtual method that enables class handling on the PreviewMouseLeftButtonDown
event, by simply overriding the event. This is the simplest way to implement class handling if such a virtual
method is available somewhere in your class' hierarchy. The following code shows the
OnPreviewMouseLeftButtonDown implementation in the "MyEditContainer" that is derived from Canvas. The
implementation marks the event as handled in the arguments, and then adds some code to give the source
element a basic visible change.
If no virtual is available on base classes or for that particular method, class handling can be added directly using
a utility method of the EventManager class, RegisterClassHandler. This method should only be called within the
static initialization of classes that are adding class handling. This example adds another handler for
PreviewMouseLeftButtonDown , and in this case the registered class is the custom class. In contrast, when using
the virtuals, the registered class is really the UIElement base class. In cases where base classes and subclass each
register class handling, the subclass handlers are invoked first. The behavior in an application would be that first
this handler would show its message box and then the visual change in the virtual method's handler would be
shown.
 static MyEditContainer()
 {
   EventManager.RegisterClassHandler(typeof(MyEditContainer), PreviewMouseRightButtonDownEvent, new
 RoutedEventHandler(LocalOnMouseRightButtonDown));
 }
 internal static void LocalOnMouseRightButtonDown(object sender, RoutedEventArgs e)
 {
   MessageBox.Show("this is invoked before the On* class handler on UIElement");
   //e.Handled = true; //uncommenting this would cause ONLY the subclass' class handler to respond
 }
See also
 EventManager
 Marking Routed Events as Handled, and Class Handling
 Handle a Routed Event
 Routed Events Overview
        Input (WPF)
        11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) includes support for several types of input. This input includes text,
touch, mouse, commands, focus, touch, drag-and-drop, and digital ink. This section describes topics related to
input in WPF.
In This Section
Input Overview
Commanding Overview
Focus Overview
Styling for Focus in Controls, and FocusVisualStyle
Walkthrough: Creating Your First Touch Application
How-to Topics
Digital Ink
Reference
UIElement
FrameworkElement
ContentElement
FrameworkContentElement
Keyboard
Mouse
FocusManager
Related Sections
Controls
Events
        Input Overview
        11/21/2022 • 26 minutes to read • Edit Online
Input API
The primary input API exposure is found on the base element classes: UIElement, ContentElement,
FrameworkElement, and FrameworkContentElement. For more information about the base elements, see Base
Elements Overview. These classes provide functionality for input events related to key presses, mouse buttons,
mouse wheel, mouse movement, focus management, and mouse capture, to name a few. By placing the input
API on the base elements, rather than treating all input events as a service, the input architecture enables the
input events to be sourced by a particular object in the UI, and to support an event routing scheme whereby
more than one element has an opportunity to handle an input event. Many input events have a pair of events
associated with them. For example, the key down event is associated with the KeyDown and PreviewKeyDown
events. The difference in these events is in how they are routed to the target element. Preview events tunnel
down the element tree from the root element to the target element. Bubbling events bubble up from the target
element to the root element. Event routing in WPF is discussed in more detail later in this overview and in the
Routed Events Overview.
Keyboard and Mouse Classes
In addition to the input API on the base element classes, the Keyboard class and Mouse classes provide
additional API for working with keyboard and mouse input.
Examples of input API on the Keyboard class are the Modifiers property, which returns the ModifierKeys
currently pressed, and the IsKeyDown method, which determines whether a specified key is pressed.
The following example uses the GetKeyStates method to determine if a Key is in the down state.
Examples of input API on the Mouse class are MiddleButton, which obtains the state of the middle mouse
button, and DirectlyOver, which gets the element the mouse pointer is currently over.
The following example determines whether the LeftButton on the mouse is in the Pressed state.
   if (Mouse.LeftButton == MouseButtonState.Pressed)
   {
       UpdateSampleResults("Left Button Pressed");
   }
The Mouse and Keyboard classes are covered in more detail throughout this overview.
Stylus Input
WPF has integrated support for the Stylus. The Stylus is a pen input made popular by the Tablet PC. WPF
applications can treat the stylus as a mouse by using the mouse API, but WPF also exposes a stylus device
abstraction that use a model similar to the keyboard and mouse. All stylus-related APIs contain the word
"Stylus".
Because the stylus can act as a mouse, applications that support only mouse input can still obtain some level of
stylus support automatically. When the stylus is used in such a manner, the application is given the opportunity
to handle the appropriate stylus event and then handles the corresponding mouse event. In addition, higher-
level services such as ink input are also available through the stylus device abstraction. For more information
about ink as input, see Getting Started with Ink.
Event Routing
A FrameworkElement can contain other elements as child elements in its content model, forming a tree of
elements. In WPF, the parent element can participate in input directed to its child elements or other descendants
by handing events. This is especially useful for building controls out of smaller controls, a process known as
"control composition" or "compositing." For more information about element trees and how element trees relate
to event routes, see Trees in WPF.
Event routing is the process of forwarding events to multiple elements, so that a particular object or element
along the route can choose to offer a significant response (through handling) to an event that might have been
sourced by a different element. Routed events use one of three routing mechanisms: direct, bubbling, and
tunneling. In direct routing, the source element is the only element notified, and the event is not routed to any
other elements. However, the direct routed event still offers some additional capabilities that are only present for
routed events as opposed to standard CLR events. Bubbling works up the element tree by first notifying the
element that sourced the event, then the parent element, and so on. Tunneling starts at the root of the element
tree and works down, ending with the original source element. For more information about routed events, see
Routed Events Overview.
WPF input events generally come in pairs that consists of a tunneling event and a bubbling event. Tunneling
events are distinguished from bubbling events with the "Preview" prefix. For instance, PreviewMouseMove is the
tunneling version of a mouse move event and MouseMove is the bubbling version of this event. This event
pairing is a convention that is implemented at the element level and is not an inherent capability of the WPF
event system. For details, see the WPF Input Events section in Routed Events Overview.
   <StackPanel>
     <Button Background="AliceBlue"
             KeyDown="OnButtonKeyDown"
             Content="Button1"/>
   </StackPanel>
The second section is written in code and defines the event handler. When the left arrow key is pressed and the
Button has keyboard focus, the handler runs and the Background color of the Button is changed. If the key is
pressed, but it is not the left arrow key, the Background color of the Button is changed back to its starting color.
   private void OnButtonKeyDown(object sender, KeyEventArgs e)
   {
       Button source = e.Source as Button;
       if (source != null)
       {
           if (e.Key == Key.Left)
           {
                source.Background = Brushes.LemonChiffon;
           }
           else
           {
                source.Background = Brushes.AliceBlue;
           }
       }
   }
   <StackPanel>
     <Button Background="AliceBlue"
             MouseEnter="OnMouseExampleMouseEnter"
             MouseLeave="OnMosueExampleMouseLeave">Button
     </Button>
   </StackPanel>
The second section of the example is written in code and defines the event handlers. When the mouse enters the
Button, the Background color of the Button is changed to SlateGray. When the mouse leaves the Button, the
Background color of the Button is changed back to AliceBlue.
       // If source is a Button.
       if (source != null)
       {
           source.Background = Brushes.SlateGray;
       }
   }
       // If source is a Button.
       if (source != null)
       {
           source.Background = Brushes.AliceBlue;
       }
   }
   Private Sub OnMosueExampleMouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs)
       ' Cast the source of the event to a Button.
       Dim source As Button = TryCast(e.Source, Button)
Text Input
The TextInput event enables you to listen for text input in a device-independent manner. The keyboard is the
primary means of text input, but speech, handwriting, and other input devices can generate text input also.
For keyboard input, WPF first sends the appropriate KeyDown/KeyUp events. If those events are not handled
and the key is textual (rather than a control key such as directional arrows or function keys), then a TextInput
event is raised. There is not always a simple one-to-one mapping between KeyDown/KeyUp and TextInput
events because multiple keystrokes can generate a single character of text input and single keystrokes can
generate multi-character strings. This is especially true for languages such as Chinese, Japanese, and Korean
which use Input Method Editors (IMEs) to generate the thousands of possible characters in their corresponding
alphabets.
When WPF sends a KeyUp/KeyDown event, Key is set to Key.System if the keystrokes could become part of a
TextInput event (if ALT+S is pressed, for example). This allows code in a KeyDown event handler to check for
Key.System and, if found, leave processing for the handler of the subsequently raised TextInput event. In these
cases, the various properties of the TextCompositionEventArgs argument can be used to determine the original
keystrokes. Similarly, if an IME is active, Key has the value of Key.ImeProcessed, and ImeProcessedKey gives the
original keystroke or keystrokes.
The following example defines a handler for the Click event and a handler for the KeyDown event.
The first segment of code or markup creates the user interface.
   <StackPanel KeyDown="OnTextInputKeyDown">
     <Button Click="OnTextInputButtonClick"
             Content="Open" />
     <TextBox> . . . </TextBox>
   </StackPanel>
Because input events bubble up the event route, the StackPanel receives the input regardless of which element
has keyboard focus. The TextBox control is notified first and the OnTextInputKeyDown handler is called only if the
TextBox did not handle the input. If the PreviewKeyDown event is used instead of the KeyDown event, the
 OnTextInputKeyDown handler is called first.
In this example, the handling logic is written two times—one time for CTRL+O, and again for button's click event.
This can be simplified by using commands, instead of handling the input events directly. Commands are
discussed in this overview and in Commanding Overview.
Touch and Manipulation
New hardware and API in the Windows 7 operating system provide applications the ability to receive input from
multiple touches simultaneously. WPF enables applications to detect and respond to touch in a manner similar
to responding to other input, such as the mouse or keyboard, by raising events when touch occurs.
WPF exposes two types of events when touch occurs: touch events and manipulation events. Touch events
provide raw data about each finger on a touchscreen and its movement. Manipulation events interpret the input
as certain actions. Both types of events are discussed in this section.
Prerequisites
You need the following components to develop an application that responds to touch.
   Visual Studio 2010.
   Windows 7.
   A device, such as a touchscreen, that supports Windows Touch.
Terminology
The following terms are used when touch is discussed.
   Touch is a type of user input that is recognized by Windows 7. Usually, touch is initiated by putting
   fingers on a touch-sensitive screen. Note that devices such as a touchpad that is common on laptop
   computers do not support touch if the device merely converts the finger's position and movement as
   mouse input.
   Multitouch is touch that occurs from more than one point simultaneously. Windows 7 and WPF
   supports multitouch. Whenever touch is discussed in the documentation for WPF, the concepts apply to
   multitouch.
   A manipulation occurs when touch is interpreted as a physical action that is applied to an object. In WPF,
   manipulation events interpret input as a translation, expansion, or rotation manipulation.
   A   touch device   represents a device that produces touch input, such as a single finger on a touchscreen.
Controls that Respond to Touch
The following controls can be scrolled by dragging a finger across the control if it has content that is scrolled out
of view.
   ComboBox
   ContextMenu
   DataGrid
   ListBox
   ListView
   MenuItem
   TextBox
   ToolBar
   TreeView
The ScrollViewer defines the ScrollViewer.PanningMode attached property that enables you to specify whether
touch panning is enabled horizontally, vertically, both, or neither. The ScrollViewer.PanningDeceleration property
specifies how quickly the scrolling slows down when the user lifts the finger from the touchscreen. The
ScrollViewer.PanningRatio attached property specifies the ratio of scrolling offset to translate manipulation
offset.
Touch Events
The base classes, UIElement, UIElement3D, and ContentElement, define events that you can subscribe to so your
application will respond to touch. Touch events are useful when your application interprets touch as something
other than manipulating an object. For example, an application that enables a user to draw with one or more
fingers would subscribe to touch events.
All three classes define the following events, which behave similarly, regardless of the defining class.
   TouchDown
   TouchMove
   TouchUp
   TouchEnter
   TouchLeave
   PreviewTouchDown
   PreviewTouchMove
   PreviewTouchUp
   GotTouchCapture
   LostTouchCapture
Like keyboard and mouse events, the touch events are routed events. The events that begin with Preview are
tunneling events and the events that begin with Touch are bubbling events. For more information about routed
events, see Routed Events Overview. When you handle these events, you can get the position of the input,
relative to any element, by calling the GetTouchPoint or GetIntermediateTouchPoints method.
To understand the interaction among the touch events, consider the scenario where a user puts one finger on an
element, moves the finger in the element, and then lifts the finger from the element. The following illustration
shows the execution of the bubbling events (the tunneling events are omitted for simplicity).
                     Touch events
The following list describes the sequence of the events in the preceding illustration.
1. The TouchEnter event occurs one time when the user puts a finger on the element.
2. The TouchDown event occurs one time.
3. The TouchMove event occurs multiple times as the user moves the finger within the element.
4. The TouchUp event occurs one time when the user lifts the finger from the element.
5. The TouchLeave event occurs one time.
When more than two fingers are used, the events occur for each finger.
Manipulation Events
For cases where an application enables a user to manipulate an object, the UIElement class defines manipulation
events. Unlike the touch events that simply report the position of touch, the manipulation events report how the
input can be interpreted. There are three types of manipulations, translation, expansion, and rotation. The
following list describes how to invoke the three types of manipulations.
   Put a finger on an object and move the finger across the touchscreen to invoke a translation
   manipulation. This usually moves the object.
   Put two fingers on an object and move the fingers closer together or farther apart from one another to
   invoke an expansion manipulation. This usually resizes the object.
   Put two fingers on an object and rotate the fingers around each other to invoke a rotation manipulation.
   This usually rotates the object.
More than one type of manipulation can occur simultaneously.
When you cause objects to respond to manipulations, you can have the object appear to have inertia. This can
make your objects simulate the physical world. For example, when you push a book across a table, if you push
hard enough the book will continue to move after you release it. WPF enables you to simulate this behavior by
raising manipulation events after the user's fingers releases the object.
For information about how to create an application that enables the user to move, resize, and rotate an object,
see Walkthrough: Creating Your First Touch Application.
The UIElement defines the following manipulation events.
   ManipulationStarting
   ManipulationStarted
   ManipulationDelta
   ManipulationInertiaStarting
   ManipulationCompleted
   ManipulationBoundaryFeedback
By default, a UIElement does not receive these manipulation events. To receive manipulation events on a
UIElement, set UIElement.IsManipulationEnabled to true .
The Execution Path of Manipulation Events
Consider a scenario where a user "throws" an object. The user puts a finger on the object, moves the finger
across the touchscreen for a short distance, and then lifts the finger while it is moving. The result of this is that
the object will move under the user's finger and continue to move after the user lifts the finger.
The following illustration shows the execution path of manipulation events and important information about
each event.
                                   Manipulation events
The following list describes the sequence of the events in the preceding illustration.
1. The ManipulationStarting event occurs when the user places a finger on the object. Among other things,
   this event allows you to set the ManipulationContainer property. In the subsequent events, the position of
   the manipulation will be relative to the ManipulationContainer. In events other than
   ManipulationStarting, this property is read-only, so the ManipulationStarting event is the only time that
   you can set this property.
2. The ManipulationStarted event occurs next. This event reports the origin of the manipulation.
3. The ManipulationDelta event occurs multiple times as a user's fingers move on a touchscreen. The
   DeltaManipulation property of the ManipulationDeltaEventArgs class reports whether the manipulation
   is interpreted as movement, expansion, or translation. This is where you perform most of the work of
   manipulating an object.
4. The ManipulationInertiaStarting event occurs when the user's fingers lose contact with the object. This
   event enables you to specify the deceleration of the manipulations during inertia. This is so your object
   can emulate different physical spaces or attributes if you choose. For example, suppose your application
   has two objects that represent items in the physical world, and one is heavier than the other. You can
   make the heavier object decelerate faster than the lighter object.
5. The ManipulationDelta event occurs multiple times as inertia occurs. Note that this event occurs when the
   user's fingers move across the touchscreen and when WPF simulates inertia. In other words,
   ManipulationDelta occurs before and after the ManipulationInertiaStarting event. The
   ManipulationDeltaEventArgs.IsInertial property reports whether the ManipulationDelta event occurs
   during inertia, so you can check that property and perform different actions, depending on its value.
6. The ManipulationCompleted event occurs when the manipulation and any inertia ends. That is, after all
   the ManipulationDelta events occur, the ManipulationCompleted event occurs to signal that the
   manipulation is complete.
The UIElement also defines the ManipulationBoundaryFeedback event. This event occurs when the
ReportBoundaryFeedback method is called in the ManipulationDelta event. The ManipulationBoundaryFeedback
event enables applications or components to provide visual feedback when an object hits a boundary. For
example, the Window class handles the ManipulationBoundaryFeedback event to cause the window to slightly
move when its edge is encountered.
You can cancel the manipulation by calling the Cancel method on the event arguments in any manipulation
event except ManipulationBoundaryFeedback event. When you call Cancel, the manipulation events are no
longer raised and mouse events occur for touch. The following table describes the relationship between the time
the manipulation is canceled and the mouse events that occur.
                                                            T H E M O USE EVEN T S T H AT O C C UR F O R IN P UT T H AT
  T H E EVEN T T H AT C A N C EL IS C A L L ED IN           A L REA DY O C C URRED
ManipulationInertiaStarting and ManipulationCompleted Mouse down, mouse move, and mouse up events.
Note that if you call Cancel when the manipulation is in inertia, the method returns      false    and the input does
not raise mouse events.
The Relationship Between Touch and Manipulation Events
A UIElement can always receive touch events. When the IsManipulationEnabled property is set to true , a
UIElement can receive both touch and manipulation events. If the TouchDown event is not handled (that is, the
Handled property is false ), the manipulation logic captures the touch to the element and generates the
manipulation events. If the Handled property is set to true in the TouchDown event, the manipulation logic
does not generate manipulation events. The following illustration shows the relationship between touch events
and manipulation events.
                                                                                                          Touch and
manipulation events
The following list describes the relationship between the touch and manipulation events that is shown in the
preceding illustration.
   When the first touch device generates a TouchDown event on a UIElement, the manipulation logic calls
   the CaptureTouch method, which generates the GotTouchCapture event.
   When the GotTouchCapture occurs, the manipulation logic calls the Manipulation.AddManipulator
   method, which generates the ManipulationStarting event.
   When the TouchMove events occur, the manipulation logic generates the ManipulationDelta events that
   occur before the ManipulationInertiaStarting event.
   When the last touch device on the element raises the TouchUp event, the manipulation logic generates
   the ManipulationInertiaStarting event.
Focus
There are two main concepts that pertain to focus in WPF: keyboard focus and logical focus.
Keyboard Focus
Keyboard focus refers to the element that is receiving keyboard input. There can be only one element on the
whole desktop that has keyboard focus. In WPF, the element that has keyboard focus will have
IsKeyboardFocused set to true . The static Keyboard method FocusedElement returns the element that currently
has keyboard focus.
Keyboard focus can be obtained by tabbing to an element or by clicking the mouse on certain elements, such as
a TextBox. Keyboard focus can also be obtained programmatically by using the Focus method on the Keyboard
class. Focus attempts to give the specified element keyboard focus. The element returned by Focus is the
element that currently has keyboard focus.
In order for an element to obtain keyboard focus the Focusable property and the IsVisible properties must be
set to true . Some classes, such as Panel, have Focusable set to false by default; therefore, you may have to set
this property to true if you want that element to be able to obtain focus.
The following example uses Focus to set keyboard focus on a Button. The recommended place to set initial focus
in an application is in the Loaded event handler.
   <StackPanel Name="focusScope1"
               FocusManager.IsFocusScope="True"
               Height="200" Width="200">
     <Button Name="button1" Height="50" Width="50"/>
     <Button Name="button2" Height="50" Width="50"/>
   </StackPanel>
   StackPanel focuseScope2 = new StackPanel();
   FocusManager.SetIsFocusScope(focuseScope2, true);
Classes in WPF which are focus scopes by default are Window, Menu, ToolBar, and ContextMenu.
An element that has keyboard focus will also have logical focus for the focus scope it belongs to; therefore,
setting focus on an element with the Focus method on the Keyboard class or the base element classes will
attempt to give the element keyboard focus and logical focus.
To determine the focused element in a focus scope, use GetFocusedElement. To change the focused element for
a focus scope, use SetFocusedElement.
For more information about logical focus, see Focus Overview.
Mouse Position
The WPF input API provides helpful information with regard to coordinate spaces. For example, coordinate
 (0,0) is the upper-left coordinate, but the upper-left of which element in the tree? The element that is the input
target? The element you attached your event handler to? Or something else? To avoid confusion, the WPF input
API requires that you specify your frame of reference when you work with coordinates obtained through the
mouse. The GetPosition method returns the coordinate of the mouse pointer relative to the specified element.
Mouse Capture
Mouse devices specifically hold a modal characteristic known as mouse capture. Mouse capture is used to
maintain a transitional input state when a drag-and-drop operation is started, so that other operations involving
the nominal on-screen position of the mouse pointer do not necessarily occur. During the drag, the user cannot
click without aborting the drag-and-drop, which makes most mouseover cues inappropriate while the mouse
capture is held by the drag origin. The input system exposes APIs that can determine mouse capture state, as
well as APIs that can force mouse capture to a specific element, or clear mouse capture state. For more
information on drag-and-drop operations, see Drag and Drop Overview.
Commands
Commands enable input handling at a more semantic level than device input. Commands are simple directives,
such as Cut , Copy , Paste , or Open . Commands are useful for centralizing your command logic. The same
command might be accessed from a Menu, on a ToolBar, or through a keyboard shortcut. Commands also
provide a mechanism for disabling controls when the command becomes unavailable.
RoutedCommand is the WPF implementation of ICommand. When a RoutedCommand is executed, a
PreviewExecuted and an Executed event are raised on the command target, which tunnel and bubble through
the element tree like other input. If a command target is not set, the element with keyboard focus will be the
command target. The logic that performs the command is attached to a CommandBinding. When an Executed
event reaches a CommandBinding for that specific command, the ExecutedRoutedEventHandler on the
CommandBinding is called. This handler performs the action of the command.
For more information on commanding, see Commanding Overview.
WPF provides a library of common commands which consists of ApplicationCommands, MediaCommands,
ComponentCommands, NavigationCommands, and EditingCommands, or you can define your own.
The following example shows how to set up a MenuItem so that when it is clicked it will invoke the Paste
command on the TextBox, assuming the TextBox has keyboard focus.
   <StackPanel>
     <Menu>
       <MenuItem Command="ApplicationCommands.Paste" />
     </Menu>
     <TextBox />
   </StackPanel>
What's Next
You now have several techniques to handle input in WPF. You should also have an improved understanding of
the various types of input events and the routed event mechanisms used by WPF.
Additional resources are available that explain WPF framework elements and event routing in more detail. See
the following overviews for more information, Commanding Overview, Focus Overview, Base Elements
Overview, Trees in WPF, and Routed Events Overview.
See also
   Focus Overview
   Commanding Overview
   Routed Events Overview
   Base Elements Overview
   Properties
       Commanding Overview
       11/21/2022 • 13 minutes to read • Edit Online
Commanding is an input mechanism in Windows Presentation Foundation (WPF) which provides input handling
at a more semantic level than device input. Examples of commands are the Copy , Cut , and Paste operations
found on many applications.
This overview defines what commands are in WPF, which classes are part of the commanding model, and how
to use and create commands in your applications.
This topic contains the following sections:
   What Are Commands?
   Simple Command Example in WPF
   Four Main Concepts in WPF Commanding
   Command Library
   Creating Custom Commands
The semantics of a command can be consistent across applications and classes, but the logic of the action is
specific to the particular object acted upon. The key combination CTRL+X invokes the Cut command in text
classes, image classes, and Web browsers, but the actual logic for performing the Cut operation is defined by
the application that performs the cut. A RoutedCommand enables clients to implement the logic. A text object
may cut the selected text into the clipboard, while an image object may cut the selected image. When an
application handles the Executed event, it has access to the target of the command and can take appropriate
action depending on the target's type.
   <StackPanel>
     <Menu>
       <MenuItem Command="ApplicationCommands.Paste" />
     </Menu>
     <TextBox />
   </StackPanel>
Commands
Commands in WPF are created by implementing the ICommand interface. ICommand exposes two methods,
Execute, and CanExecute, and an event, CanExecuteChanged. Execute performs the actions that are associated
with the command. CanExecute determines whether the command can execute on the current command target.
CanExecuteChanged is raised if the command manager that centralizes the commanding operations detects a
change in the command source that might invalidate a command that has been raised but not yet executed by
the command binding. The WPF implementation of ICommand is the RoutedCommand class and is the focus of
this overview.
The main sources of input in WPF are the mouse, the keyboard, ink, and routed commands. The more device-
oriented inputs use a RoutedEvent to notify objects in an application page that an input event has occurred. A
RoutedCommand is no different. The Execute and CanExecute methods of a RoutedCommand do not contain the
application logic for the command, but rather they raise routed events that tunnel and bubble through the
element tree until they encounter an object with a CommandBinding. The CommandBinding contains the
handlers for these events and it is the handlers that perform the command. For more information on event
routing in WPF, see Routed Events Overview.
The Execute method on a RoutedCommand raises the PreviewExecuted and the Executed events on the
command target. The CanExecute method on a RoutedCommand raises the CanExecute and PreviewCanExecute
events on the command target. These events tunnel and bubble through the element tree until they encounter
an object which has a CommandBinding for that particular command.
WPF supplies a set of common routed commands spread across several classes: MediaCommands,
ApplicationCommands, NavigationCommands, ComponentCommands, and EditingCommands. These classes
consist only of the RoutedCommand objects and not the implementation logic of the command. The
implementation logic is the responsibility of the object on which the command is being executed on.
Command Sources
A command source is the object which invokes the command. Examples of command sources are MenuItem,
Button, and KeyGesture.
Command sources in WPF generally implement the ICommandSource interface.
ICommandSource exposes three properties: Command, CommandTarget, and CommandParameter:
   Command is the command to execute when the command source is invoked.
   CommandTarget is the object on which to execute the command. It is worth noting that in WPF the
   CommandTarget property on ICommandSource is only applicable when the ICommand is a
   RoutedCommand. If the CommandTarget is set on an ICommandSource and the corresponding
   command is not a RoutedCommand, the command target is ignored. If the CommandTarget is not set, the
   element with keyboard focus will be the command target.
   CommandParameter is a user-defined data type used to pass information to the handlers implementing
   the command.
The WPF classes that implement ICommandSource are ButtonBase, MenuItem, Hyperlink, and InputBinding.
ButtonBase, MenuItem, and Hyperlink invoke a command when they are clicked, and an InputBinding invokes a
command when the InputGesture associated with it is performed.
The following example shows how to use a MenuItem in a ContextMenu as a command source for the
Properties command.
   <StackPanel>
     <StackPanel.ContextMenu>
       <ContextMenu>
         <MenuItem Command="ApplicationCommands.Properties" />
       </ContextMenu>
     </StackPanel.ContextMenu>
   </StackPanel>
Typically, a command source will listen to the CanExecuteChanged event. This event informs the command
source that the ability of the command to execute on the current command target may have changed. The
command source can query the current status of the RoutedCommand by using the CanExecute method. The
command source can then disable itself if the command cannot execute. An example of this is a MenuItem
graying itself out when a command cannot execute.
An InputGesture can be used as a command source. Two types of input gestures in WPF are the KeyGesture and
MouseGesture. You can think of a KeyGesture as a keyboard shortcut, such as CTRL+C. A KeyGesture is
comprised of a Key and a set of ModifierKeys. A MouseGesture is comprised of a MouseAction and an optional
set of ModifierKeys.
In order for an InputGesture to act as a command source, it must be associated with a command. There are a
few ways to accomplish this. One way is to use an InputBinding.
The following example shows how to create a KeyBinding between a KeyGesture and a RoutedCommand.
   <Window.InputBindings>
     <KeyBinding Key="B"
                 Modifiers="Control"
                 Command="ApplicationCommands.Open" />
   </Window.InputBindings>
   KeyGesture OpenKeyGesture = new KeyGesture(
       Key.B,
       ModifierKeys.Control);
this.InputBindings.Add(OpenCmdKeybinding);
Me.InputBindings.Add(OpenCmdKeybinding)
ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture);
ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture)
CommandBinding
A CommandBinding associates a command with the event handlers that implement the command.
The CommandBinding class contains a Command property, and PreviewExecuted, Executed, PreviewCanExecute,
and CanExecute events.
Command is the command that the CommandBinding is being associated with. The event handlers which are
attached to the PreviewExecuted and Executed events implement the command logic. The event handlers
attached to the PreviewCanExecute and CanExecute events determine if the command can execute on the
current command target.
The following example shows how to create a CommandBinding on the root Window of an application. The
CommandBinding associates the Open command with Executed and CanExecute handlers.
   <Window.CommandBindings>
     <CommandBinding Command="ApplicationCommands.Open"
                     Executed="OpenCmdExecuted"
                     CanExecute="OpenCmdCanExecute"/>
   </Window.CommandBindings>
   // Creating CommandBinding and attaching an Executed and CanExecute handler
   CommandBinding OpenCmdBinding = new CommandBinding(
       ApplicationCommands.Open,
       OpenCmdExecuted,
       OpenCmdCanExecute);
this.CommandBindings.Add(OpenCmdBinding);
Me.CommandBindings.Add(OpenCmdBinding)
A CommandBinding is attached to a specific object, such as the root Window of the application or a control. The
object that the CommandBinding is attached to defines the scope of the binding. For example, a
CommandBinding attached to an ancestor of the command target can be reached by the Executed event, but a
CommandBinding attached to a descendant of the command target cannot be reached. This is a direct
consequence of the way a RoutedEvent tunnels and bubbles from the object that raises the event.
In some situations the CommandBinding is attached to the command target itself, such as with the TextBox class
and the Cut, Copy, and Paste commands. Quite often though, it is more convenient to attach the
CommandBinding to an ancestor of the command target, such as the main Window or the Application object,
especially if the same CommandBinding can be used for multiple command targets. These are design decisions
you will want to consider when you are creating your commanding infrastructure.
Command Target
The command target is the element on which the command is executed. With regards to a RoutedCommand, the
command target is the element at which routing of the Executed and CanExecute starts. As noted previously, in
WPF the CommandTarget property on ICommandSource is only applicable when the ICommand is a
RoutedCommand. If the CommandTarget is set on an ICommandSource and the corresponding command is not
a RoutedCommand, the command target is ignored.
The command source can explicitly set the command target. If the command target is not defined, the element
with keyboard focus will be used as the command target. One of the benefits of using the element with
keyboard focus as the command target is that it allows the application developer to use the same command
source to invoke a command on multiple targets without having to keep track of the command target. For
example, if a MenuItem invokes the Paste command in an application that has a TextBox control and a
PasswordBox control, the target can be either the TextBox or PasswordBox depending on which control has
keyboard focus.
The following example shows how to explicitly set the command target in markup and in code behind.
   <StackPanel>
     <Menu>
       <MenuItem Command="ApplicationCommands.Paste"
                 CommandTarget="{Binding ElementName=mainTextBox}" />
     </Menu>
     <TextBox Name="mainTextBox"/>
   </StackPanel>
The CommandManager
The CommandManager serves a number of command related functions. It provides a set of static methods for
adding and removing PreviewExecuted, Executed, PreviewCanExecute, and CanExecute event handlers to and
from a specific element. It provides a means to register CommandBinding and InputBinding objects onto a
specific class. The CommandManager also provides a means, through the RequerySuggested event, to notify a
command when it should raise the CanExecuteChanged event.
The InvalidateRequerySuggested method forces the CommandManager to raise the RequerySuggested event.
This is useful for conditions that should disable/enable a command but are not conditions that the
CommandManager is aware of.
Command Library
WPF provides a set of predefined commands. The command library consists of the following classes:
ApplicationCommands, NavigationCommands, MediaCommands, EditingCommands, and the
ComponentCommands. These classes provide commands such as Cut, BrowseBack and BrowseForward, Play,
Stop, and Pause.
Many of these commands include a set of default input bindings. For example, if you specify that your
application handles the copy command, you automatically get the keyboard binding "CTRL+C" You also get
bindings for other input devices, such as Tablet PC pen gestures and speech information.
When you reference commands in the various command libraries using WPF WPF XAML processor references
at load time).
See also
   RoutedCommand
   CommandBinding
   InputBinding
   CommandManager
   Input Overview
   Routed Events Overview
   Implement ICommandSource
   How to: Add a Command to a MenuItem
   Create a Custom RoutedCommand Sample
       Focus Overview
       11/21/2022 • 8 minutes to read • Edit Online
In WPF there are two main concepts that pertain to focus: keyboard focus and logical focus. Keyboard focus
refers to the element that receives keyboard input and logical focus refers to the element in a focus scope that
has focus. These concepts are discussed in detail in this overview. Understanding the difference in these
concepts is important for creating complex applications that have multiple regions where focus can be obtained.
The major classes that participate in focus management are the Keyboard class, the FocusManager class, and the
base element classes, such as UIElement and ContentElement. For more information about the base elements,
see the Base Elements Overview.
The Keyboard class is concerned primarily with keyboard focus and the FocusManager is concerned primarily
with logical focus, but this is not an absolute distinction. An element that has keyboard focus will also have
logical focus, but an element that has logical focus does not necessarily have keyboard focus. This is apparent
when you use the Keyboard class to set the element that has keyboard focus, for it also sets logical focus on the
element.
Keyboard Focus
Keyboard focus refers to the element that is currently receiving keyboard input. There can be only one element
on the whole desktop that has keyboard focus. In WPF, the element that has keyboard focus will have
IsKeyboardFocused set to true . The static property FocusedElement on the Keyboard class gets the element
that currently has keyboard focus.
In order for an element to obtain keyboard focus, the Focusable and the IsVisible properties on the base
elements must be set to true . Some classes, such as the Panel base class, have Focusable set to false by
default; therefore, you must set Focusable to true if you want such an element to be able to obtain keyboard
focus.
Keyboard focus can be obtained through user interaction with the UI, such as tabbing to an element or clicking
the mouse on certain elements. Keyboard focus can also be obtained programmatically by using the Focus
method on the Keyboard class. The Focus method attempts to give the specified element keyboard focus. The
returned element is the element that has keyboard focus, which might be a different element than requested if
either the old or new focus object block the request.
The following example uses the Focus method to set keyboard focus on a Button.
The IsKeyboardFocused property on the base element classes gets a value indicating whether the element has
keyboard focus. The IsKeyboardFocusWithin property on the base element classes gets a value indicating
whether the element or any one of its visual child elements has keyboard focus.
When setting initial focus at application startup, the element to receive focus must be in the visual tree of the
initial window loaded by the application, and the element must have Focusable and IsVisible set to true . The
recommended place to set initial focus is in the Loaded event handler. A Dispatcher callback can also be used by
calling Invoke or BeginInvoke.
Logical Focus
Logical focus refers to the FocusManager.FocusedElement in a focus scope. A focus scope is an element that
keeps track of the FocusedElement within its scope. When keyboard focus leaves a focus scope, the focused
element will lose keyboard focus but will retain logical focus. When keyboard focus returns to the focus scope,
the focused element will obtain keyboard focus. This allows for keyboard focus to be changed between multiple
focus scopes but ensures that the focused element in the focus scope regains keyboard focus when focus
returns to the focus scope.
There can be multiple elements that have logical focus in an application, but there may only be one element that
has logical focus in a particular focus scope.
An element that has keyboard focus has logical focus for the focus scope it belongs to.
An element can be turned into a focus scope in Extensible Application Markup Language (XAML) by setting the
FocusManager attached property IsFocusScope to true . In code, an element can be turned into a focus scope
by calling SetIsFocusScope.
The following example makes a StackPanel into a focus scope by setting the IsFocusScope attached property.
   <StackPanel Name="focusScope1"
               FocusManager.IsFocusScope="True"
               Height="200" Width="200">
     <Button Name="button1" Height="50" Width="50"/>
     <Button Name="button2" Height="50" Width="50"/>
   </StackPanel>
Keyboard Navigation
The KeyboardNavigation class is responsible for implementing default keyboard focus navigation when one of
the navigation keys is pressed. The navigation keys are: TAB, SHIFT+TAB, CTRL+TAB, CTRL+SHIFT+TAB,
UPARROW, DOWNARROW, LEFTARROW, and RIGHTARROW keys.
The navigation behavior of a navigation container can be changed by setting the attached KeyboardNavigation
properties TabNavigation, ControlTabNavigation, and DirectionalNavigation. These properties are of type
KeyboardNavigationMode and the possible values are Continue, Local, Contained, Cycle, Once, and None. The
default value is Continue, which means the element is not a navigation container.
The following example creates a Menu with a number of MenuItem objects. The TabNavigation attached
property is set to Cycle on the Menu. When focus is changed using the tab key within the Menu, focus will move
from each element and when the last element is reached focus will return to the first element.
   <Menu KeyboardNavigation.TabNavigation="Cycle">
     <MenuItem Header="Menu Item 1" />
     <MenuItem Header="Menu Item 2" />
     <MenuItem Header="Menu Item 3" />
     <MenuItem Header="Menu Item 4" />
   </Menu>
   navigationMenu.Items.Add(item1);
   navigationMenu.Items.Add(item2);
   navigationMenu.Items.Add(item3);
   navigationMenu.Items.Add(item4);
   KeyboardNavigation.SetTabNavigation(navigationMenu,
       KeyboardNavigationMode.Cycle);
   navigationMenu.Items.Add(item1)
   navigationMenu.Items.Add(item2)
   navigationMenu.Items.Add(item3)
   navigationMenu.Items.Add(item4)
   KeyboardNavigation.SetTabNavigation(navigationMenu, KeyboardNavigationMode.Cycle)
Navigating Focus Programmatically
Additional API to work with focus are MoveFocus and PredictFocus.
MoveFocus changes focus to the next element in the application. A TraversalRequest is used to specify the
direction. The FocusNavigationDirection passed to MoveFocus specifies the different directions focus can be
moved, such as First, Last, Up and Down.
The following example uses MoveFocus to change the focused element.
PredictFocus returns the object which would receive focus if focus were to be changed. Currently, only Up,
Down, Left, and Right are supported by PredictFocus.
Focus Events
The events related to keyboard focus are PreviewGotKeyboardFocus, GotKeyboardFocus and
PreviewLostKeyboardFocus, LostKeyboardFocus. The events are defined as attached events on the Keyboard
class, but are more readily accessible as equivalent routed events on the base element classes. For more
information about events, see the Routed Events Overview.
GotKeyboardFocus is raised when the element obtains keyboard focus. LostKeyboardFocus is raised when the
element loses keyboard focus. If the PreviewGotKeyboardFocus event or the PreviewLostKeyboardFocusEvent
event is handled and Handled is set to true , then focus will not change.
The following example attaches GotKeyboardFocus and LostKeyboardFocus event handlers to a TextBox.
   <Border BorderBrush="Black" BorderThickness="1"
           Width="200" Height="100" Margin="5">
     <StackPanel>
       <Label HorizontalAlignment="Center" Content="Type Text In This TextBox" />
       <TextBox Width="175"
                Height="50"
                Margin="5"
                TextWrapping="Wrap"
                HorizontalAlignment="Center"
                VerticalScrollBarVisibility="Auto"
                GotKeyboardFocus="TextBoxGotKeyboardFocus"
                LostKeyboardFocus="TextBoxLostKeyboardFocus"
                KeyDown="SourceTextKeyDown"/>
     </StackPanel>
   </Border>
When the TextBox obtains keyboard focus, the Background property of the TextBox is changed to LightBlue.
       if (source != null)
       {
           // Change the TextBox color when it obtains focus.
           source.Background = Brushes.LightBlue;
When the TextBox loses keyboard focus, the Background property of the TextBox is changed back to white.
       if (source != null)
       {
           // Change the TextBox color when it loses focus.
           source.Background = Brushes.White;
           // Set the hit counter back to zero and updates the display.
           this.ResetCounter();
       }
   }
   Private Sub TextBoxLostKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
       Dim source As TextBox = TryCast(e.Source, TextBox)
           ' Set the hit counter back to zero and updates the display.
           Me.ResetCounter()
       End If
   End Sub
The events related to logical focus are GotFocus and LostFocus. These events are defined on the FocusManager
as attached events, but the FocusManager does not expose CLR event wrappers. UIElement and ContentElement
expose these events more conveniently.
See also
   FocusManager
   UIElement
   ContentElement
   Input Overview
   Base Elements Overview
       Styling for Focus in Controls, and FocusVisualStyle
       11/21/2022 • 5 minutes to read • Edit Online
Windows Presentation Foundation (WPF) provides two parallel mechanisms for changing the visual appearance
of a control when it receives keyboard focus. The first mechanism is to use property setters for properties such
as IsKeyboardFocused within the style or template that is applied to the control. The second mechanism is to
provide a separate style as the value of the FocusVisualStyle property; the "focus visual style" creates a separate
visual tree for an adorner that draws on top of the control, rather than changing the visual tree of the control or
other UI element by replacing it. This topic discusses the scenarios where each of these mechanisms is
appropriate.
See also
   FocusVisualStyle
   Styling and Templating
   Focus Overview
   Input Overview
        Walkthrough: Creating Your First Touch Application
        11/21/2022 • 5 minutes to read • Edit Online
WPF enables applications to respond to touch. For example, you can interact with an application by using one or
more fingers on a touch-sensitive device, such as a touchscreen This walkthrough creates an application that
enables the user to move, resize, or rotate a single object by using touch.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio.
   A device that accepts touch input, such as a touchscreen, that supports Windows Touch.
Additionally, you should have a basic understanding of how to create an application in WPF, especially how to
subscribe to and handle an event. For more information, see Walkthrough: My first WPF desktop application.
</Window.Resources>
        <Canvas>
          <Rectangle Fill="Red" Name="manRect"
                       Width="200" Height="200"
                       RenderTransform="{StaticResource InitialMatrixTransform}"
                       IsManipulationEnabled="true" />
        </Canvas>
      </Window>
3. If you are using Visual Basic, in the first line of MainWindow.xaml, replace
    x:Class="BasicManipulation.MainWindow" with x:Class="MainWindow" .
      Rect containingRect =
          new Rect(((FrameworkElement)e.ManipulationContainer).RenderSize);
      Rect shapeBounds =
          rectToMove.RenderTransform.TransformBounds(
              new Rect(rectToMove.RenderSize));
      e.Handled = true;
  }
      Private Sub Window_ManipulationDelta(ByVal sender As Object, ByVal e As ManipulationDeltaEventArgs)
          e.Handled = True
      End Sub
          e.Handled = true;
      }
          e.Handled = True
      End Sub
The topics in this section describe how to use the input and commanding infrastructure in Windows
Presentation Foundation (WPF).
In This Section
Enable a Command
Change the Cursor Type
Change the Color of an Element Using Focus Events
Apply a FocusVisualStyle to a Control
Detect When the Enter Key is Pressed
Create a Rollover Effect Using Events
Make an Object Follow the Mouse Pointer
Create a RoutedCommand
Implement ICommandSource
Hook Up a Command to a Control with No Command Support
Hook Up a Command to a Control with Command Support
Reference
UIElement
FrameworkElement
ContentElement
FrameworkContentElement
Keyboard
Mouse
FocusManager
Related Sections
       How to: Enable a Command
       11/21/2022 • 2 minutes to read • Edit Online
The following example demonstrates how to use commanding in Windows Presentation Foundation (WPF). The
example shows how to associate a RoutedCommand to a Button, create a CommandBinding, and create the
event handlers which implement the RoutedCommand. For more information on commanding, see the
Commanding Overview.
Example
The first section of code creates the user interface (UI), which consists of a Button and a StackPanel, and creates a
CommandBinding that associates the command handlers with the RoutedCommand.
The Command property of the Button is associated with the Close command.
The CommandBinding is added to the CommandBindingCollection of the root Window. The Executed and
CanExecute event handlers are attached to this binding and associated with the Close command.
Without the CommandBinding there is no command logic, only a mechanism to invoke the command. When the
Button is clicked, the PreviewExecuted RoutedEvent is raised on the command target followed by the Executed
RoutedEvent. These events traverse the element tree looking for a CommandBinding for that particular
command. It is worth noting that because RoutedEvent tunnel and bubble through the element tree, care must
be taken in where the CommandBinding is put. If the CommandBinding is on a sibling of the command target or
another node that is not on the route of the RoutedEvent, the CommandBinding will not be accessed.
   <Window x:Class="WCSamples.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="CloseCommand"
       Name="RootWindow"
       >
     <Window.CommandBindings>
       <CommandBinding Command="ApplicationCommands.Close"
                       Executed="CloseCommandHandler"
                       CanExecute="CanExecuteHandler"
                       />
     </Window.CommandBindings>
     <StackPanel Name="MainStackPanel">
       <Button Command="ApplicationCommands.Close"
               Content="Close File" />
     </StackPanel>
   </Window>
   // Create ui elements.
   StackPanel CloseCmdStackPanel = new StackPanel();
   Button CloseCmdButton = new Button();
   CloseCmdStackPanel.Children.Add(CloseCmdButton);
The next section of code implements the Executed and CanExecute event handlers.
The Executed handler calls a method to close the open file. The CanExecute handler calls a method to determine
whether a file is open. If a file is open, CanExecute is set to true ; otherwise, it is set to false .
See also
 Commanding Overview
       How to: Change the Cursor Type
       11/21/2022 • 3 minutes to read • Edit Online
This example shows how to change the Cursor of the mouse pointer for a specific element and for the
application.
This example consists of a Extensible Application Markup Language (XAML) file and a code behind file.
Example
The user interface is created, which consists of a ComboBox to select the desired Cursor, a pair of RadioButton
objects to determine if the cursor change applies to only a single element or applies to the entire application,
and a Border which is the element that the new cursor is applied to.
   <StackPanel>
     <Border Width="300">
       <StackPanel Orientation="Horizontal"
                   HorizontalAlignment="Center">
         <StackPanel Margin="10">
           <Label HorizontalAlignment="Left">Cursor Type</Label>
           <ComboBox Width="100"
                     SelectionChanged="CursorTypeChanged"
                     HorizontalAlignment="Left"
                     Name="CursorSelector">
             <ComboBoxItem Content="AppStarting" />
             <ComboBoxItem Content="ArrowCD" />
             <ComboBoxItem Content="Arrow" />
             <ComboBoxItem Content="Cross" />
             <ComboBoxItem Content="HandCursor" />
             <ComboBoxItem Content="Help" />
             <ComboBoxItem Content="IBeam" />
             <ComboBoxItem Content="No" />
             <ComboBoxItem Content="None" />
             <ComboBoxItem Content="Pen" />
             <ComboBoxItem Content="ScrollSE" />
             <ComboBoxItem Content="ScrollWE" />
             <ComboBoxItem Content="SizeAll" />
             <ComboBoxItem Content="SizeNESW" />
             <ComboBoxItem Content="SizeNS" />
             <ComboBoxItem Content="SizeNWSE" />
             <ComboBoxItem Content="SizeWE" />
             <ComboBoxItem Content="UpArrow" />
             <ComboBoxItem Content="WaitCursor" />
             <ComboBoxItem Content="Custom" />
           </ComboBox>
         </StackPanel>
         <!-- The user can select different cursor types using this ComboBox -->
         <StackPanel Margin="10">
           <Label HorizontalAlignment="Left">Scope of Cursor</Label>
           <StackPanel>
             <RadioButton Name="rbScopeElement" IsChecked="True"
                          Checked="CursorScopeSelected">Display Area Only</RadioButton>
             <RadioButton Name="rbScopeApplication"
                          Checked="CursorScopeSelected">Entire Appliation</RadioButton>
           </StackPanel>
         </StackPanel>
       </StackPanel>
     </Border>
     <!-- When the mouse pointer is over this Border -->
     <!-- the selected cursor type is shown -->
     <Border Name="DisplayArea" Height="250" Width="400"
             Margin="20" Background="AliceBlue">
       <Label HorizontalAlignment="Center">
         Move Mouse Pointer Over This Area
       </Label>
     </Border>
   </StackPanel>
The following code behind creates a SelectionChanged event handler which is called when the cursor type is
changed in the ComboBox. A switch statement filters on the cursor name and sets the Cursor property on the
Border which is named DisplayArea.
If the cursor change is set to "Entire Application", the OverrideCursor property is set to the Cursor property of
the Border control. This forces the cursor to change for the whole application.
End Sub
See also
 Input Overview
       How to: Change the Color of an Element Using
       Focus Events
      11/21/2022 • 2 minutes to read • Edit Online
This example shows how to change the color of an element when it gains and loses focus by using the GotFocus
and LostFocus events.
This example consists of a Extensible Application Markup Language (XAML) file and a code-behind file.
Example
The following XAML creates the user interface, which consists of two Button objects, and attaches event handlers
for the GotFocus and LostFocus events to the Button objects.
   <StackPanel>
     <StackPanel.Resources>
       <Style TargetType="{x:Type Button}">
         <Setter Property="Height" Value="20"/>
         <Setter Property="Width" Value="250"/>
         <Setter Property="HorizontalAlignment" Value="Left"/>
       </Style>
     </StackPanel.Resources>
     <Button
         GotFocus="OnGotFocusHandler"
         LostFocus="OnLostFocusHandler">Click Or Tab To Give Keyboard Focus</Button>
     <Button
         GotFocus="OnGotFocusHandler"
         LostFocus="OnLostFocusHandler">Click Or Tab To Give Keyborad Focus</Button>
   </StackPanel>
The following code behind creates the GotFocus and LostFocus event handlers. When the Button gains keyboard
focus, the Background of the Button is changed to red. When the Button loses keyboard focus, the Background
of the Button is changed back to white.
 public partial class Window1 : Window
 {
     public Window1()
     {
         InitializeComponent();
     }
     'raised when Button gains focus. Changes the color of the Button to red.
     Private Sub OnGotFocusHandler(ByVal sender As Object, ByVal e As RoutedEventArgs)
         Dim tb As Button = CType(e.Source, Button)
         tb.Background = Brushes.Red
     End Sub
     'raised when Button loses focus. Changes the color back to white.
     Private Sub OnLostFocusHandler(ByVal sender As Object, ByVal e As RoutedEventArgs)
         Dim tb As Button = CType(e.Source, Button)
         tb.Background = Brushes.White
     End Sub
 End Class
See also
 Input Overview
       How to: Apply a FocusVisualStyle to a Control
       11/21/2022 • 2 minutes to read • Edit Online
This example shows you how to create a focus visual style in resources and apply the style to a control, using the
FocusVisualStyle property.
Example
The following example defines a style that creates additional control compositing that only applies when that
control is keyboard focused in the user interface (UI). This is accomplished by defining a style with a
ControlTemplate, then referencing that style as a resource when setting the FocusVisualStyle property.
An external rectangle resembling a border is placed outside of the rectangular area. Unless otherwise modified,
the sizing of the style uses the ActualHeight and ActualWidth of the rectangular control where the focus visual
style is applied. This example sets negative values for the Margin to make the border appear slightly outside the
focused control.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   >
     <Page.Resources>
       <Style x:Key="MyFocusVisual">
         <Setter Property="Control.Template">
           <Setter.Value>
             <ControlTemplate>
                <Rectangle Margin="-2" StrokeThickness="1" Stroke="Red" StrokeDashArray="1 2"/>
             </ControlTemplate>
           </Setter.Value>
         </Setter>
       </Style>
     </Page.Resources>
     <StackPanel Background="Ivory" Orientation="Horizontal">
       <Canvas Width="10"/>
       <Button Width="100" Height="30" FocusVisualStyle="{DynamicResource MyFocusVisual}">
         Focus Here</Button>
       <Canvas Width="100"/>
       <Button Width="100" Height="30" FocusVisualStyle="{DynamicResource MyFocusVisual}">
         Focus Here</Button>
     </StackPanel>
   </Page>
A FocusVisualStyle is additive to any control template style that comes either from an explicit style or a theme
style; the primary style for a control can still be created by using a ControlTemplate and setting that style to the
Style property.
Focus visual styles should be used consistently across a theme or a UI, rather than using a different one for each
focusable element. For details, see Styling for Focus in Controls, and FocusVisualStyle.
See also
   FocusVisualStyle
   Styling and Templating
   Styling for Focus in Controls, and FocusVisualStyle
       How to: Detect When the Enter Key Pressed
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to detect when the Enter key is pressed on the keyboard.
This example consists of a Extensible Application Markup Language (XAML) file and a code-behind file.
Example
When the user presses the Enter key in the TextBox, the input in the text box appears in another area of the user
interface (UI).
The following XAML creates the user interface, which consists of a StackPanel, a TextBlock, and a TextBox.
   <StackPanel>
     <TextBlock Width="300" Height="20">
       Type some text into the TextBox and press the Enter key.
     </TextBlock>
     <TextBox Width="300" Height="30" Name="textBox1"
              KeyDown="OnKeyDownHandler"/>
     <TextBlock Width="300" Height="100" Name="textBlock1"/>
   </StackPanel>
The following code behind creates the KeyDown event handler. If the key that is pressed is the Enter key, a
message is displayed in the TextBlock.
See also
   Input Overview
   Routed Events Overview
       How to: Create a Rollover Effect Using Events
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to change the color of an element as the mouse pointer enters and leaves the area
occupied by the element.
This example consists of a Extensible Application Markup Language (XAML) file and a code-behind file.
  NOTE
  This example demonstrates how to use events, but the recommended way to achieve this same effect is to use a Trigger in
  a style. For more information, see Styling and Templating.
Example
The following XAML creates the user interface, which consists of Border around a TextBlock, and attaches the
MouseEnter and MouseLeave event handlers to the Border.
   <StackPanel>
     <Border MouseEnter="OnMouseEnterHandler"
             MouseLeave="OnMouseLeaveHandler"
             Name="border1" Margin="10"
             BorderThickness="1"
             BorderBrush="Black"
             VerticalAlignment="Center"
             Width="300" Height="100">
       <Label Margin="10" FontSize="14"
               HorizontalAlignment="Center">Move Cursor Over Me</Label>
     </Border>
   </StackPanel>
The following code behind creates the MouseEnter and MouseLeave event handlers. When the mouse pointer
enters the Border, the background of the Border is changed to red. When the mouse pointer leaves the Border,
the background of the Border is changed back to white.
       // raised when mouse cursor enters the area occupied by the element
       void OnMouseEnterHandler(object sender, MouseEventArgs e)
       {
           border1.Background = Brushes.Red;
       }
       // raised when mouse cursor leaves the area occupied by the element
       void OnMouseLeaveHandler(object sender, MouseEventArgs e)
       {
           border1.Background = Brushes.White;
       }
   }
Partial Public Class Window1
    Inherits Window
This example shows how to change the dimensions of an object when the mouse pointer moves on the screen.
The example includes an user interface (UI) and a code-behind file that creates the event handler.
Example
The following XAML creates the UI, which consists of an Ellipse inside of a StackPanel, and attaches the event
handler for the MouseMove event.
   <Window x:Class="WCSamples.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="mouseMoveWithPointer"
       Height="400"
       Width="500"
       >
     <Canvas MouseMove="MouseMoveHandler"
             Background="LemonChiffon">
       <Ellipse Name="ellipse" Fill="LightBlue"
                Width="100" Height="100"/>
     </Canvas>
   </Window>
The following code behind creates the MouseMove event handler. When the mouse pointer moves, the height
and the width of the Ellipse are increased and decreased.
     'Set the Height and Width of the Ellipse to the mouse coordinates.
     ellipse1.Height = pY
     ellipse1.Width = pX
 End Sub
See also
 Input Overview
       How to: Create a RoutedCommand
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to create a custom RoutedCommand and how to implement the custom command by
creating a ExecutedRoutedEventHandler and a CanExecuteRoutedEventHandler and attaching them to a
CommandBinding. For more information on commanding, see the Commanding Overview.
Example
The first step in creating a RoutedCommand is defining the command and instantiating it.
In order to use the command in an application, event handlers which define what the command does must be
created
       if(target != null)
       {
            e.CanExecute = true;
       }
       else
       {
            e.CanExecute = false;
       }
   }
   ' CanExecuteRoutedEventHandler that only returns true if
   ' the source is a control.
   Private Sub CanExecuteCustomCommand(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
       Dim target As Control = TryCast(e.Source, Control)
Next, a CommandBinding is created which associates the command with the event handlers. The
CommandBinding is created on a specific object. This object defines the scope of the CommandBinding in the
element tree
   <Window x:Class="SDKSamples.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:custom="clr-namespace:SDKSamples"
       Height="600" Width="800"
       >
     <Window.CommandBindings>
       <CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}"
                       Executed="ExecutedCustomCommand"
                       CanExecute="CanExecuteCustomCommand" />
     </Window.CommandBindings>
The final step is invoking the command. One way to invoke a command is to associate it with a
ICommandSource, such as a Button.
   <StackPanel>
     <Button Command="{x:Static custom:Window1.CustomRoutedCommand}"
             Content="CustomRoutedCommand"/>
   </StackPanel>
   // create the ui
   StackPanel CustomCommandStackPanel = new StackPanel();
   Button CustomCommandButton = new Button();
   CustomCommandStackPanel.Children.Add(CustomCommandButton);
   CustomCommandButton.Command = CustomRoutedCommand;
   ' create the ui
   Dim CustomCommandStackPanel As New StackPanel()
   Dim CustomCommandButton As New Button()
   CustomCommandStackPanel.Children.Add(CustomCommandButton)
CustomCommandButton.Command = CustomRoutedCommand
When the Button is clicked, the Execute method on the custom RoutedCommand is called. The RoutedCommand
raises the PreviewExecuted and Executed routed events. These events traverse the element tree looking for a
CommandBinding for this particular command. If a CommandBinding is found, the
ExecutedRoutedEventHandler associated with CommandBinding is called.
See also
   RoutedCommand
   Commanding Overview
       How to: Implement ICommandSource
       11/21/2022 • 5 minutes to read • Edit Online
This example shows how to create a command source by implementing ICommandSource. A command source
is an object that knows how to invoke a command. The ICommandSource interface exposes three members:
   Command: the command that will be invoked.
   CommandParameter: a user-defined data type which is passed from the command source to the method that
   handles the command.
   CommandTarget: the object that the command is being executed on.
In this example, a class is created that inherits from the Slider control and implements the ICommandSource
interface.
Example
WPF provides a number of classes which implement ICommandSource, such as Button, MenuItem, and
Hyperlink. A command source defines how it invokes a command. These classes invoke a command when
they're clicked and they only become a command source when their Command property is set.
In this example, you'll invoke the command when the slider is moved, or more accurately, when the Value
property is changed.
The following is the class definition:
End Sub
The next step is to implement the ICommandSource members. In this example, the properties are implemented
as DependencyProperty objects. This enables the properties to use data binding. For more information about
the DependencyProperty class, see the Dependency Properties Overview. For more information about data
binding, see the Data Binding Overview.
Only the Command property is shown here.
   // Make Command a dependency property so it can use databinding.
   public static readonly DependencyProperty CommandProperty =
       DependencyProperty.Register(
           "Command",
           typeof(ICommand),
           typeof(CommandSlider),
           new PropertyMetadata((ICommand)null,
           new PropertyChangedCallback(CommandChanged)));
The next step is to add and remove the command which is associated with the command source. The Command
property cannot simply be overwritten when a new command is added, because the event handlers associated
with the previous command, if there was one, must be removed first.
      if (this.Command != null)
      {
          RoutedCommand command = this.Command as RoutedCommand;
          // If a RoutedCommand.
          if (command != null)
          {
               if (command.CanExecute(CommandParameter, CommandTarget))
               {
                    this.IsEnabled = true;
               }
               else
               {
                    this.IsEnabled = false;
               }
          }
          // If a not RoutedCommand.
          else
          {
               if (Command.CanExecute(CommandParameter))
               {
                    this.IsEnabled = true;
               }
               else
               {
                    this.IsEnabled = false;
               }
          }
      }
  }
          ' If a RoutedCommand.
          If command IsNot Nothing Then
               If command.CanExecute(CommandParameter, CommandTarget) Then
                    Me.IsEnabled = True
               Else
                    Me.IsEnabled = False
               End If
               ' If a not RoutedCommand.
          Else
               If Me.Command.CanExecute(CommandParameter) Then
                    Me.IsEnabled = True
               Else
                    Me.IsEnabled = False
               End If
          End If
      End If
  End Sub
The last step is the Execute method. If the command is a RoutedCommand, the RoutedCommand Execute
method is called; otherwise, the ICommand Execute method is called.
 // If Command is defined, moving the slider will invoke the command;
 // Otherwise, the slider will behave normally.
 protected override void OnValueChanged(double oldValue, double newValue)
 {
     base.OnValueChanged(oldValue, newValue);
     if (this.Command != null)
     {
         RoutedCommand command = Command as RoutedCommand;
         if (command != null)
         {
              command.Execute(CommandParameter, CommandTarget);
         }
         else
         {
              ((ICommand)Command).Execute(CommandParameter);
         }
     }
 }
 ' If Command is defined, moving the slider will invoke the command;
 ' Otherwise, the slider will behave normally.
 Protected Overrides Sub OnValueChanged(ByVal oldValue As Double, ByVal newValue As Double)
     MyBase.OnValueChanged(oldValue, newValue)
See also
 ICommandSource
 ICommand
 RoutedCommand
 Commanding Overview
      How to: Hook Up a Command to a Control with No
      Command Support
      11/21/2022 • 2 minutes to read • Edit Online
The following example shows how to hook up a RoutedCommand to a Control which does not have built in
support for the command. For a complete sample which hooks up commands to multiple sources, see the
Create a Custom RoutedCommand Sample sample.
Example
Windows Presentation Foundation (WPF) provides a library of common commands which application
programmers encounter regularly. The classes which comprise the command library are:
ApplicationCommands, ComponentCommands, NavigationCommands, MediaCommands, and
EditingCommands.
The static RoutedCommand objects which make up these classes do not supply command logic. The logic for the
command is associated with the command with a CommandBinding. Many controls in WPF have built in
support for some of the commands in the command library. TextBox, for example, supports many of the
application edit commands such as Paste, Copy, Cut, Redo, and Undo. The application developer does not have
to do anything special to get these commands to work with these controls. If the TextBox is the command target
when the command is executed, it will handle the command using the CommandBinding that is built into the
control.
The following shows how to use a Button as the command source for the Open command. A CommandBinding
is created that associates the specified CanExecuteRoutedEventHandler and the CanExecuteRoutedEventHandler
with the RoutedCommand.
First, the command source is created. A Button is used as the command source.
Finally, a CommandBinding is created on the root Window of the application that associates the routed events
handlers to the Open command.
   <Window.CommandBindings>
     <CommandBinding Command="ApplicationCommands.Open"
                     Executed="OpenCmdExecuted"
                     CanExecute="OpenCmdCanExecute"/>
   </Window.CommandBindings>
this.CommandBindings.Add(OpenCmdBinding);
Me.CommandBindings.Add(OpenCmdBinding)
See also
   Commanding Overview
   Hook Up a Command to a Control with Command Support
       How to: Hook Up a Command to a Control with
       Command Support
       11/21/2022 • 3 minutes to read • Edit Online
The following example shows how to hook up a RoutedCommand to a Control which has built in support for the
command. For a complete sample which hooks up commands to multiple sources, see the Create a Custom
RoutedCommand Sample sample.
Example
Windows Presentation Foundation (WPF) provides a library of common commands which application
programmers encounter regularly. The classes which comprise the command library are:
ApplicationCommands, ComponentCommands, NavigationCommands, MediaCommands, and
EditingCommands.
The static RoutedCommand objects which make up these classes do not supply command logic. The logic for the
command is associated with the command with a CommandBinding. Some controls have built in
CommandBindings for some commands. This mechanism allows the semantics of a command to stay the same,
while the actual implementation is can change. A TextBox, for example, handles the Paste command differently
than a control designed to support images, but the basic idea of what it means to paste something stays the
same. The command logic cannot be supplied by the command, but rather must be supplied by the control or
the application.
Many controls in WPF do have built in support for some of the commands in the command library. TextBox, for
example, supports many of the application edit commands such as Paste, Copy, Cut, Redo, and Undo. The
application developer does not have to do anything special to get these commands to work with these controls.
If the TextBox is the command target when the command is executed, it will handle the command using the
CommandBinding that is built into the control.
The following shows how to use a MenuItem as the command source for the Paste command, where a TextBox is
the target of the command. All the logic that defines how the TextBox performs the paste is built into the TextBox
control.
A MenuItem is created and it's Command property is set to the Paste command. The CommandTarget is not
explicitly set to the TextBox object. When the CommandTarget is not set, the target for the command is the
element which has keyboard focus. If the element which has keyboard focus does not support the Paste
command or cannot currently execute the paste command (the clipboard is empty, for example) then the
MenuItem would be grayed out.
<Window x:Class="SDKSamples.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MenuItemCommandTask"
    >
    <DockPanel>
      <Menu DockPanel.Dock="Top">
        <MenuItem Command="ApplicationCommands.Paste" Width="75" />
      </Menu>
      <TextBox BorderBrush="Black" BorderThickness="2" Margin="25"
                TextWrapping="Wrap">
        The MenuItem will not be enabled until
        this TextBox gets keyboard focus
      </TextBox>
    </DockPanel>
</Window>
// Window1 constructor
public Window1()
{
    InitializeComponent();
    // Instantiating UIElements.
    DockPanel mainPanel = new DockPanel();
    Menu mainMenu = new Menu();
    MenuItem pasteMenuItem = new MenuItem();
    TextBox mainTextBox = new TextBox();
See also
 Commanding Overview
 Hook Up a Command to a Control with No Command Support
       Digital Ink
       11/21/2022 • 2 minutes to read • Edit Online
This section discusses the use of digital ink in the WPF. Traditionally found only in the Tablet PC SDK, digital ink is
now available in the core Windows Presentation Foundation. This means you can now develop full-fledged
Tablet PC applications by using the power of Windows Presentation Foundation.
In This Section
Overviews
How-to Topics
Related Sections
Windows Presentation Foundation
      Digital Ink Overviews
      11/21/2022 • 2 minutes to read • Edit Online
In This Section
Getting Started with Ink
Collecting Ink
Handwriting Recognition
Storing Ink
The Ink Object Model: Windows Forms and COM versus WPF
Advanced Ink Handling
       Get Started with Ink in WPF
       11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) has an ink feature that makes it easy to incorporate digital ink into
your app.
Prerequisites
To use the following examples, first install Visual Studio. It also helps to know how to write basic WPF apps. For
help getting started with WPF, see Walkthrough: My first WPF desktop application.
Quick Start
This section helps you write a simple WPF application that collects ink.
Got Ink?
To create a WPF app that supports ink:
1. Open Visual Studio.
2. Create a new WPF App .
   In the New Project dialog, expand the Installed > Visual C# or Visual Basic > Windows Desktop
   category. Then, select the WPF App (.NET Framework) app template. Enter a name, and then select OK .
   Visual Studio creates the project, and MainWindow.xaml opens in the designer.
3. Type   <InkCanvas/>   between the   <Grid>   tags.
4. Press F5 to launch your application in the debugger.
5. Using a stylus or mouse, write hello world in the window.
You've written the ink equivalent of a "hello world" application with only 12 keystrokes!
Spice Up Your App
Let’s take advantage of some features of the WPF. Replace everything between the opening and closing
<Window> tags with the following markup:
   <Page>
     <InkCanvas Name="myInkCanvas" MouseRightButtonUp="RightMouseUpHandler">
       <InkCanvas.Background>
          <LinearGradientBrush>
            <GradientStop Color="Yellow" Offset="0.0" />
              <GradientStop Color="Blue" Offset="0.5" />
                <GradientStop Color="HotPink" Offset="1.0" />
                  </LinearGradientBrush>
       </InkCanvas.Background>
     </InkCanvas>
   </Page>
2. In Solution Explorer , expand MainWindow.xaml and open the code-behind file (MainWindow.xaml.cs or
   MainWindow.xaml.vb). Add the following event handler code:
End Sub
3. Run the application. Add some ink, and then right-click with the mouse or perform a press-and-hold
   equivalent with a stylus.
   The display zooms in each time you click with the right mouse button.
Use Procedural Code Instead of XAML
You can access all WPF features from procedural code. Follow these steps to create a "Hello Ink World"
application for WPF that doesn’t use any XAML at all.
1. Create a new console application project in Visual Studio.
   In the New Project dialog, expand the Installed > Visual C# or Visual Basic > Windows Desktop
   category. Then, select the Console App (.NET Framework) app template. Enter a name, and then select
   OK .
2. Paste the following code into the Program.cs or Program.vb file:
      using System;
      using System.Windows;
      using System.Windows.Controls;
      class Program : Application
      {
          Window win;
          InkCanvas ic;
          [STAThread]
          static void Main(string[] args)
          {
              new Program().Run();
          }
      }
      Imports System.Windows
      Imports System.Windows.Controls
      Class Program
          Inherits Application
          Private win As Window
          Private ic As InkCanvas
End Sub
End Class
Module Module1
          Sub Main()
              Dim prog As New Program()
              prog.Run()
End Sub
End Module
See also
   Digital Ink
   Collecting Ink
   Handwriting Recognition
   Storing Ink
        Collect Ink
        11/21/2022 • 4 minutes to read • Edit Online
The Windows Presentation Foundation platform collects digital ink as a core part of its functionality. This topic
discusses methods for collection of ink in Windows Presentation Foundation (WPF).
Prerequisites
To use the following examples, you must first install Visual Studio and the Windows SDK. You should also
understand how to write applications for the WPF. For more information about getting started with WPF, see
Walkthrough: My first WPF desktop application.
   <Grid>
     <InkCanvas/>
   </Grid>
The InkCanvas element can also contain child elements, making it possible to add ink annotation capabilities to
almost any type of XAML element. For example, to add inking capabilities to a text element, simply make it a
child of an InkCanvas:
   <InkCanvas>
     <TextBlock>Show text here.</TextBlock>
   </InkCanvas>
   <InkCanvas>
     <Image Source="myPicture.jpg"/>
   </InkCanvas>
InkCollection Modes
The InkCanvas provides support for various input modes through its EditingMode property.
Manipulate Ink
The InkCanvas provides support for many ink editing operations. For example, InkCanvas supports back-of-pen
erase, and no additional code is needed to add the functionality to the element.
Selection
Setting selection mode is as simple as setting the InkCanvasEditingMode property to Select .
The following code sets the editing mode based on the value of a CheckBox:
DrawingAttributes
Use the DrawingAttributes property to change the appearance of ink strokes. For instance, the Color member of
DrawingAttributes sets the color of the rendered Stroke.
The following example changes the color of the selected strokes to red:
DefaultDrawingAttributes
The DefaultDrawingAttributes property provides access to properties such as the height, width, and color of the
strokes to be created in an InkCanvas. Once you change the DefaultDrawingAttributes, all future strokes entered
into the InkCanvas are rendered with the new property values.
In addition to modifying the DefaultDrawingAttributes in the code-behind file, you can use XAML syntax for
specifying DefaultDrawingAttributes properties.
The next example demonstrates how to set the Color property. To use this code, create a new WPF project called
"HelloInkCanvas" in Visual Studio. Replace the code in the MainWindow.xaml file with the following code:
   <Window x:Class="HelloInkCanvas.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:Ink="clr-namespace:System.Windows.Ink;assembly=PresentationCore"
       Title="Hello, InkCanvas!" Height="300" Width="300"
       >
     <Grid>
       <InkCanvas Name="inkCanvas1" Background="Ivory">
         <InkCanvas.DefaultDrawingAttributes>
            <Ink:DrawingAttributes xmlns:ink="system-windows-ink" Color="Red" Width="5" />
         </InkCanvas.DefaultDrawingAttributes>
       </InkCanvas>
       <!-- This stack panel of buttons is a sibling to InkCanvas (not a child) but overlapping it,
             higher in z-order, so that ink is collected and rendered behind -->
       <StackPanel Name="buttonBar" VerticalAlignment="Top" Height="26" Orientation="Horizontal" Margin="5">
         <Button Click="Ink">Ink</Button>
         <Button Click="Highlight">Highlight</Button>
         <Button Click="EraseStroke">EraseStroke</Button>
         <Button Click="Select">Select</Button>
       </StackPanel>
     </Grid>
   </Window>
Next, add the following button event handlers to the code behind file, inside the MainWindow class:
After copying this code, press F5 in Visual Studio to run the program in the debugger.
Notice how the StackPanel places the buttons on top of the InkCanvas. If you try to ink over the top of the
buttons, the InkCanvas collects and renders the ink behind the buttons. This is because the buttons are siblings
of the InkCanvas as opposed to children. Also, the buttons are higher in the z-order, so the ink is rendered
behind them.
See also
   DrawingAttributes
   DefaultDrawingAttributes
   System.Windows.Ink
       Handwriting Recognition
       11/21/2022 • 2 minutes to read • Edit Online
This section discusses the fundamentals of recognition as it pertains to digital ink in the WPF platform.
Recognition Solutions
The following example shows how to recognize ink using the Microsoft.Ink.InkCollector class.
  NOTE
  This sample requires that handwriting recognizers be installed on the system.
Create a new WPF application project in Visual Studio called InkRecognition . Replace the contents of the
Window1.xaml file with the following XAML code. This code renders the application's user interface.
   <Window x:Class="InkRecognition.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="InkRecognition"
       >
     <Canvas Name="theRootCanvas">
       <Border
         Background="White"
         BorderBrush="Black"
         BorderThickness="2"
         Height="300"
         Width="300"
         Canvas.Top="10"
         Canvas.Left="10">
         <InkCanvas Name="theInkCanvas"></InkCanvas>
       </Border>
       <TextBox Name="textBox1"
         Height="25"
         Width="225"
         Canvas.Top="325"
         Canvas.Left="10"></TextBox>
       <Button
         Height="25"
         Width="75"
         Canvas.Top="325"
         Canvas.Left="235"
         Click="buttonClick">Recognize</Button>
           <Button x:Name="btnClear" Content="Clear Canvas" Canvas.Left="10" Canvas.Top="367" Width="75"
   Click="btnClear_Click"/>
       </Canvas>
   </Window>
Add a reference to the Microsoft Ink assembly, Microsoft.Ink.dll, which can be found in \Program Files\Common
Files\Microsoft Shared\Ink. Replace the contents of the code behind file with the following code.
using System.Windows;
using Microsoft.Ink;
using System.IO;
namespace InkRecognition
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
        public Window1()
        {
            InitializeComponent();
        }
                           if (status == RecognitionStatus.NoError)
                                textBox1.Text = result.TopString;
                           else
                                MessageBox.Show("Recognition failed");
                    }
                    else
                    {
                           MessageBox.Show("No stroke detected");
                    }
                }
            }
        }
 '/ <summary>
 '/ Interaction logic for Window1.xaml
 '/ </summary>
Namespace InkRecognition
     Class Window1
         Inherits Window
See also
 Microsoft.Ink.InkCollector
       Storing Ink
       11/21/2022 • 2 minutes to read • Edit Online
The Save methods provide support for storing ink as Ink Serialized Format (ISF). Constructors for the
StrokeCollection class provide support for reading ink data.
       if (saveFileDialog1.ShowDialog() == true)
       {
           FileStream fs = new FileStream(saveFileDialog1.FileName,
                                          FileMode.Create);
           theInkCanvas.Strokes.Save(fs);
           fs.Close();
       }
   }
       If saveFileDialog1.ShowDialog() Then
           Dim fs As New FileStream(saveFileDialog1.FileName, FileMode.Create)
           theInkCanvas.Strokes.Save(fs)
           fs.Close()
       End If
End Sub
The following example implements a button-click event handler that presents the user with a File Open dialog
box and reads ink from the file into an InkCanvas element.
 private void buttonLoadClick(object sender, RoutedEventArgs e)
 {
     OpenFileDialog openFileDialog1 = new OpenFileDialog();
     openFileDialog1.Filter = "isf files (*.isf)|*.isf";
     if (openFileDialog1.ShowDialog() == true)
     {
         FileStream fs = new FileStream(openFileDialog1.FileName,
                                        FileMode.Open);
         theInkCanvas.Strokes = new StrokeCollection(fs);
         fs.Close();
     }
 }
     If openFileDialog1.ShowDialog() Then
         Dim fs As New FileStream(openFileDialog1.FileName, FileMode.Open)
         theInkCanvas.Strokes = New StrokeCollection(fs)
         fs.Close()
     End If
End Sub
See also
 InkCanvas
 Windows Presentation Foundation
       The Ink Object Model: Windows Forms and COM
       versus WPF
       11/21/2022 • 6 minutes to read • Edit Online
There are essentially three platforms that support digital ink: the Tablet PC Windows Forms platform, the Tablet
PC COM platform, and the Windows Presentation Foundation (WPF) platform. The Windows Forms and COM
platforms share a similar object model, but the object model for the WPF platform is substantially different. This
topic discusses the differences at a high-level so that developers that have worked with one object model can
better understand the other.
                                                                                  O N T H E W IN DO W S F O RM S/ C O M
  TO DO T H IS…                          O N T H E W P F P L AT F O RM …          P L AT F O RM S…
  Add an ink-enabled control to an       See Getting Started with Ink.            See Auto Claims Form Sample
  application
Enable ink on a custom control See Creating an Ink Input Control. See Ink Clipboard Sample.
Ink Data
On the Windows Forms and COM platforms, Microsoft.Ink.InkCollector, Microsoft.Ink.InkOverlay,
Microsoft.Ink.InkEdit, and Microsoft.Ink.InkPicture each expose a Microsoft.Ink.Ink object. The Microsoft.Ink.Ink
object contains the data for one or more Microsoft.Ink.Stroke objects and exposes common methods and
properties to manage and manipulate those strokes. The Microsoft.Ink.Ink object manages the lifetime of the
strokes it contains; the Microsoft.Ink.Ink object creates and deletes the strokes that it owns. Each
Microsoft.Ink.Stroke has an identifier that is unique within its parent Microsoft.Ink.Ink object.
On the WPF platform, the System.Windows.Ink.Stroke class owns and manages its own lifetime. A group of
Stroke objects can be collected together in a StrokeCollection, which provides methods for common ink data
management operations such as hit testing, erasing, transforming, and serializing the ink. A Stroke can belong
to zero, one, or more StrokeCollection objects at any give time. Instead of having a Microsoft.Ink.Ink object, the
InkCanvas and InkPresenter contain a System.Windows.Ink.StrokeCollection.
The following pair of illustrations compares the ink data object models. On the Windows Forms and COM
platforms, the Microsoft.Ink.Ink object constrains the lifetime of the Microsoft.Ink.Stroke objects, and the stylus
packets belong to the individual strokes. Two or more strokes can reference the same
Microsoft.Ink.DrawingAttributes object, as shown in the following illustration.
On the WPF, each System.Windows.Ink.Stroke is a common language runtime object that exists as long as
something has a reference to it. Each Stroke references a StylusPointCollection and
System.Windows.Ink.DrawingAttributes object, which are also common language runtime objects.
The following table compares how to accomplish some common tasks on the WPF platform and the Windows
Forms and COM platforms.
                                          W IN DO W S P RESEN TAT IO N
  TA SK                                   F O UN DAT IO N                         W IN DO W S F O RM S A N D C O M
Imports Microsoft.Ink
Imports System.Drawing
/// <summary>
/// Saves the digital ink from a Windows Forms application.
/// </summary>
/// <param name="inkToSave">An Ink object that contains the
/// digital ink.</param>
/// <returns>A MemoryStream containing the digital ink.</returns>
MemoryStream SaveInkInWinforms(Ink inkToSave)
{
    byte[] savedInk = inkToSave.Save();
'/ <summary>
'/ Saves the digital ink from a Windows Forms application.
'/ </summary>
'/ <param name="inkToSave">An Ink object that contains the
'/ digital ink.</param>
'/ <returns>A MemoryStream containing the digital ink.</returns>
Function SaveInkInWinforms(ByVal inkToSave As Ink) As MemoryStream
    Dim savedInk As Byte() = inkToSave.Save()
using System.Windows.Ink;
Imports System.Windows.Ink
/// <summary>
/// Loads digital ink into a StrokeCollection, which can be
/// used by a WPF application.
/// </summary>
/// <param name="savedInk">A MemoryStream containing the digital ink.</param>
public void LoadInkInWPF(MemoryStream inkStream)
{
    strokes = new StrokeCollection(inkStream);
}
   '/ <summary>
   '/ Loads digital ink into a StrokeCollection, which can be
   '/ used by a WPF application.
   '/ </summary>
   '/ <param name="savedInk">A MemoryStream containing the digital ink.</param>
   Public Sub LoadInkInWPF(ByVal inkStream As MemoryStream)
       strokes = New StrokeCollection(inkStream)
End Sub
The following examples save ink from a Windows Presentation Foundation application and load the ink into a
Windows Forms application.
using System.Windows.Ink;
Imports System.Windows.Ink
   /// <summary>
   /// Saves the digital ink from a WPF application.
   /// </summary>
   /// <param name="inkToSave">A StrokeCollection that contains the
   /// digital ink.</param>
   /// <returns>A MemoryStream containing the digital ink.</returns>
   MemoryStream SaveInkInWPF(StrokeCollection strokesToSave)
   {
       MemoryStream savedInk = new MemoryStream();
strokesToSave.Save(savedInk);
       return savedInk;
   }
   '/ <summary>
   '/ Saves the digital ink from a WPF application.
   '/ </summary>
   '/ <param name="inkToSave">A StrokeCollection that contains the
   '/ digital ink.</param>
   '/ <returns>A MemoryStream containing the digital ink.</returns>
   Function SaveInkInWPF(ByVal strokesToSave As StrokeCollection) As MemoryStream
       Dim savedInk As New MemoryStream()
strokesToSave.Save(savedInk)
Return savedInk
   using Microsoft.Ink;
   using System.Drawing;
   Imports Microsoft.Ink
   Imports System.Drawing
   /// <summary>
   /// Loads digital ink into a Windows Forms application.
   /// </summary>
   /// <param name="savedInk">A MemoryStream containing the digital ink.</param>
   public void LoadInkInWinforms(MemoryStream savedInk)
   {
       theInk = new Ink();
       theInk.Load(savedInk.ToArray());
   }
   '/ <summary>
   '/ Loads digital ink into a Windows Forms application.
   '/ </summary>
   '/ <param name="savedInk">A MemoryStream containing the digital ink.</param>
   Public Sub LoadInkInWinforms(ByVal savedInk As MemoryStream)
       theInk = New Ink()
       theInk.Load(savedInk.ToArray())
End Sub
Pen Data
All three platforms provide you with ways to intercept and manipulate the data that comes in from a tablet pen.
On the Windows Forms and COM Platforms, this is achieved by creating a Microsoft.StylusInput.RealTimeStylus,
attaching a window or control to it, and creating a class that implements the
Microsoft.StylusInput.IStylusSyncPlugin or Microsoft.StylusInput.IStylusAsyncPlugin interface. The custom plug-
in is then added to the plug-in collection of the Microsoft.StylusInput.RealTimeStylus. For more information
about this object model, see Architecture of the StylusInput APIs.
On the WPF platform, the UIElement class exposes a collection of plug-ins, similar in design to the
Microsoft.StylusInput.RealTimeStylus. To intercept pen data, create a class that inherits from StylusPlugIn and
add the object to the StylusPlugIns collection of the UIElement. For more information about this interaction, see
Intercepting Input from the Stylus.
On all platforms, a thread pool receives the ink data via stylus events and sends it to the application thread. For
more information about threading on the COM and Windows Platforms, see Threading Considerations for the
StylusInput APIs. For more information about threading on the Windows Presentation Software, see The Ink
Threading Model.
The following illustration compares the object models for the classes that receive pen data on the pen thread
pool.
       Advanced Ink Handling
       11/21/2022 • 2 minutes to read • Edit Online
The WPF ships with the InkCanvas, and is an element you can put in your application to immediately start
collecting and displaying ink. However, if the InkCanvas control does not provide a fine enough level of control,
you can maintain control at a higher level by customizing your own ink collection and ink rendering classes
using System.Windows.Input.StylusPlugIns.
The System.Windows.Input.StylusPlugIns classes provide a mechanism for implementing low-level control over
Stylus input and dynamically rendering ink. The StylusPlugIn class provides a mechanism for you to implement
custom behavior and apply it to the stream of data coming from the stylus device for optimal performance. The
DynamicRenderer, a specialized StylusPlugIn, allows you to customize dynamically rendering ink data in real-
time which means that the DynamicRenderer draws digital ink immediately as StylusPoint data is generated, so
it appears to "flow" from the stylus device.
In This Section
Custom Rendering Ink
Intercepting Input from the Stylus
Creating an Ink Input Control
The Ink Threading Model
       Custom Rendering Ink
       11/21/2022 • 7 minutes to read • Edit Online
The DrawingAttributes property of a stroke allows you to specify the appearance of a stroke, such as its size,
color, and shape, but there may be times that you want to customize the appearance beyond what
DrawingAttributes allow. You may want to customize the appearance of ink by rendering in the appearance of an
air brush, oil paint, and many other effects. The Windows Presentation Foundation (WPF) allows you to custom
render ink by implementing a custom DynamicRenderer and Stroke object.
This topic contains the following subsections:
   Architecture
   Implementing a Dynamic Renderer
   Implementing Custom Strokes
   Implementing a Custom InkCanvas
   Conclusion
Architecture
Ink rendering occurs two times; when a user writes ink to an inking surface, and again after the stroke is added
to the ink-enabled surface. The DynamicRenderer renders the ink when the user moves the tablet pen on the
digitizer, and the Stroke renders itself once it is added to an element.
There are three classes to implement when dynamically rendering ink.
1. DynamicRenderer : Implement a class that derives from DynamicRenderer. This class is a specialized
   StylusPlugIn that renders the stroke as it is drawn. The DynamicRenderer does the rendering on a
   separate thread, so the inking surface appears to collect ink even when the application user interface (UI)
   thread is blocked. For more information about the threading model, see The Ink Threading Model. To
   customize dynamically rendering a stroke, override the OnDraw method.
2. Stroke : Implement a class that derives from Stroke. This class is responsible for static rendering of the
   StylusPoint data after it has been converted into a Stroke object. Override the DrawCore method to
   ensure that static rendering of the stroke is consistent with dynamic rendering.
3. InkCanvas: Implement a class that derives from InkCanvas. Assign the customized DynamicRenderer to
   the DynamicRenderer property. Override the OnStrokeCollected method and add a custom stroke to the
   Strokes property. This ensures that the appearance of the ink is consistent.
Imports   System.Windows.Media
Imports   System.Windows
Imports   System.Windows.Input.StylusPlugIns
Imports   System.Windows.Input
Imports   System.Windows.Ink
    [ThreadStatic]
    static private Pen pen = null;
       <ThreadStatic()> _
       Private Shared pen As Pen = Nothing
End Sub
       End Sub
   End Class
   using   System;
   using   System.Windows.Media;
   using   System.Windows;
   using   System.Windows.Input.StylusPlugIns;
   using   System.Windows.Input;
   using   System.Windows.Ink;
   Imports   System.Windows.Media
   Imports   System.Windows
   Imports   System.Windows.Input.StylusPlugIns
   Imports   System.Windows.Input
   Imports   System.Windows.Ink
End Sub
       End Sub
   End Class
An InkCanvas can have more than one DynamicRenderer. You can add multiple DynamicRenderer objects to the
InkCanvas by adding them to the StylusPlugIns property.
Conclusion
You can customize the appearance of ink by deriving your own DynamicRenderer, Stroke, and InkCanvas classes.
Together, these classes ensure that the appearance of the stroke is consistent when the user draws the stroke
and after it is collected.
See also
   Advanced Ink Handling
             Intercepting Input from the Stylus
             11/21/2022 • 5 minutes to read • Edit Online
Architecture
The StylusPlugIn is the evolution of the StylusInput APIs, described in Accessing and Manipulating Pen Input.
Each UIElement has a StylusPlugIns property that is a StylusPlugInCollection. You can add a StylusPlugIn to an
element's StylusPlugIns property to manipulate StylusPoint data as it is generated. StylusPoint data consists of
all the properties supported by the system digitizer, including the X and Y point data, as well as PressureFactor
data.
Your StylusPlugIn objects are inserted directly into the stream of data coming from the Stylus device when you
add the StylusPlugIn to the StylusPlugIns property. The order in which plug-ins are added to the StylusPlugIns
collection dictates the order in which they will receive StylusPoint data. For example, if you add a filter plug-in
that restricts input to a particular region, and then add a plug-in that recognizes gestures as they are written, the
plug-in that recognizes gestures will receive filtered StylusPoint data.
If a StylusPlugIn throws or causes an exception, the application will close. You should thoroughly test controls
that consume a StylusPlugIn and only use a control if you are certain the StylusPlugIn will not throw an
exception.
The following example demonstrates a plug-in that restricts the stylus input by modifying the X and Y values in
the StylusPoint data as it comes in from the Stylus device.
     using     System;
     using     System.Windows.Media;
     using     System.Windows;
     using     System.Windows.Input.StylusPlugIns;
     using     System.Windows.Input;
     using     System.Windows.Ink;
Imports   System.Windows.Media
Imports   System.Windows
Imports   System.Windows.Input.StylusPlugIns
Imports   System.Windows.Input
Imports   System.Windows.Ink
End Sub
End Sub
End Sub
    End Sub
End Class
Adding Your Plug-in to an InkCanvas
The easiest way to use your custom plug-in is to implement a class that derives from InkCanvas and add it to the
StylusPlugIns property.
The following example demonstrates a custom InkCanvas that filters the ink.
        public FilterInkCanvas()
            : base()
        {
            this.StylusPlugIns.Add(filter);
        }
   }
If you add a FilterInkCanvas to your application and run it, you will notice that the ink isn't restricted to a
region until after the user completes a stroke. This is because the InkCanvas has a DynamicRenderer property,
which is a StylusPlugIn and is already a member of the StylusPlugIns collection. The custom StylusPlugIn you
added to the StylusPlugIns collection receives the StylusPoint data after DynamicRenderer receives data. As a
result, the StylusPoint data will not be filtered until after the user lifts the pen to end a stroke. To filter the ink as
the user draws it, you must insert the FilterPlugin before the DynamicRenderer.
The following C# code demonstrates a custom InkCanvas that filters the ink as it is drawn.
        public DynamicallyFilteredInkCanvas()
            : base()
        {
            int dynamicRenderIndex =
                this.StylusPlugIns.IndexOf(this.DynamicRenderer);
            this.StylusPlugIns.Insert(dynamicRenderIndex, filter);
        }
   }
Conclusion
By deriving your own StylusPlugIn classes and inserting them into StylusPlugInCollection collections, you can
greatly enhance the behavior of your digital ink. You have access to the StylusPoint data as it is generated, giving
you the opportunity to customize the Stylus input. Because you have such low-level access to the StylusPoint
data, you can implement ink collection and rendering with optimal performance for your application.
See also
   Advanced Ink Handling
   Accessing and Manipulating Pen Input
       Creating an Ink Input Control
       11/21/2022 • 7 minutes to read • Edit Online
You can create a custom control that dynamically and statically renders ink. That is, render ink as a user draws a
stroke, causing the ink to appear to "flow" from the tablet pen, and display ink after it is added to the control,
either via the tablet pen, pasted from the Clipboard, or loaded from a file. To dynamically render ink, your
control must use a DynamicRenderer. To statically render ink, you must override the stylus event methods
(OnStylusDown, OnStylusMove, and OnStylusUp) to collect StylusPoint data, create strokes, and add them to an
InkPresenter (which renders the ink on the control).
This topic contains the following subsections:
   How to: Collect Stylus Point Data and Create Ink Strokes
   How to: Enable Your Control to Accept Input from the Mouse
   Putting it together
   Using Additional Plug-ins and DynamicRenderers
   Conclusion
How to: Collect Stylus Point Data and Create Ink Strokes
To create a control that collects and manages ink strokes do the following:
1. Derive a class from Control or one of the classes derived from Control, such as Label.
      using   System;
      using   System.Windows.Ink;
      using   System.Windows.Input;
      using   System.Windows.Input.StylusPlugIns;
      using   System.Windows.Controls;
      using   System.Windows;
2. Add an InkPresenter to the class and set the Content property to the new InkPresenter.
InkPresenter ip;
      public InkControl()
      {
          // Add an InkPresenter for drawing.
          ip = new InkPresenter();
          this.Content = ip;
      }
3. Attach the RootVisual of the DynamicRenderer to the InkPresenter by calling the AttachVisuals method,
   and add the DynamicRenderer to the StylusPlugIns collection. This allows the InkPresenter to display the
   ink as the stylus point data is collected by your control.
      public InkControl()
      {
4. Override the OnStylusDown method. In this method, capture the stylus with a call to Capture. By
   capturing the stylus, your control will to continue to receive StylusMove and StylusUp events even if the
   stylus leaves the control's boundaries. This is not strictly mandatory, but almost always desired for a good
   user experience. Create a new StylusPointCollection to gather StylusPoint data. Finally, add the initial set
   of StylusPoint data to the StylusPointCollection.
          stylusPoints.Add(eventPoints);
      }
5. Override the OnStylusMove method and add the StylusPoint data to the StylusPointCollection object that
   you created earlier.
6. Override the OnStylusUp method and create a new Stroke with the StylusPointCollection data. Add the
   new Stroke you created to the Strokes collection of the InkPresenter and release stylus capture.
      protected override void OnStylusUp(StylusEventArgs e)
      {
          if (stylusPoints == null)
          {
              return;
          }
How to: Enable Your Control to Accept Input from the Mouse
If you add the preceding control to your application, run it, and use the mouse as an input device, you will notice
that the strokes are not persisted. To persist the strokes when the mouse is used as the input device do the
following:
1. Override the OnMouseLeftButtonDown and create a new StylusPointCollection Get the position of the
   mouse when the event occurred and create a StylusPoint using the point data and add the StylusPoint to
   the StylusPointCollection.
base.OnMouseLeftButtonDown(e);
2. Override the OnMouseMove method. Get the position of the mouse when the event occurred and create
   a StylusPoint using the point data. Add the StylusPoint to the StylusPointCollection object that you created
   earlier.
      protected override void OnMouseMove(MouseEventArgs e)
      {
base.OnMouseMove(e);
          Point pt = e.GetPosition(this);
          stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
      }
3. Override the OnMouseLeftButtonUp method. Create a new Stroke with the StylusPointCollection data,
   and add the new Stroke you created to the Strokes collection of the InkPresenter.
base.OnMouseLeftButtonUp(e);
          if (stylusPoints == null)
          {
              return;
          }
          Point pt = e.GetPosition(this);
          stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
          stylusPoints = null;
      }
Putting it together
The following example is a custom control that collects ink when the user uses either the mouse or the pen.
using   System;
using   System.Windows.Ink;
using   System.Windows.Input;
using   System.Windows.Input.StylusPlugIns;
using   System.Windows.Controls;
using   System.Windows;
    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;
    static InkControl()
    {
        // Allow ink to be drawn only within the bounds of the control.
        Type owner = typeof(InkControl);
        ClipToBoundsProperty.OverrideMetadata(owner,
            new FrameworkPropertyMetadata(true));
    }
          stylusPoints.Add(eventPoints);
    }
base.OnMouseLeftButtonDown(e);
base.OnMouseMove(e);
    Point pt = e.GetPosition(this);
    stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
}
           if (stylusPoints == null)
           {
               return;
           }
           Point pt = e.GetPosition(this);
           stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
           stylusPoints = null;
       }
   }
Conclusion
You can create a control that collects and renders ink by overriding the stylus event methods. By creating your
own control, deriving your own StylusPlugIn classes, and inserting them the into StylusPlugInCollection, you can
implement virtually any behavior imaginable with digital ink. You have access to the StylusPoint data as it is
generated, giving you the opportunity to customize Stylus input and render it on the screen as appropriate for
your application. Because you have such low-level access to the StylusPoint data, you can implement ink
collection and render it with optimal performance for your application.
See also
   Advanced Ink Handling
   Accessing and Manipulating Pen Input
       The Ink Threading Model
       11/21/2022 • 4 minutes to read • Edit Online
One of the benefits of ink on a Tablet PC is that it feels a lot like writing with a regular pen and paper. To
accomplish this, the tablet pen collects input data at a much higher rate than a mouse does and renders the ink
as the user writes. The application's user interface (UI) thread is not sufficient for collecting pen data and
rendering ink, because it can become blocked. To solve this, a WPF application uses two additional threads when
a user writes ink.
The following list describes the threads that take part in collecting and rendering digital ink:
   Pen thread - the thread that takes input from the stylus. (In reality, this is a thread pool, but this topic
   refers to it as a pen thread.)
   Application user interface thread - the thread that controls the user interface of the application.
   Dynamic rendering thread - the thread that renders the ink while the user draws a stroke. The dynamic
   rendering thread is different than the thread that renders other UI elements for the application, as
   mentioned in Window Presentation Foundation Threading Model.
The inking model is the same whether the application uses the InkCanvas or a custom control similar to the one
in Creating an Ink Input Control. Although this topic discusses threading in terms of the InkCanvas, the same
concepts apply when you create a custom control.
Threading Overview
The following diagram illustrates the threading model when a user draws a stroke:
In This Section
Select Ink from a Custom Control
Add Custom Data to Ink Data
Erase Ink on a Custom Control
Recognize Application Gestures
Drag and Drop Ink
Data Bind to an InkCanvas
Analyze Ink with Analysis Hints
Rotate Ink
Disable the RealTimeStylus for WPF Applications
       How to: Select Ink from a Custom Control
       11/21/2022 • 16 minutes to read • Edit Online
By adding an IncrementalLassoHitTester to your custom control, you can enable your control so that a user can
select ink with a lasso tool, similar to the way the InkCanvas selects ink with a lasso.
This example assumes you are familiar with creating an ink-enabled custom control. To create a custom control
that accepts ink input, see Creating an Ink Input Control.
Example
When the user draws a lasso, the IncrementalLassoHitTester predicts which strokes will be within the lasso
path's boundaries after the user completes the lasso. Strokes that are determined to be within the lasso path's
boundaries can be thought of as being selected. Selected strokes can also become unselected. For example, if
the user reverses direction while drawing the lasso, the IncrementalLassoHitTester may unselect some strokes.
The IncrementalLassoHitTester raises the SelectionChanged event, which enables your custom control to
respond while the user is drawing the lasso. For example, you can change the appearance of strokes as the user
selects and unselects them.
Next, add two DrawingAttributes to the class: one to use when the user writes ink, one to use when the user
selects ink. In the constructor, initialize the DrawingAttributes and attach both AttributeChanged events to the
same event handler. Then set the DrawingAttributes property of the DynamicRenderer to the ink
DrawingAttributes.
   DrawingAttributes inkDA;
   DrawingAttributes selectDA;
   Private inkDA As DrawingAttributes
   Private selectDA As DrawingAttributes
   // In the constructor.
   // Selection drawing attributes use dark gray ink.
   selectDA = new DrawingAttributes();
   selectDA.Color = Colors.DarkGray;
   AddHandler inkDA.AttributeChanged, _
              AddressOf DrawingAttributesChanged
   AddHandler selectDA.AttributeChanged, _
              AddressOf DrawingAttributesChanged
Add a property that exposes the selection mode. When the user changes the selection mode, set the
DrawingAttributes property of the DynamicRenderer to the appropriate DrawingAttributes object and then
reattach the RootVisual Property to the InkPresenter.
   // Property to indicate whether the user is inputting or
   // selecting ink.
   public InkMode Mode
   {
       get
       {
           return mode;
       }
       set
       {
             mode = value;
Expose the DrawingAttributes as properties so applications can determine the appearance of the ink strokes and
selection strokes.
   // Property to allow the user to change the pen's DrawingAttributes.
   public DrawingAttributes InkDrawingAttributes
   {
       get
       {
           return inkDA;
       }
   }
When a property of a DrawingAttributes object changes, the RootVisual must be reattached to the InkPresenter.
In the event handler for the AttributeChanged event, reattach the RootVisual to the InkPresenter.
End Sub
   ' StylusPointCollection that collects the stylus points from the stylus events.
   Private stylusPoints As StylusPointCollection
When the user starts to draw a stroke, either ink or the lasso, unselect any selected strokes. Then, if the user is
drawing a lasso, create an IncrementalLassoHitTester by calling GetIncrementalLassoHitTester, subscribe to the
SelectionChanged event, and call AddPoints. This code can be a separate method and called from the
OnStylusDown and OnMouseDown methods.
       if (mode == InkMode.Select)
       {
           // Remove the previously drawn lasso, if it exists.
           if (lassoPath != null)
           {
               presenter.Strokes.Remove(lassoPath);
               lassoPath = null;
           }
             selectionTester =
                 presenter.Strokes.GetIncrementalLassoHitTester(80);
             selectionTester.SelectionChanged +=
                 new LassoSelectionChangedEventHandler(selectionTester_SelectionChanged);
             selectionTester.AddPoints(collectedPoints);
       }
   }
           selectionTester = presenter.Strokes.GetIncrementalLassoHitTester(80)
           AddHandler selectionTester.SelectionChanged, AddressOf selectionTester_SelectionChanged
           selectionTester.AddPoints(collectedPoints)
       End If
   End Sub
Add the stylus points to the IncrementalLassoHitTester while the user draws the lasso. Call the following method
from the OnStylusMove, OnStylusUp, OnMouseMove, and OnMouseLeftButtonUp methods.
End Sub
Handle the IncrementalLassoHitTester.SelectionChanged event to respond when the user selects and unselects
strokes. The LassoSelectionChangedEventArgs class has the SelectedStrokes and DeselectedStrokes properties
that get the strokes that were selected and unselected, respectively.
End Sub
When the user finishes drawing the lasso, unsubscribe from the SelectionChanged event and call EndHitTesting.
   using   System;
   using   System.Windows;
   using   System.Windows.Controls;
   using   System.Windows.Media;
   using   System.Windows.Input;
   using   System.Windows.Input.StylusPlugIns;
   using   System.Windows.Ink;
// This control allows the user to input and select ink. When the
// user selects ink, the lasso remains visible until they erase, or clip
// the selected strokes, or clear the selection. When the control is
// in selection mode, strokes that are selected turn red.
public class InkSelector : Label
{
    InkMode mode;
    DrawingAttributes inkDA;
    DrawingAttributes selectDA;
    InkPresenter presenter;
    IncrementalLassoHitTester selectionTester;
    StrokeCollection selectedStrokes = new StrokeCollection();
    // StylusPointCollection that collects the stylus points from the stylus events.
    StylusPointCollection stylusPoints;
    // Stroke that represents the lasso.
    Stroke lassoPath;
DynamicRenderer renderer;
    public InkSelector()
    {
        mode = InkMode.Ink;
        // In the constructor.
        // Selection drawing attributes use dark gray ink.
        selectDA = new DrawingAttributes();
        selectDA.Color = Colors.DarkGray;
    static InkSelector()
    {
        // Allow ink to be drawn only within the bounds of the control.
        Type owner = typeof(InkSelector);
        ClipToBoundsProperty.OverrideMetadata(owner,
            new FrameworkPropertyMetadata(true));
    }
stylusPoints.Add(eventPoints);
    InitializeHitTester(eventPoints);
}
Mouse.Capture(this);
    if (e.StylusDevice != null)
    {
        return;
    }
Point pt = e.GetPosition(this);
stylusPoints.Add(collectedPoints);
    InitializeHitTester(collectedPoints);
}
private void InitializeHitTester(StylusPointCollection collectedPoints)
{
    // Deselect any selected strokes.
    foreach (Stroke selectedStroke in selectedStrokes)
    {
        selectedStroke.DrawingAttributes.Color = inkDA.Color;
    }
    selectedStrokes.Clear();
    if (mode == InkMode.Select)
    {
        // Remove the previously drawn lasso, if it exists.
        if (lassoPath != null)
        {
            presenter.Strokes.Remove(lassoPath);
            lassoPath = null;
        }
        selectionTester =
            presenter.Strokes.GetIncrementalLassoHitTester(80);
        selectionTester.SelectionChanged +=
            new LassoSelectionChangedEventHandler(selectionTester_SelectionChanged);
        selectionTester.AddPoints(collectedPoints);
    }
}
base.OnMouseMove(e);
    if (e.StylusDevice != null)
    {
        return;
    }
    if (e.LeftButton == MouseButtonState.Released)
    {
        return;
    }
Point pt = e.GetPosition(this);
stylusPoints.Add(collectedPoints);
    AddPointsToHitTester(collectedPoints);
}
// When the user lifts the stylus, create a Stroke from the
// collected stylus points and add it to the InkPresenter.
// When the control is selecting strokes, add the
// point data to the IncrementalHitTester.
protected override void OnStylusUp(StylusEventArgs e)
{
    stylusPoints ??= new StylusPointCollection();
    StylusPointCollection collectedPoints =
        e.GetStylusPoints(this, stylusPoints.Description);
    stylusPoints.Add(collectedPoints);
    AddPointsToHitTester(collectedPoints);
    AddStrokeToPresenter();
    stylusPoints = null;
    Stylus.Capture(null);
}
base.OnMouseLeftButtonUp(e);
    stylusPoints.Add(collectedPoints);
    AddPointsToHitTester(collectedPoints);
    AddStrokeToPresenter();
stylusPoints = null;
    Mouse.Capture(null);
}
    if (mode == InkMode.Ink)
    {
        // Add the stroke to the InkPresenter.
        newStroke.DrawingAttributes = inkDA.Clone();
        presenter.Strokes.Add(newStroke);
    }
    set
    {
          mode = value;
              mode = value;
Imports   System.Windows
Imports   System.Windows.Controls
Imports   System.Windows.Media
Imports   System.Windows.Input
Imports   System.Windows.Input.StylusPlugIns
Imports   System.Windows.Ink
' This control allows the user to input and select ink. When the
' user selects ink, the lasso remains visible until they erase, or clip
' the selected strokes, or clear the selection. When the control is
' in selection mode, strokes that are selected turn red.
Public Class InkSelector
    Inherits Label
' StylusPointCollection that collects the stylus points from the stylus events.
Private stylusPoints As StylusPointCollection
    AddHandler inkDA.AttributeChanged, _
               AddressOf DrawingAttributesChanged
    AddHandler selectDA.AttributeChanged, _
               AddressOf DrawingAttributesChanged
End Sub
End Sub
Stylus.Capture(Me)
stylusPoints.Add(eventPoints)
InitializeHitTester(eventPoints)
End Sub
Mouse.Capture(Me)
stylusPoints.Add(collectedPoints)
InitializeHitTester(collectedPoints)
End Sub
        selectionTester = presenter.Strokes.GetIncrementalLassoHitTester(80)
        AddHandler selectionTester.SelectionChanged, AddressOf selectionTester_SelectionChanged
        selectionTester.AddPoints(collectedPoints)
    End If
End Sub
End Sub
MyBase.OnMouseMove(e)
stylusPoints.Add(collectedPoints)
AddPointsToHitTester(collectedPoints)
End Sub
End Sub
' When the user lifts the stylus, create a Stroke from the
' collected stylus points and add it to the InkPresenter.
' When the control is selecting strokes, add the
' point data to the IncrementalHitTester.
Protected Overrides Sub OnStylusUp(ByVal e As StylusEventArgs)
    stylusPoints.Add(collectedPoints)
    AddPointsToHitTester(collectedPoints)
    AddStrokeToPresenter()
stylusPoints = Nothing
Stylus.Capture(Nothing)
End Sub
MyBase.OnMouseLeftButtonUp(e)
    stylusPoints.Add(collectedPoints)
    AddPointsToHitTester(collectedPoints)
    AddStrokeToPresenter()
stylusPoints = Nothing
Mouse.Capture(Nothing)
End Sub
End Sub
End Sub
End Sub
End Class
See also
 IncrementalLassoHitTester
 StrokeCollection
 StylusPointCollection
 Creating an Ink Input Control
       How to: Add Custom Data to Ink Data
       11/21/2022 • 2 minutes to read • Edit Online
You can add custom data to ink that will be saved when the ink is saved as ink serialized format (ISF). You can
save the custom data to the DrawingAttributes, the StrokeCollection, or the Stroke. Being able to save custom
data on three objects gives you the ability to decide the best place to save the data. All three classes use similar
methods to store and access custom data.
Only the following types can be saved as custom data:
   Boolean
   Boolean[]
   Byte
   Byte[]
   Char
   Char[]
   DateTime
   DateTime[]
   Decimal
   Decimal[]
   Double
   Double[]
   Int16
   Int16[]
   Int32
   Int32[]
   Int64
   Int64[]
   Single
   Single[]
   String
   UInt16
   UInt16[]
   UInt32
   UInt32[]
   UInt64
   UInt64[]
Example
The following example demonstrates how to add and retrieve custom data from a StrokeCollection.
       inkCanvas1.Strokes.AddPropertyData(timestamp, DateTime.Now);
   }
       if (inkCanvas1.Strokes.ContainsPropertyData(timestamp))
       {
           object date = inkCanvas1.Strokes.GetPropertyData(timestamp);
              if (date is DateTime)
              {
                  MessageBox.Show("This StrokeCollection's timestamp is " +
                      ((DateTime)date).ToString());
              }
       }
       else
       {
              MessageBox.Show(
                  "The StrokeCollection does not have a timestamp.");
       }
   }
The following example creates an application that displays an InkCanvas and two buttons. The button,
 switchAuthor , enables two pens to be used by two different authors. The button changePenColors changes the
color of each stroke on the InkCanvas according to the author. The application defines two DrawingAttributes
objects and adds a custom property to each one that indicates which author drew the Stroke. When the user
clicks changePenColors , the application changes the appearance of the stroke according to the value of the
custom property.
<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Adding Custom Data to Ink" Height="500" Width="700"
    >
  <DockPanel Name="root">
    <StackPanel Background="DarkSlateBlue">
      <Button Name="switchAuthor" Click="switchAuthor_click" >
        Switch to student's pen
      </Button>
      <Button Name="changePenColors" Click="changeColor_click" >
        Change the color of the pen ink
      </Button>
    </StackPanel>
    <InkCanvas Name="inkCanvas1">
    </InkCanvas>
  </DockPanel>
</Window>
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;
using   System.Windows.Ink;
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
    public Window1()
    {
        InitializeComponent();
          teachersDA.Color = Colors.Red;
          teachersDA.Width = 5;
          teachersDA.Height = 5;
          teachersDA.AddPropertyData(authorGuid, teacher);
          studentsDA.Color = Colors.Blue;
          studentsDA.Width = 5;
          studentsDA.Height = 5;
          studentsDA.AddPropertyData(authorGuid, student);
          inkCanvas1.DefaultDrawingAttributes = teachersDA;
    }
    // Change the color of the ink that on the InkCanvas that used the pen.
    void changeColor_click(Object sender, RoutedEventArgs e)
    {
        foreach (Stroke s in inkCanvas1.Strokes)
        {
            if (s.DrawingAttributes.ContainsPropertyData(authorGuid))
            {
                object data = s.DrawingAttributes.GetPropertyData(authorGuid);
The IncrementalStrokeHitTester determines whether the currently drawn stroke intersects another stroke. This is
useful for creating a control that enables a user to erase parts of a stroke, the way a user can on an InkCanvas
when the EditingMode is set to EraseByPoint.
Example
The following example creates a custom control that enables the user to erase parts of strokes. This example
creates a control that contains ink when it is initialized. To create a control that collects ink, see Creating an Ink
Input Control.
   using   System.Windows;
   using   System.Windows.Controls;
   using   System.Windows.Ink;
   using   System.Windows.Input;
   using   System.Windows.Media;
   using   System.IO;
InkPresenter presenter;
       string strokesString =
           @"ALwHAxdIEETLgIgERYQBGwIAJAFGhAEbAgAkAQUBOBkgMgkA9P8CAekiOkUzCQD4n"
           + "wIBWiA6RTgIAP4DAAAAgH8RAACAPx8JEQAAAAAAAPA/CiUHh/A6N4HR0AivFX8Vs"
           + "IfsiuyLSaIeDSLwabiHm0GgUDi+KZkACjsQh/A9t4IC5VJpfLhaIxyxXIh7Dncnh"
           + "+6e7qODwoERlPAw8EpGoJAgh61IKjCYXBYDA4DAIHF67KIHAAojB4fwMteBn+RKB"
           + "lziaIfwWTeCwePqbM8WgIeeQCDQOFRvcIAKNA+H8B8XgQHkUbjQTTnGuaZns3l4h"
           + "/DWt4a0YKBBOA94D6HRCAiGnp5CS8LExMLB1tOgYIAKUBOH8KnXhU7lMold+tcbi"
           + "kChkqu2EtPYxp9bmYCH8HDHg4ZhMIwRyMHH+4Jt8nleX8c0/D/AkYwxJGiHkkQgM"
           + "Ch9CqcFhMDQCBwWAwuR2eAACmgdh/EpF4lA6XMUfhMXgMHgVDxBFpRKpZII5EINA"
           + "OA64M+J4Lw1CIoAh/B2x4PS4bQodAopEI5IJBki4waEx2Qy+dy+ayHgleEmmHH8c"
           + "e3MZOCGw5TWd3CwsHAwMCgRAEAgElKwOHZKBApaGIfxezeL0uN02N8IzwaGEpNIJ"
           + "ZxHnELyOj0GfyuU6FgmhplIgIfwYgeDHeaI1vjOtZgcHgHAYb9hUCgEFgsPm1xnM"
           + "ZkYhsnYJgZeZh4uAgCgnSBIOJv4OAgwCmkgh/GrR41X4dGoRJL9EKra5HKY7IZ3C"
           + "4fj/M06olSoU8kkehUbh8jkMdCH8IJXhAXhMCk8JuNlmNyh0YiEumUwn2wMRxyHw"
           + "2TzWmzeb02OzGKxMITwIhnrjzbb44zRhGEKRhCM4zrr6sQKXRWH8kuXkmPj0DiXC"
           + "gcJbC9HZZgkKgUG4bLh3YrwJHAYw2CAh/CiN4Tq7DOZr4BB/AFtdOWW5P2h1Wkzv"
           + "l4+YwqXf8d5fZ7ih51QKbB4LQrLAYDBIDABA4BO4nAICApvIIfy4BeXA2DRSrQlL"
           + "oHHsYQ/KMXlsvl8rn8Xkcdg+G9NVaUWimUDYk9Ah/BoF4M0YBCqZPYqk8dwLf7hD"
           + "YNBJFLKBNqZTqNubWshl9VoM1reFYZYQEBGUsDAwKEjYuDQKBgICBgCAgIOAg4nI"
           + "8OACloSh/BFl4Gf/IOt6FXfF8F4ToPCZzlPwP4+B+DHmQO847rfDeCcG8eKh/EZV"
           + "4i9eZt8A9nUF8VzxaUe5grl7YrPaHfpRKJNx4yHmUuj1vicwmMBEAjUVgKB61A=";
       public InkEraser()
       {
           presenter = new InkPresenter();
           this.Content = presenter;
             if (converter.CanConvertFrom(typeof(string)))
    {
        StrokeCollection newStrokes =
            converter.ConvertFrom(strokesString) as StrokeCollection;
        presenter.Strokes.Clear();
        presenter.Strokes.Add(newStrokes);
    }
}
    InitializeEraserHitTester(points);
}
    if (e.StylusDevice != null)
    {
        return;
    }
Point pt = e.GetPosition(this);
    InitializeEraserHitTester(collectedPoints);
}
    AddPointsToEraserHitTester(points);
}
    if (e.StylusDevice != null)
    {
        return;
    }
    if (e.LeftButton == MouseButtonState.Released)
    {
        return;
    }
Point pt = e.GetPosition(this);
        StopEraseHitTesting(points);
    }
        if (e.StylusDevice != null)
        {
            return;
        }
Point pt = e.GetPosition(this);
        StopEraseHitTesting(collectedPoints);
    }
' This control initializes with ink already on it and allows the
' user to erase the ink with the tablet pen or mouse.
          If converter.CanConvertFrom(GetType(String)) Then
              Dim newStrokes As StrokeCollection = converter.ConvertFrom(strokesString)
              presenter.Strokes.Clear()
              presenter.Strokes.Add(newStrokes)
          End If
End Sub
          MyBase.OnStylusDown(e)
          Dim points As StylusPointCollection = e.GetStylusPoints(Me)
InitializeEraserHitTester(points)
End Sub
InitializeEraserHitTester(collectedPoints)
End Sub
End Sub
AddPointsToEraserHitTester(points)
End Sub
AddPointsToEraserHitTester(collectedPoints)
End Sub
    If eraseTester.IsValid Then
        eraseTester.AddPoints(points)
    End If
End Sub
StopEraseHitTesting(points)
End Sub
MyBase.OnMouseLeftButtonUp(e)
StopEraseHitTesting(collectedPoints)
End Sub
        eraseTester.AddPoints(points)
        RemoveHandler eraseTester.StrokeHit, AddressOf eraseTester_StrokeHit
        eraseTester.EndHitTesting()
End Sub
    End Sub
End Class
       How To: Recognize Application Gestures
       11/21/2022 • 2 minutes to read • Edit Online
The following example demonstrates how to erase ink when a user makes a ScratchOut gesture on an
InkCanvas. This example assumes an InkCanvas, called inkCanvas1 , is declared in the XAML file.
Example
   using   System;
   using   System.Windows;
   using   System.Windows.Controls;
   using   System.Windows.Ink;
   using   System.Collections.ObjectModel;
             if (inkCanvas1.IsGestureRecognizerAvailable)
             {
                 inkCanvas1.EditingMode = InkCanvasEditingMode.InkAndGesture;
                 inkCanvas1.Gesture += new InkCanvasGestureEventHandler(inkCanvas1_Gesture);
                 inkCanvas1.SetEnabledGestures(
                     new ApplicationGesture[] { ApplicationGesture.ScratchOut });
             }
       }
                 if (hitStrokes.Count > 0)
                 {
                     inkCanvas1.Strokes.Remove(hitStrokes);
                 }
             }
       }
   }
 Imports   System.Windows
 Imports   System.Windows.Controls
 Imports   System.Windows.Ink
 Imports   System.Collections.ObjectModel
 Class Window1
     Inherits Window
           If inkCanvas1.IsGestureRecognizerAvailable Then
               inkCanvas1.EditingMode = InkCanvasEditingMode.InkAndGesture
               AddHandler inkCanvas1.Gesture, AddressOf inkCanvas1_Gesture
               inkCanvas1.SetEnabledGestures(New ApplicationGesture() {ApplicationGesture.ScratchOut})
           End If
End Sub
     End Sub
 End Class
See also
 ApplicationGesture
 InkCanvas
 Gesture
      How to: Drag and Drop Ink
      11/21/2022 • 3 minutes to read • Edit Online
Example
The following example creates an application that enables the user to drag selected strokes from one InkCanvas
to the other.
   <Window x:Class="Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="InkDragDropSample" Height="500" Width="700"
       >
     <Grid>
       <Grid.RowDefinitions>
         <RowDefinition Height="Auto"/>
         <RowDefinition Height="*"/>
       </Grid.RowDefinitions>
       <Grid.ColumnDefinitions>
         <ColumnDefinition/>
         <ColumnDefinition/>
       </Grid.ColumnDefinitions>
       <CheckBox Grid.Row="1"
                 Checked="switchToSelect" Unchecked="switchToInk">
         Select Mode
       </CheckBox>
     </Grid>
   </Window>
   using   System;
   using   System.IO;
   using   System.Windows;
   using   System.Windows.Ink;
   using   System.Windows.Controls;
   using   System.Windows.Data;
   using   System.Windows.Input;
   using   System.Windows.Media;
       public Window1()
       {
           InitializeComponent();
       }
Point pt = e.GetPosition(ic);
        DragDropEffects effects =
            DragDrop.DoDragDrop(ic, dataObject,
                                DragDropEffects.Move);
Imports   System.IO
Imports   System.Windows
Imports   System.Windows.Ink
Imports   System.Windows.Controls
Imports   System.Windows.Data
Imports   System.Windows.Input
Imports   System.Windows.Media
Class Window1
    Inherits Window
End Sub
    End Sub
    Private Sub InkCanvas_Drop(ByVal sender As Object, _
                       ByVal e As DragEventArgs)
        ms.Position = 0
        Dim strokes As New StrokeCollection(ms)
        ' Add the strokes to the InkCanvas and keep them selected.
        ic.Strokes.Add(strokes)
        ic.Select(strokes)
End Sub
End Sub
        ic1.EditingMode = InkCanvasEditingMode.Select
        ic2.EditingMode = InkCanvasEditingMode.Select
End Sub
        ic1.EditingMode = InkCanvasEditingMode.Ink
        ic2.EditingMode = InkCanvasEditingMode.Ink
End Sub
End Class
      How to: Data Bind to an InkCanvas
      11/21/2022 • 2 minutes to read • Edit Online
Example
The following example demonstrates how to bind the Strokes property of an InkCanvas to another InkCanvas.
   <InkCanvas Background="LightGray"
              Canvas.Top="0" Canvas.Left="0"
              Height="400" Width="200" Name="ic"/>
   <!-- Bind the Strokes of the second InkCavas to the first InkCanvas
        and mirror the strokes along the Y axis.-->
   <InkCanvas Background="LightBlue"
              Canvas.Top="0" Canvas.Left="200"
              Height="400" Width="200"
              Strokes="{Binding ElementName=ic, Path=Strokes}">
     <InkCanvas.LayoutTransform>
       <ScaleTransform ScaleX="-1" ScaleY="1" />
     </InkCanvas.LayoutTransform>
   </InkCanvas>
The following example demonstrates how to bind the DefaultDrawingAttributes property to a data source.
   <Canvas.Resources>
     <!--Define an array containing some DrawingAttributes.-->
     <x:Array x:Key="MyDrawingAttributes" x:Type="{x:Type DrawingAttributes}">
       <DrawingAttributes Color="Black" FitToCurve="true" Width="3" Height="3"/>
       <DrawingAttributes Color="Blue" FitToCurve="false" Width="5" Height="5"/>
       <DrawingAttributes Color="Red" FitToCurve="true" Width="7" Height="7"/>
     </x:Array>
   <Canvas>
     <Canvas.Resources>
       <!--Define an array containing the InkEditingMode Values.-->
       <x:Array x:Key="MyEditingModes" x:Type="{x:Type InkCanvasEditingMode}">
         <x:Static Member="InkCanvasEditingMode.Ink"/>
         <x:Static Member="InkCanvasEditingMode.Select"/>
         <x:Static Member="InkCanvasEditingMode.EraseByPoint"/>
         <x:Static Member="InkCanvasEditingMode.EraseByStroke"/>
       </x:Array>
       <InkCanvas.LayoutTransform>
         <ScaleTransform ScaleX="-1" ScaleY="1" />
       </InkCanvas.LayoutTransform>
     </InkCanvas>
  <!--Use the array, MyEditingModes, to populate a ListBox-->
  <ListBox Name="lbEditingMode"
           Canvas.Top="0" Canvas.Left="450"
           Height="100" Width="100"
           ItemsSource="{StaticResource MyEditingModes}" />
</Canvas>
      How to: Analyze Ink with Analysis Hints
      11/21/2022 • 5 minutes to read • Edit Online
Example
The following example is an application that uses multiple System.Windows.Ink.AnalysisHintNode objects on a
form that accepts ink input. The application uses the System.Windows.Ink.AnalysisHintNode.Factoid%2A
property to provide context information for each entry on the form. The application uses background analysis to
analyze the ink and clears the form of all ink five seconds after the user stops adding ink.
   <Window x:Class="FormAnalyzer"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="FormAnalyzer"
         SizeToContent="WidthAndHeight"
       >
       <StackPanel Orientation="Vertical">
       <InkCanvas Name="xaml_writingCanvas" Height="500" Width="840"
                  StrokeCollected="RestartAnalysis" >
               <Grid>
                   <Grid.Resources>
                       <Style TargetType="{x:Type Label}">
                            <Setter Property="FontSize" Value="20"/>
                            <Setter Property="FontFamily" Value="Arial"/>
                       </Style>
                   <Grid.ColumnDefinitions>
                       <ColumnDefinition Width="100"></ColumnDefinition>
                       <ColumnDefinition Width="160"></ColumnDefinition>
                       <ColumnDefinition Width="160"></ColumnDefinition>
                       <ColumnDefinition Width="100"></ColumnDefinition>
                       <ColumnDefinition Width="160"></ColumnDefinition>
                       <ColumnDefinition Width="160"></ColumnDefinition>
                   </Grid.ColumnDefinitions>
                   <Grid.RowDefinitions>
                       <RowDefinition Height="100"></RowDefinition>
                       <RowDefinition Height="100"></RowDefinition>
                       <RowDefinition Height="100"></RowDefinition>
                       <RowDefinition Height="100"></RowDefinition>
                       <RowDefinition Height="100"></RowDefinition>
                   </Grid.RowDefinitions>
                  <TextBlock Name="xaml_blockTitle"
                     Grid.Row="0" Grid.Column="1"
                     Grid.ColumnSpan="5"/>
          <TextBlock Name="xaml_blockDirector"
                     Grid.Row="1" Grid.Column="1"
                     Grid.ColumnSpan="5"/>
                  <TextBlock Name="xaml_blockStarring"
                     Grid.Row="2" Grid.Column="1"
                     Grid.ColumnSpan="5"/>
                  <TextBlock Name="xaml_blockRating"
                     Grid.Row="3" Grid.Column="1"
                     Grid.ColumnSpan="2"/>
                  <TextBlock Name="xaml_blockYear"
                     Grid.Row="3" Grid.Column="4"
                     Grid.ColumnSpan="2"/>
                  <TextBlock Name="xaml_blockGenre"
                     Grid.Row="4" Grid.Column="1"
                     Grid.ColumnSpan="5"/>
using   System;
using   System.Windows;
using   System.Windows.Controls;
using   System.Windows.Ink;
using   System.Windows.Threading;
    public FormAnalyzer()
    {
    InitializeComponent();
}
/// <summary>
/// InkCanvas.StrokeCollected event handler. Begins
/// ink analysis and starts the timer to clear the strokes.
/// If five seconds pass without a Stroke being added,
/// the strokes on the InkCanvas will be cleared.
/// </summary>
/// <par    am name="sender">InkCanvas that raises the
/// StrokeCollected event.</param>
/// <param name="args">Contains the event data.</param>
private void RestartAnalysis(object sender,
                InkCanvasStrokeCollectedEventArgs args)
{
          recoText = hintNodeTitle.GetRecognizedString();
          if (recoText != "") xaml_blockTitle.Text = recoText;
          recoText = hintNodeDirector.GetRecognizedString();
          if (recoText != "") xaml_blockDirector.Text = recoText;
          recoText = hintNodeStarring.GetRecognizedString();
          if (recoText != "") xaml_blockStarring.Text = recoText;
          recoText = hintNodeRating.GetRecognizedString();
          if (recoText != "") xaml_blockRating.Text = recoText;
          recoText = hintNodeYear.GetRecognizedString();
          if (recoText != "") xaml_blockYear.Text = recoText;
          recoText = hintNodeGenre.GetRecognizedString();
          if (recoText != "") xaml_blockGenre.Text = recoText;
    }
    //Clear the canvas, but leave the current strokes in the analyzer.
    private void ClearCanvas(object sender, EventArgs args)
    {
        strokeRemovalTimer.Stop();
          xaml_writingCanvas.Strokes.Clear();
    }
}
Imports   System.Windows
Imports   System.Windows.Controls
Imports   System.Windows.Ink
Imports   System.Windows.Threading
Class FormAnalyzer
    Inherits Window
InitializeComponent()
End Sub
End Sub
End Sub
        recoText = hintNodeTitle.GetRecognizedString()
        If recoText <> "" Then
            xaml_blockTitle.Text = recoText
        End If
        recoText = hintNodeDirector.GetRecognizedString()
        If recoText <> "" Then
            xaml_blockDirector.Text = recoText
        End If
        recoText = hintNodeStarring.GetRecognizedString()
        If recoText <> "" Then
            xaml_blockStarring.Text = recoText
        End If
        recoText = hintNodeRating.GetRecognizedString()
        If recoText <> "" Then
            xaml_blockRating.Text = recoText
        End If
        recoText = hintNodeYear.GetRecognizedString()
        If recoText <> "" Then
            xaml_blockYear.Text = recoText
        End If
        recoText = hintNodeGenre.GetRecognizedString()
        If recoText <> "" Then
            xaml_blockGenre.Text = recoText
        End If
End Sub
    'Clear the canvas, but leave the current strokes in the analyzer.
    Private Sub ClearCanvas(ByVal sender As Object, ByVal args As EventArgs)
strokeRemovalTimer.Stop()
xaml_writingCanvas.Strokes.Clear()
    End Sub
End Class
         How to: Rotate Ink
         11/21/2022 • 7 minutes to read • Edit Online
   <Canvas>
      <InkCanvas Name="inkCanvas1" Background="LightBlue"
                 Height="200" Width="200"
                 Canvas.Top="20" Canvas.Left="20" />
   using    System;
   using    System.Windows;
   using    System.Windows.Controls;
   using    System.Windows.Controls.Primitives;
   using    System.Windows.Documents;
   using    System.Windows.Input;
   using    System.Windows.Media;
   using    System.Windows.Shapes;
   using    System.Windows.Ink;
VisualCollection visualChildren;
RotateTransform rotation;
    visualChildren.Add(outline);
    visualChildren.Add(rotateHandle);
    strokeBounds = AdornedStrokes.GetBounds();
}
/// <summary>
/// Draw the rotation handle and the outline of
/// the element.
/// </summary>
/// <param name="finalSize">The final area within the
/// parent that this element should use to arrange
/// itself and its children.</param>
/// <returns>The actual size used. </returns>
protected override Size ArrangeOverride(Size finalSize)
{
    if (strokeBounds.IsEmpty)
    {
        return finalSize;
    }
    if (rotation != null)
    {
        handleRect.Transform(rotation.Value);
    }
    }
/// <summary>
/// Rotates the rectangle representing the
/// strokes' bounds as the user drags the
/// Thumb.
/// </summary>
void rotateHandle_DragDelta(object sender, DragDeltaEventArgs e)
{
    // Find the angle of which to rotate the shape. Use the right
    // triangle that uses the center and the mouse's position
    // as vertices for the hypotenuse.
    if (deltaY.Equals(0))
    {
        return;
    }
    // Convert to degrees.
    angle = angle * 180 / Math.PI;
    if (Double.IsNaN(angle))
    {
        return;
    }
/// <summary>
/// Rotates the strokes to the same angle as outline.
/// </summary>
void rotateHandle_DragCompleted(object sender,
                                DragCompletedEventArgs e)
                                      DragCompletedEventArgs e)
    {
          if (rotation == null)
          {
              return;
          }
          // Redraw rotateHandle.
          this.InvalidateArrange();
    }
    /// <summary>
    /// Gets the strokes of the adorned element
    /// (in this case, an InkPresenter).
    /// </summary>
    private StrokeCollection AdornedStrokes
    {
        get
        {
            return ((InkPresenter)AdornedElement).Strokes;
        }
    }
Imports   System.Windows
Imports   System.Windows.Controls
Imports   System.Windows.Controls.Primitives
Imports   System.Windows.Documents
Imports   System.Windows.Input
Imports   System.Windows.Media
Imports   System.Windows.Shapes
Imports   System.Windows.Ink
    AddHandler rotateHandle.DragDelta, _
        AddressOf rotateHandle_DragDelta
    AddHandler rotateHandle.DragCompleted, _
        AddressOf rotateHandle_DragCompleted
    visualChildren.Add(outline)
    visualChildren.Add(rotateHandle)
strokeBounds = AdornedStrokes.GetBounds()
End Sub
''' <summary>
''' Draw the rotation handle and the outline of
''' the element.
''' </summary>
''' <param name="finalSize">The final area within the
''' parent that this element should use to arrange
''' itself and its children.</param>
''' <returns>The actual size used. </returns>
Protected Overrides Function ArrangeOverride(ByVal finalSize As Size) _
          As Size
    If strokeBounds.IsEmpty Then
        Return finalSize
    End If
    ' Draws the thumb and the rectangle around the strokes.
    rotateHandle.Arrange(handleRect)
    outline.Data = New RectangleGeometry(strokeBounds)
    outline.Data = New RectangleGeometry(strokeBounds)
    outline.Arrange(New Rect(finalSize))
    Return finalSize
''' <summary>
''' Rotates the rectangle representing the
''' strokes' bounds as the user drags the
''' Thumb.
''' </summary>
Private Sub rotateHandle_DragDelta(ByVal sender As Object, _
                           ByVal e As DragDeltaEventArgs)
    'Find the angle of which to rotate the shape. Use the right
    'triangle that uses the center and the mouse's position
    'as vertices for the hypotenuse.
    Dim pos As Point = Mouse.GetPosition(Me)
    If deltaY.Equals(0) Then
        Return
    End If
    If Double.IsNaN(angle) Then
        Return
    End If
End Sub
''' <summary>
''' Rotates the strokes to the same angle as outline.
''' </summary>
Private Sub rotateHandle_DragCompleted(ByVal sender As Object, _
                               ByVal e As DragCompletedEventArgs)
End Sub
       ''' <summary>
       ''' Gets the strokes of the adorned element
       ''' (in this case, an InkPresenter).
       ''' </summary>
       Private ReadOnly Property AdornedStrokes() As StrokeCollection
           Get
               Return CType(AdornedElement, InkPresenter).Strokes
           End Get
       End Property
The following example is a Extensible Application Markup Language (XAML) file that defines an InkPresenter and
populates it with ink. The Window_Loaded event handler adds the custom adorner to the InkPresenter.
   <Window x:Class="Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="Rotating Strokes Adorner" Height="500" Width="500"
       Loaded="Window_Loaded"
       >
     <InkPresenter Name="inkPresenter1" >
       <InkPresenter.Strokes>
         ALMDAwRIEEU1BQE4GSAyCQD0/wIB6SI6RTMJAPifAgFaIDpFOAgA/gMAAACAfxEAAIA/
         HwkRAAAAAAAA8D8KlwE1h/CPd4SB4NA4OicCjcGjcClcDj8Lh8DgUSkUmmU6nUmoUuk
         0ukUCQKVyehz+rzuly+bzORx+BReRQ+RTaRCH8JyXhPbgcPicPh8Pg8Oh0qk1SoVGrV
         Oo0mi0Xi8rm9Xr9Dqc/p87pc/k8XicHicOj1CoVKtVmv1GqUaiUHlYg8el4akXK7m7T
         cSJgQgghEyym5zx6+PACk4dhPwg/fhCbxY8dp4p2tqnqxyvbPO85z1X1aswhvCd94Tq
         55DRUGi4+Tk6OLn4KLkoOejo6ig5KTioOPCD9LlHmrzNxMRCCc3ec8+fe4AKQBmE/Cw
         9+FkPNvlOdkrYsWa+acp3Z8erOIT8JaX4S6+FbFilbHNvvPXNJbFqluxghKc5DkwrVF
         GEEIJ1w5eLKYAKShuF+Dnr4Oa8HVHXNPFFFFho8VFkqsMRYuuvJxiF+F9r4Xx8HFiqs
         FNcirnweDw9+LvvvixdV0+GhONmlj3wjNOcSCEYTnfLy4oA
       </InkPresenter.Strokes>
       </InkPresenter>
   </Window>
void Window_Loaded(object sender, RoutedEventArgs e)
{
    // Add the rotating strokes adorner to the InkPresenter.
    adornerLayer = AdornerLayer.GetAdornerLayer(inkPresenter1);
    adorner = new RotatingStrokesAdorner(inkPresenter1);
    adornerLayer.Add(adorner);
}
adornerLayer.Add(adorner)
End Sub
       Disable the RealTimeStylus for WPF Applications
       11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) has built in support for processing Windows 7 touch input. The
support comes through the tablet platform’s real-time stylus input as OnStylusDown, OnStylusUp, and
OnStylusMove events. Windows 7 also provides multi-touch input as Win32 WM_TOUCH window messages.
These two APIs are mutually exclusive on the same HWND. Enabling touch input via the tablet platform (the
default for WPF applications) disables WM_TOUCH messages. As a result, to use WM_TOUCH to receive touch
messages from a WPF window, you must disable the built-in stylus support in WPF. This is applicable in a
scenario such as a WPF window hosting a component that uses WM_TOUCH.
To disable WPF listening to stylus input, remove any tablet support added by the WPF window.
Example
The following sample code shows how to remove the default tablet platform support by using reflection.
       if (devices.Count > 0)
       {
           // Get the Type of InputManager.
           Type inputManagerType = typeof(System.Windows.Input.InputManager);
           if (stylusLogic != null)
           {
               // Get the type of the stylusLogic returned from the call to StylusLogic.
               Type stylusLogicType = stylusLogic.GetType();
       }
   }
See also
   Intercepting Input from the Stylus
      Drag and Drop
      11/21/2022 • 2 minutes to read • Edit Online
In This Section
Drag and Drop Overview
Data and Data Objects
Walkthrough: Enabling Drag and Drop on a User Control
How-to Topics
Reference
DataFormat
DataObject
DragDrop
DragDropEffects
DragEventHandler
TextDataFormat
Related Sections
       Drag and Drop Overview
       11/21/2022 • 17 minutes to read • Edit Online
This topic provides an overview of drag-and-drop support in user interface (UI), and dropping them.
  IMPORTANT
  OLE drag-and-drop does not work while in the Internet zone.
Data Transfer
Drag-and-drop is part of the more general area of data transfer. Data transfer includes drag-and-drop and copy-
and-paste operations. A drag-and-drop operation is analogous to a copy-and-paste or cut-and-paste operation
that is used to transfer data from one object or application to another by using the system clipboard. Both types
of operations require:
   A source object that provides the data.
   A way to temporarily store the transferred data.
   A target object that receives the data.
In a copy-and-paste operation, the system clipboard is used to temporarily store the transferred data; in a drag-
and-drop operation, a DataObject is used to store the data. Conceptually, a data object consists of one or more
pairs of an Object that contains the actual data, and a corresponding data format identifier.
The drag source initiates a drag-and-drop operation by calling the static DragDrop.DoDragDrop method and
passing the transferred data to it. The DoDragDrop method will automatically wrap the data in a DataObject if
necessary. For greater control over the data format, you can wrap the data in a DataObject before passing it to
the DoDragDrop method. The drop target is responsible for extracting the data from the DataObject. For more
information about working with data objects, see Data and Data Objects.
The source and target of a drag-and-drop operation are UI elements; however, the data that is actually being
transferred typically does not have a visual representation. You can write code to provide a visual representation
of the data that is dragged, such as occurs when dragging files in Windows Explorer. By default, feedback is
provided to the user by changing the cursor to represent the effect that the drag-and-drop operation will have
on the data, such as whether the data will be moved or copied.
Drag-and-Drop Effects
Drag-and-drop operations can have different effects on the transferred data. For example, you can copy the data
or you can move the data. WPF defines a DragDropEffects enumeration that you can use to specify the effect of
a drag-and-drop operation. In the drag source, you can specify the effects that the source will allow in the
DoDragDrop method. In the drop target, you can specify the effect that the target intends in the Effects property
of the DragEventArgs class. When the drop target specifies its intended effect in the DragOver event, that
information is passed back to the drag source in the GiveFeedback event. The drag source uses this information
to inform the user what effect the drop target intends to have on the data. When the data is dropped, the drop
target specifies its actual effect in the Drop event. That information is passed back to the drag source as the
return value of the DoDragDrop method. If the drop target returns an effect that is not in the drag sources list of
 allowedEffects , the drag-and-drop operation is cancelled without any data transfer occurring.
It is important to remember that in WPF, the DragDropEffects values are only used to provide communication
between the drag source and the drop target regarding the effects of the drag-and-drop operation. The actual
effect of the drag-and-drop operation depends on you to write the appropriate code in your application.
For example, the drop target might specify that the effect of dropping data on it is to move the data. However, to
move the data, it must be both added to the target element and removed from the source element. The source
element might indicate that it allows moving the data, but if you do not provide the code to remove the data
from the source element, the end result will be that the data is copied, and not moved.
Drag-and-Drop Events
Drag-and-drop operations support an event driven model. Both the drag source and the drop target use a
standard set of events to handle drag-and-drop operations. The following tables summarize the standard drag-
and-drop events. These are attached events on the DragDrop class. For more information about attached events,
see Attached Events Overview.
Drag Source Events
  EVEN T                                                     SUM M A RY
  DragEnter                                                 This event occurs when an object is dragged into the drop
                                                            target's boundary. This is a bubbling event.
  DragLeave                                                 This event occurs when an object is dragged out of the drop
                                                            target's boundary. This is a bubbling event.
To handle drag-and-drop events for instances of an object, add handlers for the events listed in the preceding
tables. To handle drag-and-drop events at the class level, override the corresponding virtual On*Event and
On*PreviewEvent methods. For more information, see Class Handling of Routed Events by Control Base Classes.
Implementing Drag-and-Drop
A UI element can be a drag source, a drop target, or both. To implement basic drag-and-drop, you write code to
initiate the drag-and-drop operation and to process the dropped data. You can enhance the drag-and-drop
experience by handling optional drag-and-drop events.
To implement basic drag-and-drop, you will complete the following tasks:
   Identify the element that will be a drag source. A drag source can be a UIElement or a ContentElement.
   Create an event handler on the drag source that will initiate the drag-and-drop operation. The event is
   typically the MouseMove event.
   In the drag source event handler, call the DoDragDrop method to initiate the drag-and-drop operation. In
   the DoDragDrop call, specify the drag source, the data to be transferred, and the allowed effects.
   Identify the element that will be a drop target. A drop target can be UIElement or a ContentElement.
   On the drop target, set the AllowDrop property to   true   .
   In the drop target, create a Drop event handler to process the dropped data.
   In the Drop event handler, extract the data from the DragEventArgs by using the GetDataPresent and
   GetData methods.
   In the Drop event handler, use the data to perform the desired drag-and-drop operation.
You can enhance your drag-and-drop implementation by creating a custom DataObject and by handling
optional drag source and drop target events, as shown in the following tasks:
   To transfer custom data or multiple data items, create a DataObject to pass to the DoDragDrop method.
   To perform additional actions during a drag, handle the DragEnter, DragOver, and DragLeave events on
   the drop target.
   To change the appearance of the mouse pointer, handle the GiveFeedback event on the drag source.
   To change how the drag-and-drop operation is canceled, handle the QueryContinueDrag event on the
   drag source.
Drag-and-Drop Example
This section describes how to implement drag-and-drop for an Ellipse element. The Ellipse is both a drag source
and a drop target. The transferred data is the string representation of the ellipse’s Fill property. The following
XAML shows the Ellipse element and the drag-and-drop related events that it handles. For complete steps on
how to implement drag-and-drop, see Walkthrough: Enabling Drag and Drop on a User Control.
Inside of the MouseMove event handler, call the DoDragDrop method to initiate the drag-and-drop operation.
The DoDragDrop method takes three parameters:
    dragSource   – A reference to the dependency object that is the source of the transferred data; this is
   typically the source of the MouseMove event.
    data   - An object that contains the transferred data, wrapped in a DataObject.
    allowedEffects- One of the DragDropEffects enumeration values that specifies the permitted effects of
   the drag-and-drop operation.
Any serializable object can be passed in the data parameter. If the data is not already wrapped in a DataObject,
it will automatically be wrapped in a new DataObject. To pass multiple data items, you must create the
DataObject yourself, and pass it to the DoDragDrop method. For more information, see Data and Data Objects.
The allowedEffects parameter is used to specify what the drag source will allow the drop target to do with the
transferred data. The common values for a drag source are Copy, Move, and All.
  NOTE
  The drop target is also able to specify what effects it intends in response to the dropped data. For example, if the drop
  target does not recognize the data type to be dropped, it can refuse the data by setting its allowed effects to None. It
  typically does this in its DragOver event handler.
A drag source can optionally handle the GiveFeedback and QueryContinueDrag events. These events have
default handlers that are used unless you mark the events as handled. You will typically ignore these events
unless you have a specific need to change their default behavior.
The GiveFeedback event is raised continuously while the drag source is being dragged. The default handler for
this event checks whether the drag source is over a valid drop target. If it is, it checks the allowed effects of the
drop target. It then gives feedback to the end user regarding the allowed drop effects. This is typically done by
changing the mouse cursor to a no-drop, copy, or move cursor. You should only handle this event if you need to
use custom cursors to provide feedback to the user. If you handle this event, be sure to mark it as handled so
that the default handler does not override your handler.
The QueryContinueDrag event is raised continuously while the drag source is being dragged. You can handle
this event to determine what action ends the drag-and-drop operation based on the state of the ESC, SHIFT,
CTRL, and ALT keys, as well as the state of the mouse buttons. The default handler for this event cancels the
drag-and-drop operation if the ESC key is pressed, and drops the data if the mouse button is released.
Cau t i on
These events are raised continuously during the drag-and-drop operation. Therefore, you should avoid
resource-intensive tasks in the event handlers. For example, use a cached cursor instead of creating a new
cursor each time the GiveFeedback event is raised.
Enabling an Element to be a Drop Target
An object that is a drop target is responsible for:
     Specifying that it is a valid drop target.
     Responding to the drag source when it drags over the target.
     Checking that the transferred data is in a format that it can receive.
     Processing the dropped data.
To specify that an element is a drop target, you set its AllowDrop property to true . The drop target events will
then be raised on the element so that you can handle them. During a drag-and-drop operation, the following
sequence of events occurs on the drop target:
1. DragEnter
2. DragOver
3. DragLeave or Drop
The DragEnter event occurs when the data is dragged into the drop target's boundary. You typically handle this
event to provide a preview of the effects of the drag-and-drop operation, if appropriate for your application. Do
not set the DragEventArgs.Effects property in the DragEnter event, as it will be overwritten in the DragOver
event.
The following example shows the DragEnter event handler for an Ellipse element. This code previews the effects
of the drag-and-drop operation by saving the current Fill brush. It then uses the GetDataPresent method to
check whether the DataObject being dragged over the ellipse contains string data that can be converted to a
Brush. If so, the data is extracted using the GetData method. It is then converted to a Brush and applied to the
ellipse. The change is reverted in the DragLeave event handler. If the data cannot be converted to a Brush, no
action is performed.
   private Brush _previousFill = null;
   private void ellipse_DragEnter(object sender, DragEventArgs e)
   {
       Ellipse ellipse = sender as Ellipse;
       if (ellipse != null)
       {
           // Save the current Fill brush so that you can revert back to this value in DragLeave.
           _previousFill = ellipse.Fill;
The DragOver event occurs continuously while the data is dragged over the drop target. This event is paired
with the GiveFeedback event on the drag source. In the DragOver event handler, you typically use the
GetDataPresent and GetData methods to check whether the transferred data is in a format that the drop target
can process. You can also check whether any modifier keys are pressed, which will typically indicate whether the
user intends a move or copy action. After these checks are performed, you set the DragEventArgs.Effects
property to notify the drag source what effect dropping the data will have. The drag source receives this
information in the GiveFeedback event args, and can set an appropriate cursor to give feedback to the user.
The following example shows the DragOver event handler for an Ellipse element. This code checks to see if the
DataObject being dragged over the ellipse contains string data that can be converted to a Brush. If so, it sets the
DragEventArgs.Effects property to Copy. This indicates to the drag source that the data can be copied to the
ellipse. If the data cannot be converted to a Brush, the DragEventArgs.Effects property is set to None. This
indicates to the drag source that the ellipse is not a valid drop target for the data.
   private void ellipse_DragOver(object sender, DragEventArgs e)
   {
       e.Effects = DragDropEffects.None;
The DragLeave event occurs when the data is dragged out of the target's boundary without being dropped. You
handle this event to undo anything that you did in the DragEnter event handler.
The following example shows the DragLeave event handler for an Ellipse element. This code undoes the preview
performed in the DragEnter event handler by applying the saved Brush to the ellipse.
The Drop event occurs when the data is dropped over the drop target; by default, this happens when the mouse
button is released. In the Drop event handler, you use the GetData method to extract the transferred data from
the DataObject and perform any data processing that your application requires. The Drop event ends the drag-
and-drop operation.
The following example shows the Drop event handler for an Ellipse element. This code applies the effects of the
drag-and-drop operation, and is similar to the code in the DragEnter event handler. It checks to see if the
DataObject being dragged over the ellipse contains string data that can be converted to a Brush. If so, the Brush
is applied to the ellipse. If the data cannot be converted to a Brush, no action is performed.
See also
   Clipboard
   Walkthrough: Enabling Drag and Drop on a User Control
   How-to Topics
   Drag and Drop
        Data and Data Objects
        11/21/2022 • 8 minutes to read • Edit Online
Data that is transferred as part of a drag-and-drop operation is stored in a data object. Conceptually, a data
object consists of one or more of the following pairs:
   An Object that contains the actual data.
   A corresponding data format identifier.
The data itself can consist of anything that can be represented as a base Object. The corresponding data format
is a string or Type that provides a hint about what format the data is in. Data objects support hosting multiple
data/data format pairs; this enables a single data object to provide data in multiple formats.
Data Objects
All data objects must implement the IDataObject interface, which provides the following standard set of
methods that enable and facilitate data transfer.
M ET H O D SUM M A RY
  GetFormats                                                 Returns a list of formats that the data in this data object is
                                                             stored in, or can be converted to.
WPF provides a basic implementation of IDataObject in the DataObject class. The stock DataObject class is
sufficient for many common data transfer scenarios.
There are several pre-defined formats, such as bitmap, CSV, file, HTML, RTF, string, text, and audio. For
information about pre-defined data formats provided with WPF, see the DataFormats class reference topic.
Data objects commonly include a facility for automatically converting data stored in one format to a different
format while extracting data; this facility is referred to as auto-convert. When querying for the data formats
available in a data object, auto-convertible data formats can be filtered from native data formats by calling the
GetFormats(Boolean) or GetDataPresent(String, Boolean) method and specifying the autoConvert parameter as
 false . When adding data to a data object with the SetData(String, Object, Boolean) method, auto-conversion of
data can be prohibited by setting the autoConvert parameter to false .
For more examples of code that creates a data object, see Create a Data Object.
Storing Data in Multiple Formats
A single data object is able to store data in multiple formats. Strategic use of multiple data formats within a
single data object potentially makes the data object consumable by a wider variety of drop targets than if only a
single data format could be represented. Note that, in general, a drag source must be agnostic about the data
formats that are consumable by potential drop targets.
The following example shows how to use the SetData(String, Object) method to add data to a data object in
multiple formats.
   // The DataFormats class does not provide data format fields for denoting
   // UTF-32 and UTF-8, which are seldom used in practice; the following strings
   // will be used to identify these "custom" data formats.
   string utf32DataFormat = "UTF-32";
   string utf8DataFormat = "UTF-8";
   // Store the text in the data object, letting the data object choose
   // the data format (which will be DataFormats.Text in this case).
   dataObject.SetData(sourceData);
   // Store the Unicode text in the data object. Text data can be automatically
   // converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object;
   // Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
   // is done here as an exercise only.
   dataObject.SetData(DataFormats.UnicodeText, unicodeText);
   // Store the UTF-8 text in the data object...
   dataObject.SetData(utf8DataFormat, utf8Text);
   // Store the UTF-32 text in the data object...
   dataObject.SetData(utf32DataFormat, utf32Text);
   Dim dataObject As New DataObject()
   Dim sourceData As String = "Some string data to store..."
   ' The DataFormats class does not provide data format fields for denoting
   ' UTF-32 and UTF-8, which are seldom used in practice; the following strings
   ' will be used to identify these "custom" data formats.
   Dim utf32DataFormat As String = "UTF-32"
   Dim utf8DataFormat As String = "UTF-8"
   ' Store the text in the data object, letting the data object choose
   ' the data format (which will be DataFormats.Text in this case).
   dataObject.SetData(sourceData)
   ' Store the Unicode text in the data object. Text data can be automatically
   ' converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object;
   ' Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
   ' is done here as an exercise only.
   dataObject.SetData(DataFormats.UnicodeText, unicodeText)
   ' Store the UTF-8 text in the data object...
   dataObject.SetData(utf8DataFormat, utf8Text)
   ' Store the UTF-32 text in the data object...
   dataObject.SetData(utf32DataFormat, utf32Text)
   // Get the number of data formats present in the data object, including both
   // auto-convertible and native data formats.
   int numberOfDataFormats = dataFormats.Length;
   // To enumerate the resulting array of data formats, and take some action when
   // a particular data format is found, use a code structure similar to the following.
   foreach (string dataFormat in dataFormats)
   {
       if (dataFormat == DataFormats.Text)
       {
           // Take some action if/when data in the Text data format is found.
           break;
       }
       else if(dataFormat == DataFormats.StringFormat)
       {
           // Take some action if/when data in the string data format is found.
           break;
       }
   }
   Dim dataObject As New DataObject("Some string data to store...")
   ' Get the number of data formats present in the data object, including both
   ' auto-convertible and native data formats.
   Dim numberOfDataFormats As Integer = dataFormats.Length
   ' To enumerate the resulting array of data formats, and take some action when
   ' a particular data format is found, use a code structure similar to the following.
   For Each dataFormat As String In dataFormats
       If dataFormat = System.Windows.DataFormats.Text Then
           ' Take some action if/when data in the Text data format is found.
           Exit For
       ElseIf dataFormat = System.Windows.DataFormats.StringFormat Then
           ' Take some action if/when data in the string data format is found.
           Exit For
       End If
   Next dataFormat
For more examples of code that queries a data object for available data formats, see List the Data Formats in a
Data Object. For examples of querying a data object for the presence of a particular data format, see Determine
if a Data Format is Present in a Data Object.
Retrieving Data from a Data Object
Retrieving data from a data object in a particular format simply involves calling one of the GetData methods and
specifying the desired data format. One of the GetDataPresent methods can be used to check for the presence of
a particular data format. GetData returns the data in an Object; depending on the data format, this object can be
cast to a type-specific container.
The following example code uses the GetDataPresent(String) overload to check if a specified data format is
available (native or by auto-convert). If the specified format is available, the example retrieves the data by using
the GetData(String) method.
   //   Use the GetDataPresent method to check for the presence of a desired data format.
   //   This particular overload of GetDataPresent looks for both native and auto-convertible
   //   data formats.
   if   (dataObject.GetDataPresent(desiredFormat))
   {
         // If the desired data format is present, use one of the GetData methods to retrieve the
         // data from the data object.
         data = dataObject.GetData(desiredFormat) as byte[];
   }
   Dim dataObject As New DataObject("Some string data to store...")
   ' Use the GetDataPresent method to check for the presence of a desired data format.
   ' This particular overload of GetDataPresent looks for both native and auto-convertible
   ' data formats.
   If dataObject.GetDataPresent(desiredFormat) Then
       ' If the desired data format is present, use one of the GetData methods to retrieve the
       ' data from the data object.
       data = TryCast(dataObject.GetData(desiredFormat), Byte())
   End If
For more examples of code that retrieves data from a data object, see Retrieve Data in a Particular Data Format.
Removing Data From a Data Object
Data cannot be directly removed from a data object. To effectively remove data from a data object, follow these
steps:
1. Create a new data object that will contain only the data you want to retain.
2. "Copy" the desired data from the old data object to the new data object. To copy the data, use one of the
   GetData methods to retrieve an Object that contains the raw data, and then use one of the SetData
   methods to add the data to the new data object.
3. Replace the old data object with the new one.
  NOTE
  The SetData methods only add data to a data object; they do not replace data, even if the data and data format are
  exactly the same as a previous call. Calling SetData twice for the same data and data format will result in the data/data
  format being present twice in the data object.
       Walkthrough: Enabling Drag and Drop on a User
       Control
       11/21/2022 • 17 minutes to read • Edit Online
This walkthrough demonstrates how to create a custom user control that can participate in drag-and-drop data
transfer in Windows Presentation Foundation (WPF).
In this walkthrough, you will create a custom WPF UserControl that represents a circle shape. You will
implement functionality on the control to enable data transfer through drag-and-drop. For example, if you drag
from one Circle control to another, the Fill color data is copied from the source Circle to the target. If you drag
from a Circle control to a TextBox, the string representation of the Fill color is copied to the TextBox. You will also
create a small application that contains two panel controls and a TextBox to test the drag-and-drop functionality.
You will write code that enables the panels to process dropped Circle data, which will enable you to move or
copy Circles from the Children collection of one panel to the other.
This walkthrough illustrates the following tasks:
   Create a custom user control.
   Enable the user control to be a drag source.
   Enable the user control to be a drop target.
   Enable a panel to receive data dropped from the user control.
Prerequisites
You need Visual Studio to complete this walkthrough.
      <Ellipse x:Name="circleUI"
               Height="100" Width="100"
               Fill="Blue" />
      public Circle(Circle c)
      {
          InitializeComponent();
          this.circleUI.Height = c.circleUI.Height;
          this.circleUI.Width = c.circleUI.Height;
          this.circleUI.Fill = c.circleUI.Fill;
      }
      Public Sub New()
          ' This call is required by the designer.
          InitializeComponent()
      End Sub
xmlns:local="clr-namespace:DragDropExample"
3. In the first StackPanel, add the following XAML to create two instances of the Circle user control in the
   first panel.
The full XAML for the panel looks like the following.
      <StackPanel Grid.Column="0"
                  Background="Beige">
          <TextBox Width="Auto" Margin="2"
                    Text="green"/>
          <local:Circle Margin="2" />
          <local:Circle Margin="2" />
      </StackPanel>
      <StackPanel Grid.Column="1"
                  Background="Bisque">
      </StackPanel>
      <UserControl x:Class="DragDropWalkthrough.Circle"
                   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                   mc:Ignorable="d"
                   d:DesignHeight="300" d:DesignWidth="300"
                   AllowDrop="True">
The OnDrop method is called when the AllowDrop property is set to true and data from the drag source is
dropped on the Circle user control. In this method, you will process the data that was dropped and apply the
data to the Circle.
To process the dropped data
1. Open Circle.xaml.cs or Circle.xaml.vb.
2. Add the following OnDrop override to provide class handling for the Drop event.
   protected override void OnDrop(DragEventArgs e)
   {
       base.OnDrop(e);
           ' If the string can be converted into a Brush, allow copying or moving.
           Dim converter As New BrushConverter
           If converter.IsValid(dataString) Then
               ' Set Effects to notify the drag source what effect
               ' the drag-and-drop operation will have. These values are
               ' used by the drag source's GiveFeedback event handler.
               ' (Copy if CTRL is pressed; otherwise, move.)
               If e.KeyStates.HasFlag(DragDropKeyStates.ControlKey) Then
                    e.Effects = DragDropEffects.Copy
               Else
                    e.Effects = DragDropEffects.Move
               End If
           End If
       End If
       e.Handled = True
   End Sub
3. Add the following OnDragEnter override to provide class handling for the DragEnter event.
   By default, the panels aren't drop targets. To enable them, add the AllowDrop property to both panels and
   set the value to true .
      <StackPanel Grid.Column="0"
                  Background="Beige"
                  AllowDrop="True"
                  DragOver="panel_DragOver"
                  Drop="panel_Drop">
          <TextBox Width="Auto" Margin="2"
                    Text="green"/>
          <local:Circle Margin="2" />
          <local:Circle Margin="2" />
      </StackPanel>
      <StackPanel Grid.Column="1"
                  Background="Bisque"
                  AllowDrop="True"
                  DragOver="panel_DragOver"
                  Drop="panel_Drop">
      </StackPanel>
            if (_parent != null)
            {
                if (e.KeyStates == DragDropKeyStates.ControlKey &&
                    e.AllowedEffects.HasFlag(DragDropEffects.Copy))
                {
                    Circle _circle = new Circle((Circle)_element);
                    _panel.Children.Add(_circle);
                    // set the value to return to the DoDragDrop call
                    e.Effects = DragDropEffects.Copy;
                }
                else if (e.AllowedEffects.HasFlag(DragDropEffects.Move))
                {
                    _parent.Children.Remove(_element);
                    _panel.Children.Add(_element);
                    // set the value to return to the DoDragDrop call
                    e.Effects = DragDropEffects.Move;
                }
            }
        }
    }
}
       Private Sub panel_Drop(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
           ' If an element in the panel has already handled the drop,
           ' the panel should not also handle it.
           If e.Handled = False Then
               Dim _panel As Panel = sender
               Dim _element As UIElement = e.Data.GetData("Object")
The following examples demonstrate how to accomplish common tasks using the Windows Presentation
Foundation (WPF) drag-and-drop framework.
In This Section
Open a File That is Dropped on a RichTextBox Control
Create a Data Object
Determine if a Data Format is Present in a Data Object
List the Data Formats in a Data Object
Retrieve Data in a Particular Data Format
Store Multiple Data Formats in a Data Object
See also
   Drag and Drop Overview
       How to: Open a File That is Dropped on a
       RichTextBox Control
       11/21/2022 • 2 minutes to read • Edit Online
In Windows Presentation Foundation (WPF), the TextBox, RichTextBox, and FlowDocument controls all have built-
in drag-and-drop functionality. The built-in functionality enables drag-and-drop of text within and between the
controls. However, it does not enable opening a file by dropping the file on the control. These controls also mark
the drag-and-drop events as handled. As a result, by default, you cannot add your own event handlers to
provide functionality to open dropped files.
To add additional handling for drag-and-drop events in these controls, use the AddHandler(RoutedEvent,
Delegate, Boolean) method to add your event handlers for the drag-and-drop events. Set the handledEventsToo
parameter to true to have the specified handler be invoked for a routed event that has already been marked as
handled by another element along the event route.
  TIP
  You can replace the built-in drag-and-drop functionality of TextBox, RichTextBox, and FlowDocument by handling the
  preview versions of the drag-and-drop events and marking the preview events as handled. However, this will disable the
  built-in drag-and-drop functionality, and is not recommended.
Example
The following example demonstrates how to add handlers for the DragOver and Drop events on a RichTextBox.
This example uses the AddHandler(RoutedEvent, Delegate, Boolean) method and sets the handledEventsToo
parameter to true so that the events handlers will be invoked even though the RichTextBox marks these events
as handled. The code in the event handlers adds functionality to open a text file that is dropped on the
RichTextBox.
To test this example, drag a text file or a rich text format (RTF) file from Windows Explorer to the RichTextBox. The
file will be opened in the RichTextBox. If you press the SHIFT key before the dropping the file, the file will be
opened as plain text.
   <RichTextBox x:Name="richTextBox1"
                AllowDrop="True" />
public MainWindow()
{
    InitializeComponent();
        System.Windows.Documents.TextRange range;
        System.IO.FileStream fStream;
        if (System.IO.File.Exists(docPath[0]))
        {
            try
            {
                // Open the document in the RichTextBox.
                range = new System.Windows.Documents.TextRange(richTextBox1.Document.ContentStart,
richTextBox1.Document.ContentEnd);
                fStream = new System.IO.FileStream(docPath[0], System.IO.FileMode.OpenOrCreate);
                range.Load(fStream, dataFormat);
                fStream.Close();
            }
            catch (System.Exception)
            {
                MessageBox.Show("File could not be opened. Make sure the file is a text file.");
            }
        }
    }
}
Public Sub New()
    InitializeComponent()
End Sub
The following examples show various ways to create a data object using the constructors provided by the
DataObject class.
DataObject(Object) constructor
Description
The following example code creates a new data object and uses one of the overloaded constructors
(DataObject(Object)) to initialize the data object with a string. In this case, an appropriate data format is
determined automatically according to the stored data's type, and auto-converting of the stored data is allowed
by default.
Code
Description
The following example code is a condensed version of the code shown above.
Code
Description
The following example code is a condensed version of the code shown above.
Code
DataObject() constructor
Description
The following example code creates a new data object and uses one of the overloaded constructors (DataObject)
to initialize the data object with a string and a specified data format. In this case the data format is specified by a
Type parameter. Auto-converting of the stored data is allowed by default.
Code
Description
The following example code is a condensed version of the code shown above.
Code
Description
The following example code is a condensed version of the code shown above.
Code
See also
   IDataObject
       How to: Determine if a Data Format is Present in a
       Data Object
       11/21/2022 • 4 minutes to read • Edit Online
The following examples show how to use the various GetDataPresent method overloads to query whether a
particular data format is present in a data object.
GetDataPresent(String) overload
Description
The following example code uses the GetDataPresent(String) overload to query for the presence of a particular
data format by descriptor string.
Code
   // Query for the presence of Text data in the data object, by a data format descriptor string.
   // In this overload of GetDataPresent, the method will return true both for native data formats
   // and when the data can automatically be converted to the specifed format.
   // In this case, the Text data in the data object can be autoconverted to
   // Unicode text, so GetDataPresent returns "true".
   byte[] unicodeData = null;
   if (dataObject.GetDataPresent(DataFormats.UnicodeText))
   {
       unicodeData = dataObject.GetData(DataFormats.UnicodeText) as byte[];
   }
   ' Query for the presence of Text data in the data object, by a data format descriptor string.
   ' In this overload of GetDataPresent, the method will return true both for native data formats
   ' and when the data can automatically be converted to the specifed format.
   ' In this case, string data is present natively, so GetDataPresent returns "true".
   Dim textData As String = Nothing
   If dataObject.GetDataPresent(DataFormats.StringFormat) Then
       textData = TryCast(dataObject.GetData(DataFormats.StringFormat), String)
   End If
   ' In this case, the Text data in the data object can be autoconverted to
   ' Unicode text, so GetDataPresent returns "true".
   Dim unicodeData() As Byte = Nothing
   If dataObject.GetDataPresent(DataFormats.UnicodeText) Then
       unicodeData = TryCast(dataObject.GetData(DataFormats.UnicodeText), Byte())
   End If
GetDataPresent(Type) overload
Description
The following example code uses the GetDataPresent(Type) overload to query for the presence of a particular
data format by type.
Code
   // Query for the presence of String data in the data object, by type. In this overload
   // of GetDataPresent, the method will return true both for native data formats
   // and when the data can automatically be converted to the specifed format.
   // In this case, the Text data present in the data object can be autoconverted
   // to type string (also represented by DataFormats.String), so GetDataPresent returns "true".
   string stringData = null;
   if (dataObject.GetDataPresent(typeof(string)))
   {
       stringData = dataObject.GetData(DataFormats.Text) as string;
   }
   ' Query for the presence of String data in the data object, by type. In this overload
   ' of GetDataPresent, the method will return true both for native data formats
   ' and when the data can automatically be converted to the specifed format.
   ' In this case, the Text data present in the data object can be autoconverted
   ' to type string (also represented by DataFormats.String), so GetDataPresent returns "true".
   Dim stringData As String = Nothing
   If dataObject.GetDataPresent(GetType(String)) Then
       stringData = TryCast(dataObject.GetData(DataFormats.Text), String)
   End If
 // Query for the presence of Text data in the data object, by data format descriptor string,
 // and specifying whether auto-convertible data formats are acceptable.
 // In this case, the Text data in the data object can be autoconverted to
 // Unicode text, but it is not available natively, so GetDataPresent returns "false".
 byte[] unicodeData = null;
 if (dataObject.GetDataPresent(DataFormats.UnicodeText, false /* Auto-convert? */))
 {
     unicodeData = dataObject.GetData(DataFormats.UnicodeText) as byte[];
 }
 // In this case, the Text data in the data object can be autoconverted to
 // Unicode text, so GetDataPresent returns "true".
 if (dataObject.GetDataPresent(DataFormats.UnicodeText, true /* Auto-convert? */))
 {
     unicodeData = dataObject.GetData(DataFormats.UnicodeText) as byte[];
 }
 ' Query for the presence of Text data in the data object, by data format descriptor string,
 ' and specifying whether auto-convertible data formats are acceptable.
 ' In this case, Text data is present natively, so GetDataPresent returns "true".
 Dim textData As String = Nothing
 If dataObject.GetDataPresent(DataFormats.Text, False) Then ' Auto-convert?
     textData = TryCast(dataObject.GetData(DataFormats.Text), String)
 End If
 ' In this case, the Text data in the data object can be autoconverted to
 ' Unicode text, but it is not available natively, so GetDataPresent returns "false".
 Dim unicodeData() As Byte = Nothing
 If dataObject.GetDataPresent(DataFormats.UnicodeText, False) Then ' Auto-convert?
     unicodeData = TryCast(dataObject.GetData(DataFormats.UnicodeText), Byte())
 End If
 ' In this case, the Text data in the data object can be autoconverted to
 ' Unicode text, so GetDataPresent returns "true".
 If dataObject.GetDataPresent(DataFormats.UnicodeText, True) Then ' Auto-convert?
     unicodeData = TryCast(dataObject.GetData(DataFormats.UnicodeText), Byte())
 End If
See also
 IDataObject
       How to: List the Data Formats in a Data Object
       11/21/2022 • 3 minutes to read • Edit Online
The following examples show how to use the GetFormats method overloads get an array of strings denoting
each data format that is available in a data object.
   // Get the number of data formats present in the data object, including both
   // auto-convertible and native data formats.
   int numberOfDataFormats = dataFormats.Length;
   // To enumerate the resulting array of data formats, and take some action when
   // a particular data format is found, use a code structure similar to the following.
   foreach (string dataFormat in dataFormats)
   {
       if (dataFormat == DataFormats.Text)
       {
           // Take some action if/when data in the Text data format is found.
           break;
       }
       else if(dataFormat == DataFormats.StringFormat)
       {
           // Take some action if/when data in the string data format is found.
           break;
       }
   }
   Dim dataObject As New DataObject("Some string data to store...")
   ' Get the number of data formats present in the data object, including both
   ' auto-convertible and native data formats.
   Dim numberOfDataFormats As Integer = dataFormats.Length
   ' To enumerate the resulting array of data formats, and take some action when
   ' a particular data format is found, use a code structure similar to the following.
   For Each dataFormat As String In dataFormats
       If dataFormat = System.Windows.DataFormats.Text Then
           ' Take some action if/when data in the Text data format is found.
           Exit For
       ElseIf dataFormat = System.Windows.DataFormats.StringFormat Then
           ' Take some action if/when data in the string data format is found.
           Exit For
       End If
   Next dataFormat
   // Get the number of native data formats present in the data object.
   int numberOfDataFormats = dataFormats.Length;
   // To enumerate the resulting array of data formats, and take some action when
   // a particular data format is found, use a code structure similar to the following.
   foreach (string dataFormat in dataFormats)
   {
       if (dataFormat == DataFormats.Text)
       {
           // Take some action if/when data in the Text data format is found.
           break;
       }
   }
 Dim dataObject As New DataObject("Some string data to store...")
 ' Get the number of native data formats present in the data object.
 Dim numberOfDataFormats As Integer = dataFormats.Length
 ' To enumerate the resulting array of data formats, and take some action when
 ' a particular data format is found, use a code structure similar to the following.
 For Each dataFormat As String In dataFormats
     If dataFormat = System.Windows.DataFormats.Text Then
         ' Take some action if/when data in the Text data format is found.
         Exit For
     End If
 Next dataFormat
See also
 IDataObject
 Drag and Drop Overview
        How to: Retrieve Data in a Particular Data Format
        11/21/2022 • 2 minutes to read • Edit Online
The following examples show how to retrieve data from a data object in a specified format.
   //   Use the GetDataPresent method to check for the presence of a desired data format.
   //   This particular overload of GetDataPresent looks for both native and auto-convertible
   //   data formats.
   if   (dataObject.GetDataPresent(desiredFormat))
   {
         // If the desired data format is present, use one of the GetData methods to retrieve the
         // data from the data object.
         data = dataObject.GetData(desiredFormat) as byte[];
   }
   ' Use the GetDataPresent method to check for the presence of a desired data format.
   ' This particular overload of GetDataPresent looks for both native and auto-convertible
   ' data formats.
   If dataObject.GetDataPresent(desiredFormat) Then
       ' If the desired data format is present, use one of the GetData methods to retrieve the
       ' data from the data object.
       data = TryCast(dataObject.GetData(desiredFormat), Byte())
   End If
 //   Use the GetDataPresent method to check for the presence of a desired data format.
 //   The autoconvert parameter is set to false to filter out auto-convertible data formats,
 //   returning true only if the specified data format is available natively.
 if   (dataObject.GetDataPresent(desiredFormat, noAutoConvert))
 {
       // If the desired data format is present, use one of the GetData methods to retrieve the
       // data from the data object.
       data = dataObject.GetData(desiredFormat) as byte[];
 }
 ' Use the GetDataPresent method to check for the presence of a desired data format.
 ' The autoconvert parameter is set to false to filter out auto-convertible data formats,
 ' returning true only if the specified data format is available natively.
 If dataObject.GetDataPresent(desiredFormat, noAutoConvert) Then
     ' If the desired data format is present, use one of the GetData methods to retrieve the
     ' data from the data object.
     data = TryCast(dataObject.GetData(desiredFormat), Byte())
 End If
See also
 IDataObject
 Drag and Drop Overview
       How to: Store Multiple Data Formats in a Data
       Object
       11/21/2022 • 2 minutes to read • Edit Online
The following example shows how to use the SetData(String, Object) method to add data to a data object in
multiple formats.
Example
Description
Code
   // The DataFormats class does not provide data format fields for denoting
   // UTF-32 and UTF-8, which are seldom used in practice; the following strings
   // will be used to identify these "custom" data formats.
   string utf32DataFormat = "UTF-32";
   string utf8DataFormat = "UTF-8";
   // Store the text in the data object, letting the data object choose
   // the data format (which will be DataFormats.Text in this case).
   dataObject.SetData(sourceData);
   // Store the Unicode text in the data object. Text data can be automatically
   // converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object;
   // Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
   // is done here as an exercise only.
   dataObject.SetData(DataFormats.UnicodeText, unicodeText);
   // Store the UTF-8 text in the data object...
   dataObject.SetData(utf8DataFormat, utf8Text);
   // Store the UTF-32 text in the data object...
   dataObject.SetData(utf32DataFormat, utf32Text);
 Dim dataObject As New DataObject()
 Dim sourceData As String = "Some string data to store..."
 ' The DataFormats class does not provide data format fields for denoting
 ' UTF-32 and UTF-8, which are seldom used in practice; the following strings
 ' will be used to identify these "custom" data formats.
 Dim utf32DataFormat As String = "UTF-32"
 Dim utf8DataFormat As String = "UTF-8"
 ' Store the text in the data object, letting the data object choose
 ' the data format (which will be DataFormats.Text in this case).
 dataObject.SetData(sourceData)
 ' Store the Unicode text in the data object. Text data can be automatically
 ' converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object;
 ' Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
 ' is done here as an exercise only.
 dataObject.SetData(DataFormats.UnicodeText, unicodeText)
 ' Store the UTF-8 text in the data object...
 dataObject.SetData(utf8DataFormat, utf8Text)
 ' Store the UTF-32 text in the data object...
 dataObject.SetData(utf32DataFormat, utf32Text)
See also
 IDataObject
 Drag and Drop Overview
       Resources (WPF)
       11/21/2022 • 2 minutes to read • Edit Online
A resource is an object that can be reused in different places in your application. WPF supports different types of
resources. These resources are primarily two types of resources: XAML resources and resource data files.
Examples of XAML resources include brushes and styles. Resource data files are non-executable data files that an
application needs.
In This Section
XAML Resources
WPF Application Resource, Content, and Data Files
Pack URIs in WPF
Reference
ResourceDictionary
StaticResource Markup Extension
DynamicResource Markup Extension
x:Key Directive
Related Sections
XAML in WPF
       Overview of XAML resources
       11/21/2022 • 13 minutes to read • Edit Online
A resource is an object that can be reused in different places in your app. Examples of resources include brushes
and styles. This overview describes how to use resources in Extensible Application Markup Language (XAML).
You can also create and access resources by using code.
  NOTE
  XAML resources described in this article are different from app resources which are generally files added to an app, such
  as content, data, or embedded files.
In the preceding example, when the XAML loader processes the value {StaticResource MyBrush} for the
Background property on Button, the resource lookup logic first checks the resource dictionary for the Button
element. If Button doesn't have a definition of the resource key MyBrush (in that example it doesn't; its resource
collection is empty), the lookup next checks the parent element of Button, which is Page. If you define a resource
on the Page root element, all the elements in the logical tree of the Page can access it. And you can reuse the
same resource for setting the value of any property that accepts the same type that the resource represents. In
the previous example, the same MyBrush resource sets two different properties: the Background of a Button,
and the Fill of a Rectangle.
Static resources
Static resource references work best for the following circumstances:
   Your app design concentrates most of its resources into page or application-level resource dictionaries.
   Static resource references aren't reevaluated based on runtime behaviors, such as reloading a page. So
   there can be some performance benefit to avoiding large numbers of dynamic resource references when
   they aren't necessary based on your resource and app design.
   You're setting the value of a property that isn't on a DependencyObject or a Freezable.
   You're creating a resource dictionary that will be compiled into a DLL and packaged as part of the app or
   shared between apps.
   You're creating a theme for a custom control and are defining resources that are used within the themes.
   For this case, you typically do not want the dynamic resource reference lookup behavior; you instead
   want the static resource reference behavior so that the lookup is predictable and self-contained to the
   theme. With a dynamic resource reference, even a reference within a theme is left unevaluated until run-
   time. and there is a chance that when the theme is applied, some local element will redefine a key that
   your theme is trying to reference, and the local element will fall prior to the theme itself in the lookup. If
   that happens, your theme will not behave as expected.
   You're using resources to set large numbers of dependency properties. Dependency properties have
   effective value caching as enabled by the property system, so if you provide a value for a dependency
   property that can be evaluated at load time, the dependency property doesn't have to check for a
   reevaluated expression and can return the last effective value. This technique can be a performance
   benefit.
   You want to change the underlying resource for all consumers, or you want to maintain separate writable
   instances for each consumer by using the x:Shared Attribute.
Static resource lookup behavior
The following describes the lookup process that automatically happens when a static resource is referenced by a
property or element:
1. The lookup process checks for the requested key within the resource dictionary defined by the element
   that sets the property.
2. The lookup process then traverses the logical tree upward to the parent element and its resource
   dictionary. This process continues until the root element is reached.
3. App resources are checked. App resources are those resources within the resource dictionary that is
   defined by the Application object for your WPF app.
Static resource references from within a resource dictionary must reference a resource that has already been
defined lexically before the resource reference. Forward references cannot be resolved by a static resource
reference. For this reason, design your resource dictionary structure such that resources are defined at or near
the beginning of each respective resource dictionary.
Static resource lookup can extend into themes or into system resources, but this lookup is supported only
because the XAML loader defers the request. The deferral is necessary so that the runtime theme at the time the
page loads applies properly to the app. However, static resource references to keys that are known to only exist
in themes or as system resources aren't recommended, because such references aren't reevaluated if the theme
is changed by the user in real time. A dynamic resource reference is more reliable when you request theme or
system resources. The exception is when a theme element itself requests another resource. These references
should be static resource references, for the reasons mentioned earlier.
The exception behavior if a static resource reference isn't found varies. If the resource was deferred, then the
exception occurs at runtime. If the resource was not deferred, the exception occurs at load time.
Dynamic resources
Dynamic resources work best when:
   The value of the resource, including system resources, or resources that are otherwise user settable,
   depends on conditions that aren't known until runtime. For example, you can create setter values that
   refer to system properties as exposed by SystemColors, SystemFonts, or SystemParameters. These values
   are truly dynamic because they ultimately come from the runtime environment of the user and operating
   system. You might also have application-level themes that can change, where page-level resource access
   must also capture the change.
   You're creating or referencing theme styles for a custom control.
   You intend to adjust the contents of a ResourceDictionary during an app lifetime.
   You have a complicated resource structure that has interdependencies, where a forward reference may be
   required. Static resource references do not support forward references, but dynamic resource references
   do support them because the resource doesn't need to be evaluated until runtime, and forward
   references are therefore not a relevant concept.
   You're referencing a resource that is large from the perspective of a compile or working set, and the
   resource might not be used immediately when the page loads. Static resource references always load
   from XAML when the page loads. However, a dynamic resource reference doesn't load until it's used.
   You're creating a style where setter values might come from other values that are influenced by themes
   or other user settings.
   You're applying resources to elements that might be reparented in the logical tree during app lifetime.
   Changing the parent also potentially changes the resource lookup scope, so if you want the resource for a
   reparented element to be reevaluated based on the new scope, always use a dynamic resource reference.
Dynamic resource lookup behavior
Resource lookup behavior for a dynamic resource reference parallels the lookup behavior in your code if you
call FindResource or SetResourceReference:
1. The lookup checks for the requested key within the resource dictionary defined by the element that sets
   the property:
      If the element defines a Style property, the System.Windows.FrameworkElement.Style of the
      element has its Resources dictionary checked.
      If the element defines a Template property, the System.Windows.FrameworkTemplate.Resources
      dictionary of the element is checked.
2. The lookup traverses the logical tree upward to the parent element and its resource dictionary. This
   process continues until the root element is reached.
3. App resources are checked. App resources are those resources within the resource dictionary that are
   defined by the Application object for your WPF app.
4. The theme resource dictionary is checked for the currently active theme. If the theme changes at runtime,
   the value is reevaluated.
5. System resources are checked.
Exception behavior (if any) varies:
   If a resource was requested by a FindResource call and was not found, an exception is thrown.
   If a resource was requested by a TryFindResource call and was not found, no exception is thrown, and the
   returned value is null . If the property being set doesn't accept null , then it's still possible that a deeper
   exception will be thrown, depending on the individual property being set.
   If a resource was requested by a dynamic resource reference in XAML and was not found, then the
   behavior depends on the general property system. The general behavior is as if no property setting
   operation occurred at the level where the resource exists. For instance, if you attempt to set the
   background on an individual button element using a resource that could not be evaluated, then no value
   set results, but the effective value can still come from other participants in the property system and value
   precedence. For instance, the background value might still come from a locally defined button style or
   from the theme style. For properties that aren't defined by theme styles, the effective value after a failed
   resource evaluation might come from the default value in the property metadata.
Restrictions
Dynamic resource references have some notable restrictions. At least one of the following conditions must be
true:
   The property being set must be a property on a FrameworkElement or FrameworkContentElement. That
   property must be backed by a DependencyProperty.
   The reference is for a value within a   StyleSetter   .
   The property being set must be a property on a Freezable that is provided as a value of either a
   FrameworkElement or FrameworkContentElement property, or a Setter value.
Because the property being set must be a DependencyProperty or Freezable property, most property changes
can propagate to the UI because a property change (the changed dynamic resource value) is acknowledged by
the property system. Most controls include logic that will force another layout of a control if a
DependencyProperty changes and that property might affect layout. However, not all properties that have a
DynamicResource Markup Extension as their value are guaranteed to provide real time updates in the UI. That
functionality still might vary depending on the property, as well as depending on the type that owns the
property, or even the logical structure of your app.
   <Style TargetType="Button">
     <Setter Property="Background">
       <Setter.Value>
         <LinearGradientBrush>
            <GradientStop Offset="0.0" Color="AliceBlue"/>
            <GradientStop Offset="1.0" Color="Salmon"/>
         </LinearGradientBrush>
       </Setter.Value>
     </Setter>
     <Setter Property="FontSize" Value="18"/>
   </Style>
That style really does have a key: the implicit key typeof(System.Windows.Controls.Button) . In markup, you can
specify a TargetType directly as the type name (or you can optionally use {x:Type...} to return a Type.
Through the default theme style mechanisms used by WPF, that style is applied as the runtime style of a Button
on the page, even though the Button itself doesn't attempt to specify its Style property or a specific resource
reference to the style. Your style defined in the page is found earlier in the lookup sequence than the theme
dictionary style, using the same key that the theme dictionary style has. You could just specify
 <Button>Hello</Button> anywhere in the page, and the style you defined with TargetType of Button would
apply to that button. If you want, you can still explicitly key the style with the same type value as TargetType for
clarity in your markup, but that is optional.
Implicit keys for styles do not apply on a control if OverridesDefaultStyle is true . (Also note that
OverridesDefaultStyle might be set as part of native behavior for the control class, rather than explicitly on an
instance of the control.) Also, in order to support implicit keys for derived class scenarios, the control must
override DefaultStyleKey (all existing controls provided as part of WPF include this override). For more
information about styles, themes, and control design, see Guidelines for Designing Stylable Controls.
DataTemplate also has an implicit key. The implicit key for a DataTemplate is the DataType property value.
DataType can also be specified as the name of the type rather than explicitly using {x:Type...}. For details, see Data
Templating Overview.
See also
   ResourceDictionary
   Application resources
   Resources and code
   Define and reference a resource
   Application management overview
   x:Type markup extension
   StaticResource markup extension
   DynamicResource markup extension
       Resources and Code
       11/21/2022 • 4 minutes to read • Edit Online
This overview concentrates on how XAML syntax perspective, see XAML Resources.
An alternative method for assigning a resource reference is SetResourceReference. This method takes two
parameters: the key of the resource, and the identifier for a particular dependency property that is present on
the element instance to which the resource value should be assigned. Functionally, this method is the same and
has the advantage of not requiring any casting of return values.
Still another way to access resources programmatically is to access the contents of the Resources property as a
dictionary. Accessing the dictionary contained by this property is also how you can add new resources to
existing collections, check to see if a given key name is already taken in the collection, and other
dictionary/collection operations. If you are writing a WPF application entirely in code, you can also create the
entire collection in code, assign keys to it, and then assign the finished collection to the Resources property of an
established element. This will be described in the next section.
You can index within any given Resources collection, using a specific key as the index, but you should be aware
that accessing the resource in this way does not follow the normal runtime rules of resource resolution. You are
only accessing that particular collection. Resource lookup will not be traversing the scope to the root or the
application if no valid object was found at the requested key. However, this approach may have performance
advantages in some cases precisely because the scope of the search for the key is more constrained. See the
ResourceDictionary class for more details on how to work with the resource dictionary directly.
See also
   XAML Resources
   Styling and Templating
       Merged Resource Dictionaries
       11/21/2022 • 5 minutes to read • Edit Online
WPF application outside of the compiled XAML application. Resources can then be shared across applications
and are also more conveniently isolated for localization.
   <Page.Resources>
     <ResourceDictionary>
       <ResourceDictionary.MergedDictionaries>
         <ResourceDictionary Source="myresourcedictionary.xaml"/>
         <ResourceDictionary Source="myresourcedictionary2.xaml"/>
       </ResourceDictionary.MergedDictionaries>
     </ResourceDictionary>
   </Page.Resources>
Note that the ResourceDictionary element does not have an x:Key Directive, which is generally required for all
items in a resource collection. But another ResourceDictionary reference within the MergedDictionaries
collection is a special case, reserved for this merged resource dictionary scenario. The ResourceDictionary that
introduces a merged resource dictionary cannot have an x:Key Directive. Typically, each ResourceDictionary
within the MergedDictionaries collection specifies a Source attribute. The value of Source should be a uniform
resource identifier (URI) that resolves to the location of the resources file to be merged. The destination of that
URI must be another XAML file, with ResourceDictionary as its root element.
  NOTE
  It is legal to define resources within a ResourceDictionary that is specified as a merged dictionary, either as an alternative
  to specifying Source, or in addition to whatever resources are included from the specified source. However, this is not a
  common scenario; the main scenario for merged dictionaries is to merge resources from external file locations. If you want
  to specify resources within the markup for a page, you should typically define these in the main ResourceDictionary and
  not in the merged dictionaries.
  NOTE
  Do not use the Embedded Resource build action. The build action itself is supported for WPF applications, but the
  resolution of Source does not incorporate ResourceManager, and thus cannot separate the individual resource out of the
  stream. You could still use Embedded Resource for other purposes so long as you also used ResourceManager to access
  the resources.
A related technique is to use a Pack URI to a XAML file, and refer to it as Source. Pack URI enables references to
components of referenced assemblies and other techniques. For more information on Pack URIs, see WPF
Application Resource, Content, and Data Files.
For resources that are not compiled as part of the project, the URI is evaluated at run time. You can use a
common URI transport such as file: or http: to refer to the resource file. The disadvantage of using the
noncompiled resource approach is that file: access requires additional deployment steps, and http: access
implies the Internet security zone.
Reusing Merged Dictionaries
You can reuse or share merged resource dictionaries between applications, because the resource dictionary to
merge can be referenced through any valid uniform resource identifier (URI). Exactly how you do this will
depend on your application deployment strategy and which application model you follow. The aforementioned
Pack URI strategy provides a way to commonly source a merged resource across multiple projects during
development by sharing an assembly reference. In this scenario the resources are still distributed by the client,
and at least one of the applications must deploy the referenced assembly. It is also possible to reference merged
resources through a distributed URI that uses the http protocol.
Writing merged dictionaries as local application files or to local shared storage is another possible merged
dictionary / application deployment scenario.
Localization
If resources that need to be localized are isolated to dictionaries that are merged into primary dictionaries, and
kept as loose XAML, these files can be localized separately. This technique is a lightweight alternative to
localizing the satellite resource assemblies. For details, see WPF Globalization and Localization Overview.
See also
ResourceDictionary
XAML Resources
Resources and Code
WPF Application Resource, Content, and Data Files
      Resources How-to Topics
      11/21/2022 • 2 minutes to read • Edit Online
The topics in this section describe how to use Windows Presentation Foundation (WPF) resources.
In This Section
Define and Reference a Resource
Use Application Resources
Use SystemFonts
Use System Fonts Keys
Use SystemParameters
Use System Parameters Keys
Reference
Resources
SystemColors
SystemParameters
SystemFonts
Related Sections
XAML Resources
       How to: Define and Reference a Resource
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to define a resource and reference it by using an attribute in Extensible Application
Markup Language (XAML).
Example
The following example defines two types of resources: a SolidColorBrush resource, and several Style resources.
The SolidColorBrush resource MyBrush is used to provide the value of several properties that each take a Brush
type value. The Style resources PageBackground , TitleText and Label each target a particular control type. The
styles set a variety of different properties on the targeted controls, when that style resource is referenced by
resource key and is used to set the Style property of several specific control elements defined in XAML.
Note that one of the properties within the setters of the Label style also references the MyBrush resource
defined earlier. This is a common technique, but it is important to remember that resources are parsed and
entered into a resource dictionary in the order that they are given. Resources are also requested by the order
found within the dictionary if you use the StaticResource Markup Extension to reference them from within
another resource. Make sure that any resource that you reference is defined earlier within the resources
collection than where that resource is then requested. If necessary, you can work around the strict creation order
of resource references by using a DynamicResource Markup Extension to reference the resource at runtime
instead, but you should be aware that this DynamicResource technique has performance consequences. For
details, see XAML Resources.
 <Page Name="root"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Page.Resources>
     <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
     <Style TargetType="Border" x:Key="PageBackground">
       <Setter Property="Background" Value="Blue"/>
     </Style>
     <Style TargetType="TextBlock" x:Key="TitleText">
       <Setter Property="Background" Value="Blue"/>
       <Setter Property="DockPanel.Dock" Value="Top"/>
       <Setter Property="FontSize" Value="18"/>
       <Setter Property="Foreground" Value="#4E87D4"/>
       <Setter Property="FontFamily" Value="Trebuchet MS"/>
       <Setter Property="Margin" Value="0,40,10,10"/>
     </Style>
     <Style TargetType="TextBlock" x:Key="Label">
       <Setter Property="DockPanel.Dock" Value="Right"/>
       <Setter Property="FontSize" Value="8"/>
       <Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
       <Setter Property="FontFamily" Value="Arial"/>
       <Setter Property="FontWeight" Value="Bold"/>
       <Setter Property="Margin" Value="0,3,10,0"/>
     </Style>
   </Page.Resources>
   <StackPanel>
     <Border Style="{StaticResource PageBackground}">
       <DockPanel>
         <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
         <TextBlock Style="{StaticResource Label}">Label</TextBlock>
         <TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource
 MyBrush}" Text="Text" Margin="20" />
         <Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource
 MyBrush}" Margin="40">Button</Button>
         <Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="
 {StaticResource MyBrush}" Margin="40" />
       </DockPanel>
     </Border>
   </StackPanel>
 </Page>
See also
 XAML Resources
 Styling and Templating
       How to: Use Application Resources
       11/21/2022 • 2 minutes to read • Edit Online
Example
The following example shows an application definition file. The application definition file defines a resource
section (a value for the Resources property). Resources defined at the application level can be accessed by all
other pages that are part of the application. In this case, the resource is a declared style. Because a complete
style that includes a control template can be lengthy, this example omits the control template that is defined
within the ContentTemplate property setter of the style.
   <Application.Resources>
     <Style TargetType="Button" x:Key="GelButton" >
       <Setter Property="Margin" Value="1,2,1,2"/>
       <Setter Property="HorizontalAlignment" Value="Left"/>
       <Setter Property="Template">
         <Setter.Value>
         </Setter.Value>
       </Setter>
     </Style>
   </Application.Resources>
The following example shows a XAML page that references the application-level resource that the previous
example defined. The resource is referenced by using a StaticResource Markup Extension that specifies the
unique resource key for the requested resource. No resource with key of "GelButton" is found in the current
page, so the resource lookup scope for the requested resource continues beyond the current page and into the
defined application-level resources.
   <StackPanel
     Name="root"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     >
     <Button Height="50" Width="250" Style="{StaticResource GelButton}" Content="Button 1" />
     <Button Height="50" Width="250" Style="{StaticResource GelButton}" Content="Button 2" />
   </StackPanel>
See also
   XAML Resources
   Application Management Overview
   How-to Topics
       How to: Use SystemFonts
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to use the static resources of the SystemFonts class in order to style or customize a
button.
Example
System resources expose several system-determined values as both resources and properties in order to help
you create visuals that are consistent with system settings. SystemFonts is a class that contains both system font
values as static properties, and properties that reference resource keys that can be used to access those values
dynamically at run time. For example, CaptionFontFamily is a SystemFonts value, and CaptionFontFamilyKey is a
corresponding resource key.
In XAML, you can use the members of SystemFonts as either static properties or dynamic resource references
(with the static property value as the key). Use a dynamic resource reference if you want the font metric to
automatically update while the application runs; otherwise, use a static value reference.
  NOTE
  The resource keys have the suffix "Key" appended to the property name.
The following example shows how to access and use the properties of SystemFonts as static values in order to
style or customize a button. This markup example assigns SystemFonts values to a button.
To use the values of SystemFonts in code, you do not have to use either a static value or a dynamic resource
reference. Instead, use the non-key properties of the SystemFonts class. Although the non-key properties are
apparently defined as static properties, the run-time behavior of WPF as hosted by the system will reevaluate
the properties in real time and will properly account for user-driven changes to system values. The following
example shows how to specify the font settings of a button.
See also
 SystemFonts
 Paint an Area with a System Brush
 Use SystemParameters
 Use System Fonts Keys
 How-to Topics
 x:Static Markup Extension
 XAML Resources
 DynamicResource Markup Extension
       How to: Use System Fonts Keys
      11/21/2022 • 2 minutes to read • Edit Online
System resources expose a number of system metrics as resources to help developers create visuals that are
consistent with system settings. SystemFonts is a class that contains both system font values and system font
resources that bind to the values—for example, CaptionFontFamily and CaptionFontFamilyKey.
System font metrics can be used as either static or dynamic resources. Use a dynamic resource if you want the
font metric to update automatically while the application runs; otherwise use a static resource.
  NOTE
  Dynamic resources have the keyword Key appended to the property name.
The following example shows how to access and use system font dynamic resources to style or customize a
button. This XAML example creates a button style that assigns SystemFonts values to a button.
Example
   <Style x:Key="SimpleFont" TargetType="{x:Type Button}">
       <Setter Property = "FontSize" Value= "{DynamicResource {x:Static SystemFonts.IconFontSizeKey}}"/>
       <Setter Property = "FontWeight" Value= "{DynamicResource {x:Static SystemFonts.MessageFontWeightKey}}"/>
       <Setter Property = "FontFamily" Value= "{DynamicResource {x:Static SystemFonts.CaptionFontFamilyKey}}"/>
   </Style>
See also
   Paint an Area with a System Brush
   Use SystemParameters
   Use SystemFonts
       How to: Use SystemParameters
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to access and use the properties of SystemParameters in order to style or customize a
button.
Example
System resources expose several system based settings as resources in order to help you create visuals that are
consistent with system settings. SystemParameters is a class that contains both system parameter value
properties, and resource keys that bind to the values. For example, FullPrimaryScreenHeight is a
SystemParameters property value and FullPrimaryScreenHeightKey is the corresponding resource key.
In XAML, you can use the members of SystemParameters as either a static property usage, or a dynamic
resource references (with the static property value as the key). Use a dynamic resource reference if you want the
system based value to update automatically while the application runs; otherwise, use a static reference.
Resource keys have the suffix Key appended to the property name.
The following example shows how to access and use the static values of SystemParameters to style or customize
a button. This markup example sizes a button by applying SystemParameters values to a button.
To use the values of SystemParameters in code, you do not have to use either static references or dynamic
resource references. Instead, use the values of the SystemParameters class. Although the non-key properties are
apparently defined as static properties, the runtime behavior of WPF as hosted by the system will reevaluate the
properties in realtime, and will properly account for user-driven changes to system values. The following
example shows how to set the width and height of a button by using SystemParameters values.
See also
SystemParameters
Paint an Area with a System Brush
Use SystemFonts
Use System Parameters Keys
How-to Topics
       How to: Use System Parameters Keys
      11/21/2022 • 2 minutes to read • Edit Online
System resources expose a number of system metrics as resources to help developers create visuals that are
consistent with system settings. SystemParameters is a class that contains both system parameter values and
resource keys that bind to the values—for example, FullPrimaryScreenHeight and FullPrimaryScreenHeightKey.
System parameter metrics can be used as either static or dynamic resources. Use a dynamic resource if you
want the parameter metric to update automatically while the application runs; otherwise use a static resource.
  NOTE
  Dynamic resources have the keyword Key appended to the property name.
The following example shows how to access and use system parameter dynamic resources to style or customize
a button. This XAML example sizes a button by assigning SystemParameters values to the button's width and
height.
Example
   <Style x:Key="SimpleParam" TargetType="{x:Type Button}">
       <Setter Property = "Height" Value= "{DynamicResource {x:Static SystemParameters.CaptionHeightKey}}"/>
       <Setter Property = "Width" Value= "{DynamicResource {x:Static SystemParameters.IconGridWidthKey}}"/>
   </Style>
See also
   Paint an Area with a System Brush
   Use SystemFonts
   Use SystemParameters
      Documents
      11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) provides a versatile set of components that enable developers to build
applications with advanced document features and an improved reading experience. In addition to enhanced
capabilities and quality, Windows Presentation Foundation (WPF) also provides simplified management services
for document packaging, security, and storage.
In This Section
Documents in WPF
Document Serialization and Storage
Annotations
Flow Content
Typography
Printing and Print System Management
See also
   DocumentViewer
   FlowDocument
   System.Windows.Xps
   isXPS.exe (isXPS Conformance Tool)
       Documents in WPF
       11/21/2022 • 9 minutes to read • Edit Online
WPF also provides integrated services for document display, packaging, and security. This topic provides an
introduction to WPF document types and document packaging.
Types of Documents
WPF divides documents into two broad categories based on their intended use; these document categories are
termed "fixed documents" and "flow documents."
Fixed documents are intended for applications that require a precise "what you see is what you get" (WYSIWYG)
presentation, independent of the display or printer hardware used. Typical uses for fixed documents include
desktop publishing, word processing, and form layout, where adherence to the original page design is critical. As
part of its layout, a fixed document maintains the precise positional placement of content elements independent
of the display or print device in use. For example, a fixed document page viewed on 96 dpi display will appear
exactly the same when it is output to a 600 dpi laser printer as when it is output to a 4800 dpi phototypesetter.
The page layout remains the same in all cases, while the document quality maximizes to the capabilities of each
device.
By comparison, flow documents are designed to optimize viewing and readability and are best utilized when
ease of reading is the primary document consumption scenario. Rather than being set to one predefined layout,
flow documents dynamically adjust and reflow their content based on run-time variables such as window size,
device resolution, and optional user preferences. A Web page is a simple example of a flow document where the
page content is dynamically formatted to fit the current window. Flow documents optimize the viewing and
reading experience for the user, based on the runtime environment. For example, the same flow document will
dynamically reformat for optimal readability on either high-resolution 19-inch display or a small 2x3-inch PDA
screen. In addition, flow documents have a number of built in features including search, viewing modes that
optimize readability, and the ability to change the size and appearance of fonts. See Flow Document Overview
for illustrations, examples, and in-depth information on flow documents.
  NOTE
  For more detailed information on flow document features and how to create them, see Flow Document Overview.
Document Packaging
The System.IO.Packaging APIs provide an efficient means to organize application data, document content, and
related resources in a single container that is simple to access, portable, and easy to distribute. A ZIP file is an
example of a Package type capable of holding multiple objects as a single unit. The packaging APIs provide a
default ZipPackage implementation designed using an Open Packaging Conventions standard with XML and ZIP
file architecture. The WPF packaging APIs make it simple to create packages, and to store and access objects
within them. An object stored in a Package is referred to as a PackagePart ("part"). Packages can also include
signed digital certificates that can be used to identify the originator of a part and to validate that the contents of
a package have not been modified. Packages also include a PackageRelationship feature that allows additional
information to be added to a package or associated with specific parts without actually modifying the content of
existing parts. Package services also support Microsoft Windows Rights Management (RM).
The WPF Package architecture serves as the foundation for a number of key technologies:
   XPS documents conforming to the XML Paper Specification (XPS).
   Microsoft Office "12" open XML format documents (.docx).
   Custom storage formats for your own application design.
Based on the packaging APIs, an XpsDocument is specifically designed for storing WPF fixed content documents.
An XpsDocument is a self-contained document that can be opened in a viewer, displayed in a DocumentViewer
control, routed to a print spool, or output directly to an XPS-compatible printer.
The following sections provide additional information on the Package and XpsDocument APIs provided with
WPF.
Package Components
The WPF packaging APIs allow application data and documents to be organized into a single portable unit. A ZIP
file is one of the most common types of packages and is the default package type provided with WPF. Package
itself is an abstract class from which ZipPackage is implemented using an open standard XML and ZIP file
architecture. The Open method uses ZipPackage to create and use ZIP files by default. A package can contain
three basic types of items:
IT EM DESC RIP T IO N
PackageParts
A PackagePart ("part") is an abstract class that refers to an object stored in a Package. In a ZIP file, the package
parts correspond to the individual files stored within the ZIP file. ZipPackagePart provides the default
implementation for serializable objects stored in a ZipPackage. Like a file system, parts contained in the package
are stored in hierarchical directory or "folder-style" organization. Using the WPF packaging APIs, applications
can write, store, and read multiple PackagePart objects using a single ZIP file container.
PackageDigitalSignatures
For security, a PackageDigitalSignature ("digital signature") can be associated with parts within a package. A
PackageDigitalSignature incorporates a [509] that provides two features:
1. Identifies and authenticates the originator of the part.
2. Validates that the part has not been modified.
The digital signature does not preclude a part from being modified, but a validation check against the digital
signature will fail if the part is altered in any way. The application can then take appropriate action—for example,
block opening the part or notify the user that the part has been modified and is not secure.
PackageRelationships
A PackageRelationship ("relationship") provides a mechanism for associating additional information with the
package or a part within the package. A relationship is a package-level facility that can associate additional
information with a part without modifying the actual part content. Inserting new data directly into the part
content of is usually not practical in many cases:
   The actual type of the part and its content schema is not known.
   Even if known, the content schema might not provide a means for adding new information.
   The part might be digitally signed or encrypted, precluding any modification.
Package relationships provide a discoverable means for adding and associating additional information with
individual parts or with the entire package. Package relationships are used for two primary functions:
1. Defining dependency relationships from one part to another part.
2. Defining information relationships that add notes or other data related to the part.
A PackageRelationship provides a quick, discoverable means to define dependencies and add other information
associated with a part of the package or the package as a whole.
D e p e n d e n c y R e l a t i o n sh i p s
Dependency relationships are used to describe dependencies that one part makes to other parts. For example, a
package might contain an HTML part that includes one or more <img> image tags. The image tags refer to
images that are located either as other parts internal to the package or external to the package (such as
accessible over the Internet). Creating a PackageRelationship associated with HTML file makes discovering and
accessing the dependent resources quick and easy. A browser or viewer application can directly access the part
relationships and immediately begin assembling the dependent resources without knowing the schema or
parsing the document.
I n fo r m a t i o n R e l a t i o n sh i p s
Similar to a note or annotation, a PackageRelationship can also be used to store other types of information to be
associated with a part without having to actually modify the part content itself.
XPS Documents
XML Paper Specification (XPS) document is a package that contains one or more fixed-documents along with all
the resources and information required for rendering. XPS is also the native Windows Vista print spool file
format. An XpsDocument is stored in standard ZIP dataset, and can include a combination of XML and binary
components, such as image and font files. PackageRelationships are used to define the dependencies between
the content and the resources required to fully render the document. The XpsDocument design provides a
single, high-fidelity document solution that supports multiple uses:
      Reading, writing, and storing fixed-document content and resources as a single, portable, and easy-to-
      distribute file.
      Displaying documents with the XPS Viewer application.
      Outputting documents in the native print spool output format of Windows Vista.
      Routing documents directly to an XPS-compatible printer.
See also
      FixedDocument
      FlowDocument
      XpsDocument
      ZipPackage
      ZipPackagePart
      PackageRelationship
      DocumentViewer
      Text
      Flow Document Overview
      Printing Overview
      Document Serialization and Storage
       Document Serialization and Storage
       11/21/2022 • 6 minutes to read • Edit Online
Microsoft .NET Framework provides a powerful environment for creating and displaying high quality
documents. Enhanced features that support both fixed-documents and flow-documents, advanced viewing
controls, combined with powerful 2D and 3D graphic capabilities take .NET Framework applications to a new
level of quality and user experience. Being able to flexibly manage an in-memory representation of a document
is a key feature of .NET Framework, and being able to efficiently save and load documents from a data store is a
need of almost every application. The process of converting a document from an internal in-memory
representation to an external data store is termed serialization. The reverse process of reading a data store and
recreating the original in-memory instance is termed deserialization.
After an output file name has been selected by the user, the following example illustrates use of the
CreateSerializerWriter method to store a given document in a specified format.
   // Create a SerializerProvider for accessing plug-in serializers.
   SerializerProvider serializerProvider = new SerializerProvider();
Windows Presentation Foundation (WPF) provides document viewing controls that support annotating
document content.
In This Section
Annotations Overview
Annotations Schema
Reference
Annotation
AnnotationService
DocumentViewer
Related Sections
Documents in WPF
Flow Document Overview
       Annotations Overview
       11/21/2022 • 5 minutes to read • Edit Online
Writing notes or comments on paper documents is such a commonplace activity that we almost take it for
granted. These notes or comments are "annotations" that we add to a document to flag information or to
highlight items of interest for later reference. Although writing notes on printed documents is easy and
commonplace, the ability to add personal comments to electronic documents is typically very limited, if
available at all.
This topic reviews several common types of annotations, specifically sticky notes and highlights, and illustrates
how the Microsoft Annotations Framework facilitates these types of annotations in applications through the
Windows Presentation Foundation (WPF) document viewing controls. WPF document viewing controls that
support annotations include FlowDocumentReader and FlowDocumentScrollViewer, as well as controls derived
from DocumentViewerBase such as DocumentViewer and FlowDocumentPageViewer.
Sticky Notes
A typical sticky note contains information written on a small piece of colored paper that is then "stuck" to a
document. Digital sticky notes provide similar functionality for electronic documents, but with the added
flexibility to include many other types of content such as typed text, handwritten notes (for example, Tablet PC
"ink" strokes), or Web links.
The following illustration shows some examples of highlight, text sticky note, and ink sticky note annotations.
The following example shows the method that you can use to enable annotation support in your application.
   // ------------------------ StartAnnotations --------------------------
   /// <summary>
   /// Enables annotations and displays all that are viewable.</summary>
   private void StartAnnotations()
   {
       // If there is no AnnotationService yet, create one.
       if (_annotService == null)
           // docViewer is a document viewing control named in Window1.xaml.
           _annotService = new AnnotationService(docViewer);
Highlights
People use creative methods to draw attention to items of interest when they mark up a paper document, such
as underlining, highlighting, circling words in a sentence, or drawing marks or notations in the margin. Highlight
annotations in Microsoft Annotations Framework provide a similar feature for marking up information
displayed in WPF document viewing controls.
The following illustration shows an example of a highlight annotation.
Users typically create annotations by first selecting some text or an item of interest, and then right-clicking to
display a ContextMenu of annotation options. The following example shows the Extensible Application Markup
Language (XAML) you can use to declare a ContextMenu with routed commands that users can access to create
and manage annotations.
   <DocumentViewer.ContextMenu>
     <ContextMenu>
       <MenuItem Command="ApplicationCommands.Copy" />
       <Separator />
       <!-- Add a Highlight annotation to a user selection. -->
       <MenuItem Command="ann:AnnotationService.CreateHighlightCommand"
                 Header="Add Highlight" />
       <!-- Add a Text Note annotation to a user selection. -->
       <MenuItem Command="ann:AnnotationService.CreateTextStickyNoteCommand"
                 Header="Add Text Note" />
       <!-- Add an Ink Note annotation to a user selection. -->
       <MenuItem Command="ann:AnnotationService.CreateInkStickyNoteCommand"
                 Header="Add Ink Note" />
       <Separator />
       <!-- Remove Highlights from a user selection. -->
       <MenuItem Command="ann:AnnotationService.ClearHighlightsCommand"
                 Header="Remove Highlights" />
       <!-- Remove Text Notes and Ink Notes from a user selection. -->
       <MenuItem Command="ann:AnnotationService.DeleteStickyNotesCommand"
                 Header="Remove Notes" />
       <!-- Remove Highlights, Text Notes, Ink Notes from a selection. -->
       <MenuItem Command="ann:AnnotationService.DeleteAnnotationsCommand"
                 Header="Remove Highlights & Notes" />
     </ContextMenu>
   </DocumentViewer.ContextMenu>
Data Anchoring
The Annotations Framework binds annotations to the data that the user selects, not just to a position on the
display view. Therefore, if the document view changes, such as when the user scrolls or resizes the display
window, the annotation stays with the data selection to which it is bound. For example, the following graphic
illustrates an annotation that the user has made on a text selection. When the document view changes (scrolls,
resizes, scales, or otherwise moves), the highlight annotation moves with the original data selection.
Another example scenario involves applications that enable the exchange of annotations and sticky notes
between document readers through email. This feature enables these applications to navigate the reader to the
page that contains the annotation that is being exchanged.
See also
   DocumentViewerBase
   DocumentViewer
   FlowDocumentPageViewer
   FlowDocumentScrollViewer
   FlowDocumentReader
   IAnchorInfo
   Annotations Schema
   ContextMenu Overview
   Commanding Overview
   Flow Document Overview
   How to: Add a Command to a MenuItem
      Annotations Schema
      11/21/2022 • 9 minutes to read • Edit Online
This topic describes the XML schema definition (XSD) used by the Microsoft Annotations Framework to save and
retrieve user annotation data.
The Annotations Framework serializes annotation data from an internal representation to an XML format. The
XML format used for this conversion is described by the Annotations Framework XSD Schema. The schema
defines the implementation-independent XML format that can be used to exchange annotation data between
applications.
The Annotations Framework XML schema definition consists of two subschemas
   The Annotations XML Core Schema (Core Schema).
   The Annotations XML Base Schema (Base Schema).
The Core Schema defines the primary XML structure of an Annotation. The majority of XML elements defined in
the Core Schema correspond to types in the System.Windows.Annotations namespace. The Core Schema
exposes three extension points where applications can add their own XML data. These extension points include
the Authors, ContentLocatorPart, and "Content". (Content elements are provided in the form of an XmlElement
list.)
The Base Schema described in this topic defines the extensions for the Authors, ContentLocatorPart, and Content
types included with the initial Windows Presentation Foundation (WPF) release.
     <xsd:complexType name="AnnotationsType">
       <xsd:sequence>
         <xsd:element name="Annotation" minOccurs="0" maxOccurs="unbounded"
                       type="anc:AnnotationType" />
       </xsd:sequence>
     </xsd:complexType>
</xsd:sequence>
<!-- The core schema allows any author type. Supported author types
     in version 1 (V1) are described in the base schema. -->
<xsd:element name="Author" abstract="true" block="extension restriction"/>
<!-- Both annotation anchor and annotation cargo are represented by the
     ResourceListType which contains 0 or more "Resource" elements. -->
<xsd:complexType name="ResourceListType">
  <xsd:sequence>
    <xsd:element name="Resource" minOccurs="0" maxOccurs="unbounded"
                  type="anc:ResourceType" />
  </xsd:sequence>
</xsd:complexType>
</xsd:schema>
     <xsd:import schemaLocation="AnnotationCoreV1.xsd"
          namespace="http://schemas.microsoft.com/windows/annotations/2003/11/core"/>
 <!-- ***** Author ***** -->
 <!-- Simple DisplayName Author -->
 <xsd:complexType name="StringAuthorType">
   <xsd:simpleContent >
     <xsd:extension base='xsd:string' />
   </xsd:simpleContent>
 </xsd:complexType>
 <xsd:element name="StringAuthor" type="anb:StringAuthorType"
              substitutionGroup="anc:Author"/>
 <!-- SegmentNameType: helper type to define possible segment name types -->
 <xsd:simpleType name="SegmentItemNameType">
   <xsd:restriction base='xsd:string'>
     <xsd:pattern value="Segment\d*" />
   </xsd:restriction>
 </xsd:simpleType>
*        <anb:CharacterRange>
*          <anc:Item Name="Count" Value="2" />
*          <anc:Item Name="Segment0" Value="5,10" />
*          <anc:Item Name="Segment1" Value="25,2" />
*        </anb:CharacterRange>
-->
<xsd:complexType name="CharacterRangeType">
  <xsd:complexContent>
    <xsd:extension base="anc:ContentLocatorPartType">
      <xsd:sequence minOccurs="1" maxOccurs="unbounded">
        <xsd:element name="Item" type="anb:FlowItemType" />
      </xsd:sequence>
    </xsd:extension>
  </xsd:complexContent>
</xsd:complexType>
<!-- Helper type -FixedSegmentValue: Defines possible fixed segment values -->
<xsd:simpleType name="FixedSegmentItemValueType">
   <xsd:restriction base='xsd:string'>
      <xsd:pattern value="\d*,\d*,\d*,\d*" />
   </xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="StringValueLocatorPartType">
  <xsd:complexContent>
    <xsd:extension base="anc:ContentLocatorPartType">
      <xsd:sequence minOccurs="1" maxOccurs="1">
        <xsd:element name="Item" type="anb:ValueItemType" />
      </xsd:sequence>
    </xsd:extension>
  </xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="NumberValueLocatorPartType">
  <xsd:complexContent>
    <xsd:extension base="anc:ContentLocatorPartType">
      <xsd:sequence minOccurs="1" maxOccurs="1">
        <xsd:element name="Item" type="anb:ValueItemType" />
      </xsd:sequence>
    </xsd:extension>
  </xsd:complexContent>
</xsd:complexType>
<!-- RTB Text –contains XAML representing StickyNote Reach Text Box text.
*    Used in annotations of type TextStickyNote. -->
<xsd:complexType name="TextContentType">
  <!-- See XAML schema for RTB content -->
</xsd:complexType>
</xsd:schema>
     <anc:Annotation Id="d308ea9b-36eb-4cc4-94d0-97634f10f7a2"
                      CreationTime="2006-09-13T18:28:51.4465702-07:00"
                      LastModificationTime="2006-09-13T18:28:51.4465702-07:00"
                      Type="anb:Highlight">
       <anc:Anchors>
         <anc:Resource Id="4f53661b-7328-4673-8e3f-c53f08b9cd94">
           <anc:ContentLocator>
             <anb:DataId>
               <anc:Item Name="Value" Value="FlowDocument" />
             </anb:DataId>
             <anb:CharacterRange>
               <anc:Item Name="Segment0" Value="600,609" />
               <anc:Item Name="Count" Value="1" />
             </anb:CharacterRange>
           </anc:ContentLocator>
         </anc:Resource>
       </anc:Anchors>
     </anc:Annotation>
     <anc:Annotation Id="d7a8d271-387e-4144-9f8b-bc3c97816e5f"
                      CreationTime="2006-09-13T18:28:56.7903202-07:00"
                      LastModificationTime="2006-09-13T18:28:56.8996952-07:00"
                      Type="anb:TextStickyNote">
       <anc:Authors>
         <anb:StringAuthor>Denise Smith</anb:StringAuthor>
       </anc:Authors>
       <anc:Anchors>
         <anc:Resource Id="dab2560e-6ebd-4ad0-80f9-483356a3be0b">
           <anc:ContentLocator>
             <anb:DataId>
               <anc:Item Name="Value" Value="FlowDocument" />
             </anb:DataId>
             <anb:CharacterRange>
               <anc:Item Name="Segment0" Value="787,801" />
               <anc:Item Name="Count" Value="1" />
             <anc:Item Name="Count" Value="1" />
           </anb:CharacterRange>
         </anc:ContentLocator>
       </anc:Resource>
     </anc:Anchors>
     <anc:Cargos>
       <anc:Resource Id="ea4dbabd-b400-4cf9-8908-5716b410f9e4" Name="Meta Data">
         <anb:MetaData anb:ZOrder="0" />
       </anc:Resource>
     </anc:Cargos>
   </anc:Annotation>
   <anc:Annotation Id="66803c69-b0d7-4cc3-bdff-cacc1955e806"
                    CreationTime="2006-09-13T18:29:03.6653202-07:00"
                    LastModificationTime="2006-09-13T18:29:03.7121952-07:00"
                    Type="anb:InkStickyNote">
     <anc:Authors>
       <anb:StringAuthor>Mike Nash</anb:StringAuthor>
     </anc:Authors>
     <anc:Anchors>
       <anc:Resource Id="52251c53-8eeb-4fd7-b8f3-94e78dfc25fa">
         <anc:ContentLocator>
           <anb:DataId>
             <anc:Item Name="Value" Value="FlowDocument" />
           </anb:DataId>
           <anb:CharacterRange>
             <anc:Item Name="Segment0" Value="880,884" />
             <anc:Item Name="Count" Value="1" />
           </anb:CharacterRange>
         </anc:ContentLocator>
       </anc:Resource>
     </anc:Anchors>
     <anc:Cargos>
       <anc:Resource Id="11e50b97-8d91-4ff9-82c3-16607b2b552b" Name="Meta Data">
         <anb:MetaData anb:ZOrder="1" />
       </anc:Resource>
     </anc:Cargos>
   </anc:Annotation>
</anc:Annotations>
See also
 System.Windows.Annotations
 System.Windows.Annotations.Storage
 Annotation
 AnnotationStore
 XmlStreamStore
 Annotations Overview
       Flow Content
       11/21/2022 • 2 minutes to read • Edit Online
Flow content elements provide the building blocks for creating flow content suitable for hosting in a
FlowDocument.
In This Section
Flow Document Overview
TextElement Content Model Overview
Table Overview
How-to Topics
Reference
FlowDocument
Block
List
Paragraph
Section
Table
Figure
Floater
Hyperlink
Inline
Run
Span
ListItem
Related Sections
Documents in WPF
      Flow Document Overview
      11/21/2022 • 27 minutes to read • Edit Online
Flow documents are designed to optimize viewing and readability. Rather than being set to one predefined
layout, flow documents dynamically adjust and reflow their content based on run-time variables such as
window size, device resolution, and optional user preferences. In addition, flow documents offer advanced
document features, such as pagination and columns. This topic provides an overview of flow documents and
how to create them.
    <List>
      <ListItem>
        <Paragraph>ListItem 1</Paragraph>
      </ListItem>
      <ListItem>
        <Paragraph>ListItem 2</Paragraph>
      </ListItem>
      <ListItem>
        <Paragraph>ListItem 3</Paragraph>
      </ListItem>
    </List>
  </FlowDocument>
</FlowDocumentReader>
using   System;
using   System.Windows;
using   System.Windows.Controls;
using   System.Windows.Documents;
namespace SDKSample
{
    public partial class SimpleFlowExample : Page
    {
        public SimpleFlowExample()
        {
              this.Content = myFlowDocumentReader;
          }
    }
}
   Imports System.Windows
   Imports System.Windows.Controls
   Imports System.Windows.Documents
   Namespace SDKSample
       Partial Public Class SimpleFlowExample
           Inherits Page
           Public Sub New()
               Me.Content = myFlowDocumentReader
           End Sub
       End Class
   End Namespace
The illustration below shows what this code snippet looks like.
In this example, the FlowDocumentReader control is used to host the flow content. See Flow Document Types for
more information on flow content hosting controls. Paragraph, List, ListItem, and Bold elements are used to
control content formatting, based on their order in markup. For example, the Bold element spans across only
part of the text in the paragraph; as a result, only that part of the text is bold. If you have used HTML, this will be
familiar to you.
As highlighted in the illustration above, there are several features built into Flow Documents:
   Search: Allows the user to perform a full text search of an entire document.
   Viewing Mode: The user can select their preferred viewing mode including a single-page (page-at-a-time)
   viewing mode, a two-page-at-a-time (book reading format) viewing mode, and a continuous scrolling
   (bottomless) viewing mode. For more information about these viewing modes, see
   FlowDocumentReaderViewingMode.
   Page Navigation Controls: If the viewing mode of the document uses pages, the page navigation controls
   include a button to jump to the next page (the down arrow) or previous page (the up arrow), as well as
   indicators for the current page number and total number of pages. Flipping through pages can also be
   accomplished using the keyboard arrow keys.
   Zoom: The zoom controls enable the user to increase or decrease the zoom level by clicking the plus or
   minus buttons, respectively. The zoom controls also include a slider for adjusting the zoom level. For
   more information, see Zoom.
These features can be modified based upon the control used to host the flow content. The next section describes
the different controls.
  NOTE
  FlowDocument is required to directly host flow content, so all of these viewing controls consume a FlowDocument to
  enable flow content hosting.
FlowDocumentReader
FlowDocumentReader includes features that enable the user to dynamically choose between various viewing
modes, including a single-page (page-at-a-time) viewing mode, a two-page-at-a-time (book reading format)
viewing mode, and a continuous scrolling (bottomless) viewing mode. For more information about these
viewing modes, see FlowDocumentReaderViewingMode. If you do not need the ability to dynamically switch
between different viewing modes, FlowDocumentPageViewer and FlowDocumentScrollViewer provide lighter-
weight flow content viewers that are fixed in a particular viewing mode.
FlowDocumentPageViewer and FlowDocumentScrollViewer
FlowDocumentPageViewer shows content in page-at-a-time viewing mode, while FlowDocumentScrollViewer
shows content in continuous scrolling mode. Both FlowDocumentPageViewer and FlowDocumentScrollViewer
are fixed to a particular viewing mode. Compare to FlowDocumentReader, which includes features that enable
the user to dynamically choose between various viewing modes (as provided by the
FlowDocumentReaderViewingMode enumeration), at the cost of being more resource intensive than
FlowDocumentPageViewer or FlowDocumentScrollViewer.
By default, a vertical scrollbar is always shown, and a horizontal scrollbar becomes visible if needed. The default
UI for FlowDocumentScrollViewer does not include a toolbar; however, the IsToolBarVisible property can be
used to enable a built-in toolbar.
RichTextBox
You use a RichTextBox when you want to allow the user to edit flow content. For example, if you wanted to create
an editor that allowed a user to manipulate things like tables, italic and bold formatting, etc, you would use a
RichTextBox. See RichTextBox Overview for more information.
  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, the typically built in features of flow
  content like search, viewing mode, page navigation, and zoom are not available within a RichTextBox.
For the purposes of flow content, there are two important categories:
1. Block-derived classes : Also called "Block content elements" or just "Block Elements". Elements that
   inherit from Block can be used to group elements under a common parent or to apply common attributes
   to a group.
2. Inline-derived classes : Also called "Inline content elements" or just "Inline Elements". Elements that
   inherit from Inline are either contained within a Block Element or another Inline Element. Inline Elements
   are often used as the direct container of content that is rendered to the screen. For example, a Paragraph
   (Block Element) can contain a Run (Inline Element) but the Run actually contains the text that is rendered
   on the screen.
Each class in these two categories is briefly described below.
Block-derived Classes
Paragraph
Paragraph is typically used to group content into a paragraph. The simplest and most common use of Paragraph
is to create a paragraph of text.
   <FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <Paragraph>
       Some paragraph text.
     </Paragraph>
   </FlowDocument>
   using   System;
   using   System.Windows;
   using   System.Windows.Controls;
   using   System.Windows.Documents;
   namespace SDKSample
   {
       public partial class ParagraphExample : Page
       {
           public ParagraphExample()
           {
                 this.Content = myFlowDocument;
             }
       }
   }
   Imports System.Windows
   Imports System.Windows.Controls
   Imports System.Windows.Documents
   Namespace SDKSample
       Partial Public Class ParagraphExample
           Inherits Page
           Public Sub New()
               Me.Content = myFlowDocument
           End Sub
       End Class
   End Namespace
However, you can also contain other inline-derived elements as you will see below.
Section
Section is used only to contain other Block-derived elements. It does not apply any default formatting to the
elements it contains. However, any property values set on a Section applies to its child elements. A section also
enables you to programmatically iterate through its child collection. Section is used in a similar manner to the
<DIV> tag in HTML.
In the example below, three paragraphs are defined under one Section. The section has a Background property
value of Red, therefore the background color of the paragraphs is also red.
   <FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <!-- By default, Section applies no formatting to elements contained
          within it. However, in this example, the section has a Background
          property value of "Red", therefore, the three paragraphs (the block)
          inside the section also have a red background. -->
     <Section Background="Red">
       <Paragraph>
         Paragraph 1
       </Paragraph>
       <Paragraph>
         Paragraph 2
       </Paragraph>
       <Paragraph>
         Paragraph 3
       </Paragraph>
     </Section>
   </FlowDocument>
using   System;
using   System.Windows;
using   System.Windows.Media;
using   System.Windows.Controls;
using   System.Windows.Documents;
namespace SDKSample
{
    public partial class SectionExample : Page
    {
        public SectionExample()
        {
              mySection.Blocks.Add(myParagraph1);
              mySection.Blocks.Add(myParagraph2);
              mySection.Blocks.Add(myParagraph3);
              this.Content = myFlowDocument;
          }
    }
}
   Imports   System.Windows
   Imports   System.Windows.Media
   Imports   System.Windows.Controls
   Imports   System.Windows.Documents
   Namespace SDKSample
       Partial Public Class SectionExample
           Inherits Page
           Public Sub New()
                 mySection.Blocks.Add(myParagraph1)
                 mySection.Blocks.Add(myParagraph2)
                 mySection.Blocks.Add(myParagraph3)
               Me.Content = myFlowDocument
           End Sub
       End Class
   End Namespace
BlockUIContainer
BlockUIContainer enables UIElement elements (i.e. a Button) to be embedded in block-derived flow content.
InlineUIContainer (see below) is used to embed UIElement elements in inline-derived flow content.
BlockUIContainer and InlineUIContainer are important because there is no other way to use a UIElement in flow
content unless it is contained within one of these two elements.
The following example shows how to use the BlockUIContainer element to host UIElement objects within flow
content.
   <FlowDocument ColumnWidth="400">
     <Section Background="GhostWhite">
       <Paragraph>
         A UIElement element may be embedded directly in flow content
         by enclosing it in a BlockUIContainer element.
       </Paragraph>
       <BlockUIContainer>
         <Button>Click me!</Button>
       </BlockUIContainer>
       <Paragraph>
         The BlockUIContainer element may host no more than one top-level
         UIElement. However, other UIElements may be nested within the
         UIElement contained by an BlockUIContainer element. For example,
         a StackPanel can be used to host multiple UIElement elements within
         a BlockUIContainer element.
       </Paragraph>
       <BlockUIContainer>
         <StackPanel>
           <Label Foreground="Blue">Choose a value:</Label>
           <ComboBox>
             <ComboBoxItem IsSelected="True">a</ComboBoxItem>
             <ComboBoxItem>b</ComboBoxItem>
             <ComboBoxItem>c</ComboBoxItem>
           </ComboBox>
           <Label Foreground ="Red">Choose a value:</Label>
           <StackPanel>
             <RadioButton>x</RadioButton>
             <RadioButton>y</RadioButton>
             <RadioButton>z</RadioButton>
           </StackPanel>
           <Label>Enter a value:</Label>
           <TextBox>
             A text editor embedded in flow content.
           </TextBox>
         </StackPanel>
       </BlockUIContainer>
     </Section>
   </FlowDocument>
List
List is used to create a bulleted or numeric list. Set the MarkerStyle property to a TextMarkerStyle enumeration
value to determine the style of the list. The example below shows how to create a simple list.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <List>
    <ListItem>
      <Paragraph>
         List Item 1
      </Paragraph>
    </ListItem>
    <ListItem>
      <Paragraph>
         List Item 2
      </Paragraph>
    </ListItem>
    <ListItem>
      <Paragraph>
         List Item 3
      </Paragraph>
    </ListItem>
  </List>
</FlowDocument>
using   System;
using   System.Windows;
using   System.Windows.Media;
using   System.Windows.Controls;
using   System.Windows.Documents;
namespace SDKSample
{
    public partial class ListExample : Page
    {
        public ListExample()
        {
              // Create the ListItem elements for the List and add the
              // paragraphs to them.
              ListItem myListItem1 = new ListItem();
              myListItem1.Blocks.Add(myParagraph1);
              ListItem myListItem2 = new ListItem();
              myListItem2.Blocks.Add(myParagraph2);
              ListItem myListItem3 = new ListItem();
              myListItem3.Blocks.Add(myParagraph3);
              myList.ListItems.Add(myListItem1);
              myList.ListItems.Add(myListItem2);
              myList.ListItems.Add(myListItem3);
              this.Content = myFlowDocument;
          }
    }
}
   Imports   System.Windows
   Imports   System.Windows.Media
   Imports   System.Windows.Controls
   Imports   System.Windows.Documents
   Namespace SDKSample
       Partial Public Class ListExample
           Inherits Page
           Public Sub New()
                 ' Create the ListItem elements for the List and add the
                 ' paragraphs to them.
                 Dim myListItem1 As New ListItem()
                 myListItem1.Blocks.Add(myParagraph1)
                 Dim myListItem2 As New ListItem()
                 myListItem2.Blocks.Add(myParagraph2)
                 Dim myListItem3 As New ListItem()
                 myListItem3.Blocks.Add(myParagraph3)
                 myList.ListItems.Add(myListItem1)
                 myList.ListItems.Add(myListItem2)
                 myList.ListItems.Add(myListItem3)
               Me.Content = myFlowDocument
           End Sub
       End Class
   End Namespace
  NOTE
  List is the only flow element that uses the ListItemCollection to manage child elements.
Table
Table is used to create a table. Table is similar to the Grid element but it has more capabilities and, therefore,
requires greater resource overhead. Because Grid is a UIElement, it cannot be used in flow content unless it is
contained in a BlockUIContainer or InlineUIContainer. For more information on Table, see Table Overview.
Inline -derived Classes
Run
Run is used to contain unformatted text. You might expect Run objects to be used extensively in flow content.
However, in markup, Run elements are not required to be used explicitly. Run is required to be used when
creating or manipulating flow documents by using code. For example, in the markup below, the first Paragraph
specifies the Run element explicitly while the second does not. Both paragraphs generate identical output.
   <Paragraph>
     <Run>Paragraph that explicitly uses the Run element.</Run>
   </Paragraph>
   <Paragraph>
     This Paragraph omits the Run element in markup. It renders
     the same as a Paragraph with Run used explicitly.
   </Paragraph>
  NOTE
  Starting in the .NET Framework 4, the Text property of the Run object is a dependency property. You can bind the Text
  property to a data source, such as a TextBlock. The Text property fully supports one-way binding. The Text property also
  supports two-way binding, except for RichTextBox. For an example, see Run.Text.
Span
Span groups other inline content elements together. No inherent rendering is applied to content within a Span
element. However, elements that inherit from Span including Hyperlink, Bold, Italic and Underline do apply
formatting to text.
Below is an example of a Span being used to contain inline content including text, a Bold element, and a Button.
   <FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <Paragraph>
       Text before the Span. <Span Background="Red">Text within the Span is
       red and <Bold>this text is inside the Span-derived element Bold.</Bold>
       A Span can contain more then text, it can contain any inline content. For
       example, it can contain a
       <InlineUIContainer>
         <Button>Button</Button>
       </InlineUIContainer>
       or other UIElement, a Floater, a Figure, etc.</Span>
     </Paragraph>
</FlowDocument>
InlineUIContainer
InlineUIContainer enables UIElement elements (i.e. a control like Button) to be embedded in an Inline content
element. This element is the inline equivalent to BlockUIContainer described above. Below is an example that
uses InlineUIContainer to insert a Button inline in a Paragraph.
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Paragraph>
      Text to precede the button...
</FlowDocument>
using     System;
using     System.Windows;
using     System.Windows.Media;
using     System.Windows.Controls;
using     System.Windows.Documents;
namespace SDKSample
{
    public partial class InlineUIContainerExample : Page
    {
        public InlineUIContainerExample()
        {
            Run run1 = new Run(" Text to precede the button... ");
            Run run2 = new Run(" Text to follow the button... ");
                this.Content = myFlowDocument;
            }
      }
}
   Imports   System.Windows
   Imports   System.Windows.Media
   Imports   System.Windows.Controls
   Imports   System.Windows.Documents
   Namespace SDKSample
       Partial Public Class InlineUIContainerExample
           Inherits Page
           Public Sub New()
               Dim run1 As New Run(" Text to precede the button... ")
               Dim run2 As New Run(" Text to follow the button... ")
               Me.Content = myFlowDocument
           End Sub
       End Class
   End Namespace
  NOTE
  InlineUIContainer does not need to be used explicitly in markup. If you omit it, an InlineUIContainer will be created
  anyway when the code is compiled.
  <Paragraph>
    <Figure
      Width="300" Height="100"
      Background="GhostWhite" HorizontalAnchor="PageLeft" >
      <Paragraph FontStyle="Italic" Background="Beige" Foreground="DarkGreen" >
        A Figure embeds content into flow content with placement properties
        that can be customized independently from the primary content flow
      </Paragraph>
    </Figure>
    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>
using   System;
using   System.Windows;
using   System.Windows.Media;
using   System.Windows.Controls;
using   System.Windows.Documents;
namespace SDKSample
{
    public partial class FigureExample : Page
    {
        public FigureExample()
        {
              this.Content = myFlowDocument;
          }
    }
}
   Imports   System.Windows
   Imports   System.Windows.Media
   Imports   System.Windows.Controls
   Imports   System.Windows.Documents
   Namespace SDKSample
       Partial Public Class FigureExample
           Inherits Page
           Public Sub New()
                 ' Create a Figure and assign content and layout properties to it.
                 Dim myFigure As New Figure()
                 myFigure.Width = New FigureLength(300)
                 myFigure.Height = New FigureLength(100)
                 myFigure.Background = Brushes.GhostWhite
                 myFigure.HorizontalAnchor = FigureHorizontalAnchor.PageLeft
                 Dim myFigureParagraph As New Paragraph(New Run(strFigure))
                 myFigureParagraph.FontStyle = FontStyles.Italic
                 myFigureParagraph.Background = Brushes.Beige
                 myFigureParagraph.Foreground = Brushes.DarkGreen
                 myFigure.Blocks.Add(myFigureParagraph)
               Me.Content = myFlowDocument
           End Sub
       End Class
   End Namespace
Figure and Floater differ in several ways and are used for different scenarios.
Figure:
   Can be positioned: You can set its horizontal and vertical anchors to dock it relative to the page, content,
   column or paragraph. You can also use its HorizontalOffset and VerticalOffset properties to specify
   arbitrary offsets.
   Is sizable to more than one column: You can set Figure height and width to multiples of page, content or
   column height or width. Note that in the case of page and content, multiples greater than 1 are not
   allowed. For example, you can set the width of a Figure to be "0.5 page" or "0.25 content" or "2 Column".
   You can also set height and width to absolute pixel values.
   Does not paginate: If the content inside a Figure does not fit inside the Figure, it will render whatever
   content does fit and the remaining content is lost
Floater :
   Cannot be positioned and will render wherever space can be made available for it. You cannot set the
   offset or anchor a Floater.
   Cannot be sized to more than one column: By default, Floater sizes at one column. It has a Width property
   that can be set to an absolute pixel value, but if this value is greater than one column width it is ignored
   and the floater is sized at one column. You can size it to less than one column by setting the correct pixel
   width, but sizing is not column-relative, so "0.5Column" is not a valid expression for Floater width. Floater
   has no height property and it's height cannot be set, it’s height depends on the content
   Floater paginates: If its content at its specified width extends to more than 1 column height, floater breaks
   and paginates to the next column, the next page, etc.
Figure is a good place to put standalone content where you want to control the size and positioning, and are
confident that the content will fit in the specified size. Floater is a good place to put more free-flowing content
that flows similar to the main page content, but is separated from it.
LineBreak
LineBreak causes a line break to occur in flow content. The following example demonstrates the use of
LineBreak.
   <FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <Paragraph>
       Before the LineBreak in Paragraph.
       <LineBreak />
       After the LineBreak in Paragraph.
       <LineBreak/><LineBreak/>
       After two LineBreaks in Paragraph.
     </Paragraph>
     <Paragraph>
       <LineBreak/>
     </Paragraph>
     <Paragraph>
       After a Paragraph with only a LineBreak in it.
     </Paragraph>
   </FlowDocument>
This adds a Run to the InlineCollection of the Paragraph. This is the same as the implicit Run found inside a
Paragraph in markup:
   <Paragraph>
   Some Text
   </Paragraph>
As an example of using the BlockCollection, the following example creates a new Section and then uses the Add
method to add a new Paragraph to the Section contents.
In addition to adding items to a flow collection, you can remove items as well. The following example deletes the
last Inline element in the Span.
spanx.Inlines.Remove(spanx.Inlines.LastInline);
spanx.Inlines.Remove(spanx.Inlines.LastInline)
The following example clears all of the contents (Inline elements) from the Span.
spanx.Inlines.Clear();
spanx.Inlines.Clear()
When working with flow content programmatically, you will likely make extensive use of these collections.
Whether a flow element uses an InlineCollection (Inlines) or BlockCollection (Blocks) to contain its child
elements depends on what type of child elements (Block or Inline) can be contained by the parent. Containment
rules for flow content elements are summarized in the content schema in the next section.
  NOTE
  There is a third type of collection used with flow content, the ListItemCollection, but this collection is only used with a List.
  In addition, there are several collections used with Table. See Table Overview for more information.
Content Schema
Given the number of different flow content elements, it can be overwhelming to keep track of what type of child
elements an element can contain. The diagram below summarizes the containment rules for flow elements. The
arrows represent the possible parent/child relationships.
As can be seen from the diagram above, the children allowed for an element are not necessarily determined by
whether it is a Block element or an Inline element. For example, a Span (an Inline element) can only have Inline
child elements while a Figure (also an Inline element) can only have Block child elements. Therefore, a diagram
is useful for quickly determining what element can be contained in another. As an example, let's use the diagram
to determine how to construct the flow content of a RichTextBox.
1. A RichTextBox must contain a FlowDocument which in turn must contain a Block-derived object. Below is the
corresponding segment from the diagram above.
   <RichTextBox>
     <FlowDocument>
       <!-- One or more Block-derived object… -->
     </FlowDocument>
   </RichTextBox>
2. According to the diagram, there are several Block elements to choose from including Paragraph, Section,
Table, List, and BlockUIContainer (see Block-derived classes above). Let's say we want a Table. According to the
diagram above, a Table contains a TableRowGroup containing TableRow elements, which contain TableCell
elements which contain a Block-derived object. Below is the corresponding segment for Table taken from the
diagram above.
3. Again, one or more Block elements are required underneath a TableCell. To make it simple, let's place some
text inside the cell. We can do this using a Paragraph with a Run element. Below is the corresponding segments
from the diagram showing that a Paragraph can take an Inline element and that a Run (an Inline element) can
only take plain text.
   <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <RichTextBox>
       <FlowDocument>
       </FlowDocument>
     </RichTextBox>
   </Page>
Customizing Text
Usually text is the most prevalent type of content in a flow document. Although the objects introduced above
can be used to control most aspects of how text is rendered, there are some other methods for customizing text
that is covered in this section.
Text Decorations
Text decorations allow you to apply the underline, overline, baseline, and strikethrough effects to text (see
pictures below). These decorations are added using the TextDecorations property that is exposed by a number of
objects including Inline, Paragraph, TextBlock, and TextBox.
The following example shows how to set the TextDecorations property of a Paragraph.
   <FlowDocument ColumnWidth="200">
     <Paragraph TextDecorations="Strikethrough">
       This text will render with the strikethrough effect.
     </Paragraph>
   </FlowDocument>
   Paragraph parx = new Paragraph(new Run("This text will render with the strikethrough effect."));
   parx.TextDecorations = TextDecorations.Strikethrough;
   Dim parx As New Paragraph(New Run("This text will render with the strikethrough effect."))
   parx.TextDecorations = TextDecorations.Strikethrough
The following figures show how the Overline , Baseline , and Underline decorations render, respectively.
Typography
The Typography property is exposed by most flow-related content including TextElement, FlowDocument,
TextBlock, and TextBox. This property is used to control typographical characteristics/variations of text (i.e. small
or large caps, making superscripts and subscripts, etc).
The following example shows how to set the Typography attribute, using Paragraph as the example element.
   <Paragraph
     TextAlignment="Left"
     FontSize="18"
     FontFamily="Palatino Linotype"
     Typography.NumeralStyle="OldStyle"
     Typography.Fraction="Stacked"
     Typography.Variants="Inferior"
   >
     <Run>
       This text has some altered typography characteristics. Note
       that use of an open type font is necessary for most typographic
       properties to be effective.
     </Run>
     <LineBreak/><LineBreak/>
     <Run>
       0123456789 10 11 12 13
     </Run>
     <LineBreak/><LineBreak/>
     <Run>
       1/2 2/3 3/4
     </Run>
   </Paragraph>
In contrast, the following figure shows how a similar example with default typographic properties renders.
The following example shows how to set the Typography property programmatically.
  Paragraph par = new Paragraph();
  par.Inlines.Add(runText);
  par.Inlines.Add(new LineBreak());
  par.Inlines.Add(new LineBreak());
  par.Inlines.Add(runNumerals);
  par.Inlines.Add(new LineBreak());
  par.Inlines.Add(new LineBreak());
  par.Inlines.Add(runFractions);
  par.TextAlignment = TextAlignment.Left;
  par.FontSize = 18;
  par.FontFamily = new FontFamily("Palatino Linotype");
  par.Typography.NumeralStyle = FontNumeralStyle.OldStyle;
  par.Typography.Fraction = FontFraction.Stacked;
  par.Typography.Variants = FontVariants.Inferior;
  Dim runText As New Run("This text has some altered typography characteristics. Note" & "that use of an open
  type font is necessary for most typographic" & "properties to be effective.")
  Dim runNumerals As New Run("0123456789 10 11 12 13")
  Dim runFractions As New Run("1/2 2/3 3/4")
  par.Inlines.Add(runText)
  par.Inlines.Add(New LineBreak())
  par.Inlines.Add(New LineBreak())
  par.Inlines.Add(runNumerals)
  par.Inlines.Add(New LineBreak())
  par.Inlines.Add(New LineBreak())
  par.Inlines.Add(runFractions)
  par.TextAlignment = TextAlignment.Left
  par.FontSize = 18
  par.FontFamily = New FontFamily("Palatino Linotype")
  par.Typography.NumeralStyle = FontNumeralStyle.OldStyle
  par.Typography.Fraction = FontFraction.Stacked
  par.Typography.Variants = FontVariants.Inferior
See also
  Text
  Typography in WPF
  How-to Topics
  TextElement Content Model Overview
  RichTextBox Overview
  Documents in WPF
  Table Overview
  Annotations Overview
       TextElement Content Model Overview
       11/21/2022 • 4 minutes to read • Edit Online
This content model overview describes the supported content for a TextElement. The Paragraph class is a type of
TextElement. A content model describes what objects/elements can be contained in others. This overview
summarizes the content model used for objects derived from TextElement. For more information, see Flow
Document Overview.
As can be seen from the preceding diagram, the children allowed for an element are not necessarily determined
by whether a class is derived from the Block class or an Inline class. For example, a Span (an Inline-derived class)
can only have Inline child elements, but a Figure (also an Inline-derived class) can only have Block child
elements. Therefore, a diagram is useful for quickly determining what element can be contained in another. As
an example, let's use the diagram to determine how to construct the flow content of a RichTextBox.
1. A RichTextBox must contain a FlowDocument which in turn must contain a Block-derived object. The
   following is the corresponding segment from the preceding diagram.
2. According to the diagram, there are several Block elements to choose from including Paragraph, Section,
   Table, List, and BlockUIContainer (see Block-derived classes in the preceding diagram). Let's say we want a
   Table. According to the preceding diagram, a Table contains a TableRowGroup containing TableRow
   elements, which contain TableCell elements which contain a Block-derived object. The following is the
   corresponding segment for Table taken from the preceding diagram.
      <RichTextBox>
        <FlowDocument>
          <Table>
            <TableRowGroup>
              <TableRow>
                <TableCell>
                   <!-- One or more Block-derived object… -->
                </TableCell>
              </TableRow>
            </TableRowGroup>
          </Table>
        </FlowDocument>
      </RichTextBox>
3. Again, one or more Block elements are required underneath a TableCell. To make it simple, let's place
   some text inside the cell. We can do this using a Paragraph with a Run element. The following is the
   corresponding segments from the diagram showing that a Paragraph can take an Inline element and that
   a Run (an Inline element) can only take plain text.
       </FlowDocument>
     </RichTextBox>
   </Page>
  NOTE
  Table uses several collections to manipulate its contents, but they are not covered here. For more information, see Table
  Overview.
The following example creates a new Span object, and then uses the             Add   method to add two text runs as
content children of the Span.
The following example creates a new Run element and inserts it at the beginning of the Span.
The following example deletes the last Inline element in the Span.
spanx.Inlines.Remove(spanx.Inlines.LastInline);
spanx.Inlines.Remove(spanx.Inlines.LastInline)
The following example clears all of the contents (Inline elements) from the Span.
spanx.Inlines.Clear();
spanx.Inlines.Clear()
See also
   Manipulate a FlowDocument through the Blocks Property
   Manipulate Flow Content Elements through the Blocks Property
   Manipulate a FlowDocument through the Blocks Property
   Manipulate a Table's Columns through the Columns Property
   Manipulate a Table's Row Groups through the RowGroups Property
          Table Overview
          11/21/2022 • 10 minutes to read • Edit Online
Table is a block level element that supports grid-based presentation of Flow document content. The flexibility of
this element makes it very useful, but also makes it more complicated to understand and use correctly.
This topic contains the following sections.
   Table Basics
   How is Table Different then Grid?
   Basic Table Structure
   Table Containment
   Row Groupings
   Background Rendering Precedence
   Spanning Rows or Columns
   Building a Table With Code
   [Related Topics]
Table Basics
How is Table Different then Grid?
Table and Grid share some common functionality, but each is best suited for different scenarios. A Table is
designed for use within flow content (see Flow Document Overview for more information on flow content).
Grids are best used inside of forms (basically anywhere outside of flow content). Within a FlowDocument, Table
supports flow content behaviors like pagination, column reflow, and content selection while a Grid does not. A
Grid on the other hand is best used outside of a FlowDocument for many reasons including Grid adds elements
based on a row and column index, Table does not. The Grid element allows layering of child content, allowing
more than one element to exist within a single "cell." Table does not support layering. Child elements of a Grid
can be absolutely positioned relative to the area of their "cell" boundaries. Table does not support this feature.
Finally, a Grid requires less resources then a Table so consider using a Grid to improve performance.
  NOTE
  TableCell elements may not directly host text content. For more information about the containment rules for flow content
  elements like TableCell, see Flow Document Overview.
  NOTE
  Table is similar to the Grid element but has more capabilities and, therefore, requires greater resource overhead.
Table Containment
Table derives from the Block element, and adheres to the common rules for Block level elements. A Table
element may be contained by any of the following elements:
   FlowDocument
   TableCell
   ListBoxItem
   ListViewItem
   Section
   Floater
   Figure
Row Groupings
The TableRowGroup element provides a way to arbitrarily group rows within a table; every row in a table must
belong to a row grouping. Rows within a row group often share a common intent, and may be styled as a group.
A common use for row groupings is to separate special-purpose rows, such as a title, header, and footer rows,
from the primary content contained by the table.
The following example uses XAML to define a table with styled header and footer rows.
   <Table>
     <Table.Resources>
       <!-- Style for header/footer rows. -->
       <Style x:Key="headerFooterRowStyle" TargetType="{x:Type TableRowGroup}">
         <Setter Property="FontWeight" Value="DemiBold"/>
         <Setter Property="FontSize" Value="16"/>
         <Setter Property="Background" Value="LightGray"/>
       </Style>
     <Table.Columns>
       <TableColumn/> <TableColumn/> <TableColumn/> <TableColumn/>
     </Table.Columns>
     <!-- This TableRowGroup hosts a header row for the table. -->
     <TableRowGroup Style="{StaticResource headerFooterRowStyle}">
       <TableRow>
         <TableCell/>
         <TableCell><Paragraph>Gizmos</Paragraph></TableCell>
         <TableCell><Paragraph>Thingamajigs</Paragraph></TableCell>
         <TableCell><Paragraph>Doohickies</Paragraph></TableCell>
       </TableRow>
     </TableRowGroup>
     <!-- This TableRowGroup hosts the main data rows for the table. -->
     <TableRowGroup Style="{StaticResource dataRowStyle}">
       <TableRow>
         <TableCell><Paragraph Foreground="Blue">Blue</Paragraph></TableCell>
         <TableCell><Paragraph>1</Paragraph></TableCell>
         <TableCell><Paragraph>2</Paragraph></TableCell>
         <TableCell><Paragraph>3</Paragraph> </TableCell>
       </TableRow>
       <TableRow>
         <TableCell><Paragraph Foreground="Red">Red</Paragraph></TableCell>
         <TableCell><Paragraph>1</Paragraph></TableCell>
         <TableCell><Paragraph>2</Paragraph></TableCell>
         <TableCell><Paragraph>3</Paragraph></TableCell>
       </TableRow>
       <TableRow>
         <TableCell><Paragraph Foreground="Green">Green</Paragraph></TableCell>
         <TableCell><Paragraph>1</Paragraph></TableCell>
         <TableCell><Paragraph>2</Paragraph></TableCell>
         <TableCell><Paragraph>3</Paragraph></TableCell>
       </TableRow>
     </TableRowGroup>
     <!-- This TableRowGroup hosts a footer row for the table. -->
     <TableRowGroup Style="{StaticResource headerFooterRowStyle}">
       <TableRow>
         <TableCell><Paragraph>Totals</Paragraph></TableCell>
         <TableCell><Paragraph>3</Paragraph></TableCell>
         <TableCell><Paragraph>6</Paragraph></TableCell>
         <TableCell>
            <Table></Table>
         </TableCell>
       </TableRow>
     </TableRowGroup>
   </Table>
   <Table Background="Yellow">
     <Table.Columns>
       <TableColumn/>
       <TableColumn Background="LightGreen"/>
       <TableColumn/>
     </Table.Columns>
     <TableRowGroup>
       <TableRow>
         <TableCell/><TableCell/><TableCell/>
       </TableRow>
     </TableRowGroup>
     <TableRowGroup Background="Tan">
       <TableRow>
         <TableCell/><TableCell/><TableCell/>
       </TableRow>
       <TableRow Background="LightBlue">
         <TableCell/><TableCell Background="Purple"/><TableCell/>
       </TableRow>
       <TableRow>
         <TableCell/><TableCell/><TableCell/>
       </TableRow>
     </TableRowGroup>
     <TableRowGroup>
       <TableRow>
         <TableCell/><TableCell/><TableCell/>
       </TableRow>
     </TableRowGroup>
   </Table>
The following figure shows how this example renders (showing background colors only).
   <Table>
     <Table.Columns>
       <TableColumn/>
       <TableColumn/>
       <TableColumn/>
     </Table.Columns>
     <TableRowGroup>
       <TableRow>
         <TableCell ColumnSpan="3" Background="Cyan">
            <Paragraph>This cell spans all three columns.</Paragraph>
         </TableCell>
       </TableRow>
       <TableRow>
         <TableCell Background="LightGray"><Paragraph>Cell 1</Paragraph></TableCell>
         <TableCell Background="LightGray"><Paragraph>Cell 2</Paragraph></TableCell>
         <TableCell Background="LightGray"><Paragraph>Cell 3</Paragraph></TableCell>
       </TableRow>
     </TableRowGroup>
   </Table>
Next, six TableColumn objects are created and added to the table's Columns collection, with some formatting
applied.
  NOTE
  Note that the table's Columns collection uses standard zero-based indexing.
   ' Create 6 columns and add them to the table's Columns collection.
   Dim numberOfColumns = 6
   Dim x
   For x = 0 To numberOfColumns
       table1.Columns.Add(new TableColumn())
Next, a title row is created and added to the table with some formatting applied. The title row happens to contain
a single cell that spans all six columns in the table.
   // Create and add an empty TableRowGroup to hold the table's Rows.
   table1.RowGroups.Add(new TableRowGroup());
   ' Create and add an empty TableRowGroup to hold the table's Rows.
   table1.RowGroups.Add(new TableRowGroup())
Next, a header row is created and added to the table, and the cells in the header row are created and populated
with content.
Next, a row for data is created and added to the table, and the cells in this row are created and populated with
content. Building this row is similar to building the header row, with slightly different formatting applied.
Finally, a footer row is created, added, and formatted. Like the title row, the footer contains a single cell that
spans all six columns in the table.
 table1.RowGroups[0].Rows.Add(new TableRow());
 currentRow = table1.RowGroups[0].Rows[3];
 table1.RowGroups(0).Rows.Add(new TableRow())
 currentRow = table1.RowGroups(0).Rows(3)
See also
 Flow Document Overview
 Define a Table with XAML
 Documents in WPF
 Use Flow Content Elements
      Flow Content Elements How-to Topics
      11/21/2022 • 2 minutes to read • Edit Online
The topics in this section describe how to accomplish common tasks using various flow content elements and
related features.
In This Section
Adjust Spacing Between Paragraphs
Build a Table Programmatically
Change the FlowDirection of Content Programmatically
Change the TextWrapping Property Programmatically
Define a Table with XAML
Alter the Typography of Text
Enable Text Trimming
Insert an Element Into Text Programmatically
Manipulate Flow Content Elements through the Blocks Property
Manipulate Flow Content Elements through the Inlines Property
Manipulate a FlowDocument through the Blocks Property
Manipulate a Table's Columns through the Columns Property
Manipulate a Table's Row Groups through the RowGroups Property
Use Flow Content Elements
Use FlowDocument Column-Separating Attributes
Reference
FlowDocument
Block
Inline
Related Sections
Documents in WPF
       How to: Adjust Spacing Between Paragraphs
       11/21/2022 • 2 minutes to read • Edit Online
This example shows how to adjust or eliminate spacing between paragraphs in flow content.
In flow content, extra space that appears between paragraphs is the result of margins set on these paragraphs;
thus, the spacing between paragraphs can be controlled by adjusting the margins on those paragraphs. To
eliminate extra spacing between two paragraphs altogether, set the margins for the paragraphs to 0 . To achieve
uniform spacing between paragraphs throughout an entire FlowDocument, use styling to set a uniform margin
value for all paragraphs in the FlowDocument.
It is important to note that the margins for two adjacent paragraphs will "collapse" to the larger of the two
margins, rather than doubling up. So, if two adjacent paragraphs have margins of 20 pixels and 40 pixels
respectively, the resulting space between the paragraphs is 40 pixels, the larger of the two margin values.
Example
The following example uses styling to set the margin for all Paragraph elements in a FlowDocument to 0 , which
effectively eliminates extra spacing between paragraphs in the FlowDocument.
   <FlowDocument>
     <FlowDocument.Resources>
       <!-- This style is used to set the margins for all paragraphs in the FlowDocument to 0. -->
       <Style TargetType="{x:Type Paragraph}">
         <Setter Property="Margin" Value="0"/>
       </Style>
     </FlowDocument.Resources>
     <Paragraph>
       Spacing between paragraphs is caused by margins set on the paragraphs. Two adjacent margins
       will "collapse" to the larger of the two margin widths, rather than doubling up.
     </Paragraph>
     <Paragraph>
       To eliminate extra spacing between two paragraphs, just set the paragraph margins to 0.
     </Paragraph>
   </FlowDocument>
       How to: Build a Table Programmatically
       11/21/2022 • 5 minutes to read • Edit Online
The following examples show how to programmatically create a Table and populate it with content. The contents
of the table are apportioned into five rows (represented by TableRow objects contained in a RowGroups object)
and six columns (represented by TableColumn objects). The rows are used for different presentation purposes,
including a title row intended to title the entire table, a header row to describe the columns of data in the table,
and a footer row with summary information. Note that the notion of "title", "header", and "footer" rows are not
inherent to the table; these are simply rows with different characteristics. Table cells contain the actual content,
which can be comprised of text, images, or nearly any other user interface (UI) element.
Create a table
First, a FlowDocument is created to host the Table, and a new Table is created and added to the contents of the
FlowDocument.
Add columns
Next, six TableColumn objects are created and added to the table's Columns collection, with some formatting
applied.
  NOTE
  Note that the table's Columns collection uses standard zero-based indexing.
   // Create 6 columns and add them to the table's Columns collection.
   int numberOfColumns = 6;
   for (int x = 0; x < numberOfColumns; x++)
   {
       table1.Columns.Add(new TableColumn());
   ' Create 6 columns and add them to the table's Columns collection.
   Dim numberOfColumns = 6
   Dim x
   For x = 0 To numberOfColumns
       table1.Columns.Add(new TableColumn())
Add a row
Next, a row for data is created and added to the table, and the cells in this row are created and populated with
content. Building this row is similar to building the header row, with slightly different formatting applied.
   table1.RowGroups[0].Rows.Add(new TableRow());
   currentRow = table1.RowGroups[0].Rows[3];
See also
 Table Overview
      How to: Change the FlowDirection of Content
      Programmatically
      11/21/2022 • 2 minutes to read • Edit Online
This example shows how to programmatically change the FlowDirection property of a FlowDocumentReader.
   <FlowDocumentReader>
     <FlowDocument FontFamily="Arial" Name="tf1">
       <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
       uliquip 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>
       <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>
   </FlowDocumentReader>
C# code example
The events associated with the button clicks defined above are handled in a C# code-behind file.
Example
The following code example shows how to change the value of the TextWrapping property programmatically.
Three Button elements are placed within a StackPanel element in XAML. Each Click event for a Button
corresponds with an event handler in the code. The event handlers use the same name as the TextWrapping
value they will apply to txt2 when the button is clicked. Also, the text in txt1 (a TextBlock not shown in the
XAML) is updated to reflect the change in the property.
See also
 TextWrapping
 TextWrapping
      How to: Define a Table with XAML
      11/21/2022 • 2 minutes to read • Edit Online
The following example demonstrates how to define a Table using Extensible Application Markup Language
(XAML). The example table has four columns (represented by TableColumn elements) and several rows
(represented by TableRow elements) containing data as well as title, header, and footer information. Rows must
be contained in a TableRowGroup element. Each row in the table is comprised of one or more cells (represented
by TableCell elements). Content in a table cell must be contained in a Block element; in this case Paragraph
elements are used. The table also hosts a hyperlink (represented by the Hyperlink element) in the footer row.
Example
   <FlowDocumentReader>
     <FlowDocument>
<Table CellSpacing="5">
         <Table.Columns>
           <TableColumn/>
           <TableColumn/>
           <TableColumn/>
           <TableColumn/>
         </Table.Columns>
<TableRowGroup>
           <!-- Four data rows for the major outter planets. -->
           <TableRow>
             <TableCell><Paragraph>Jupiter</Paragraph></TableCell>
             <TableCell><Paragraph>778,330,000 km</Paragraph></TableCell>
             <TableCell><Paragraph>142,984 km</Paragraph></TableCell>
             <TableCell><Paragraph>1.900e27 kg</Paragraph></TableCell>
           </TableRow>
           <TableRow Background="lightgray">
             <TableCell><Paragraph>Saturn</Paragraph></TableCell>
             <TableCell><Paragraph>1,429,400,000 km</Paragraph></TableCell>
             <TableCell><Paragraph>120,536 km</Paragraph></TableCell>
             <TableCell><Paragraph>5.68e26 kg</Paragraph></TableCell>
           </TableRow>
           <TableRow>
             <TableCell><Paragraph>Uranus</Paragraph></TableCell>
             <TableCell><Paragraph>2,870,990,000 km</Paragraph></TableCell>
             <TableCell><Paragraph>51,118 km</Paragraph></TableCell>
             <TableCell><Paragraph>8.683e25 kg</Paragraph></TableCell>
           </TableRow>
           <TableRow Background="lightgray">
             <TableCell><Paragraph>Neptune</Paragraph></TableCell>
             <TableCell><Paragraph>4,504,000,000 km</Paragraph></TableCell>
             <TableCell><Paragraph>49,532 km</Paragraph></TableCell>
             <TableCell><Paragraph>1.0247e26 kg</Paragraph></TableCell>
           </TableRow>
         </TableRowGroup>
       </Table>
     </FlowDocument>
   </FlowDocumentReader>
The following figure shows how the table defined in this example renders:
       How-to: Alter the Typography of Text
      11/21/2022 • 2 minutes to read • Edit Online
The following example shows how to set the Typography attribute, using Paragraph as the example element.
In contrast, the following figure shows how a similar example with default typographic properties renders.
   par.Inlines.Add(runText);
   par.Inlines.Add(new LineBreak());
   par.Inlines.Add(new LineBreak());
   par.Inlines.Add(runNumerals);
   par.Inlines.Add(new LineBreak());
   par.Inlines.Add(new LineBreak());
   par.Inlines.Add(runFractions);
   par.TextAlignment = TextAlignment.Left;
   par.FontSize = 18;
   par.FontFamily = new FontFamily("Palatino Linotype");
   par.Typography.NumeralStyle = FontNumeralStyle.OldStyle;
   par.Typography.Fraction = FontFraction.Stacked;
   par.Typography.Variants = FontVariants.Inferior;
   Dim runText As New Run("This text has some altered typography characteristics. Note" & "that use of an open
   type font is necessary for most typographic" & "properties to be effective.")
   Dim runNumerals As New Run("0123456789 10 11 12 13")
   Dim runFractions As New Run("1/2 2/3 3/4")
   par.Inlines.Add(runText)
   par.Inlines.Add(New LineBreak())
   par.Inlines.Add(New LineBreak())
   par.Inlines.Add(runNumerals)
   par.Inlines.Add(New LineBreak())
   par.Inlines.Add(New LineBreak())
   par.Inlines.Add(runFractions)
   par.TextAlignment = TextAlignment.Left
   par.FontSize = 18
   par.FontFamily = New FontFamily("Palatino Linotype")
   par.Typography.NumeralStyle = FontNumeralStyle.OldStyle
   par.Typography.Fraction = FontFraction.Stacked
   par.Typography.Variants = FontVariants.Inferior
See also
   Flow Document Overview
       How to: Enable Text Trimming
       11/21/2022 • 2 minutes to read • Edit Online
This example demonstrates the usage and effects of the values available in the TextTrimming enumeration.
Example
The following example defines a TextBlock element with the TextTrimming attribute set.
   <TextBlock
     Name="myTextBlock"
     Margin="20" Background="LightGoldenrodYellow"
     TextTrimming="WordEllipsis" TextWrapping="NoWrap"
     FontSize="14"
   >
     One<LineBreak/>
     two two<LineBreak/>
     Three Three Three<LineBreak/>
     four four four four<LineBreak/>
     Five Five Five Five Five<LineBreak/>
     six six six six six six<LineBreak/>
     Seven Seven Seven Seven Seven Seven Seven
   </TextBlock>
myTextBlock.TextTrimming = TextTrimming.CharacterEllipsis;
myTextBlock.TextTrimming = TextTrimming.CharacterEllipsis
There are currently three options for trimming text: CharacterEllipsis , WordEllipsis , and None .
When TextTrimming is set to CharacterEllipsis , text is trimmed and continued with an ellipsis at the character
closest to the trimming edge. This setting tends to trim text to fit more closely to the trimming boundary, but
may result in words being partially trimmed. The following figure shows the effect of this setting on a TextBlock
similar to the one defined above.
When TextTrimming is set to WordEllipsis , text is trimmed and continued with an ellipsis at the end of the first
full word closest to the trimming edge. This setting will not show partially trimmed words, but tends not to trim
text as closely to the trimming edge as the CharacterEllipsis setting. The following figure shows the effect of
this setting on the TextBlock defined above.
When TextTrimming is set to None , no text trimming is performed. In this case, text is simply cropped to the
boundary of the parent text container. The following figure shows the effect of this setting on a TextBlock similar
to the one defined above.
       How to: Insert an Element Into Text
       Programmatically
       11/21/2022 • 2 minutes to read • Edit Online
The following example shows how to use two TextPointer objects to specify a range within text to apply a Span
element to.
Example
   using   System;
   using   System.Windows;
   using   System.Windows.Media;
   using   System.Windows.Controls;
   using   System.Windows.Documents;
   namespace SDKSample
   {
       public partial class InsertInlineIntoTextExample : Page
       {
           public InsertInlineIntoTextExample()
           {
                 // Create two TextPointers that will specify the text range the Span will cover
                 TextPointer myTextPointer1 = myParagraph.ContentStart.GetPositionAtOffset(10);
                 TextPointer myTextPointer2 = myParagraph.ContentEnd.GetPositionAtOffset(-5);
                 // Create a Span that covers the range between the two TextPointers.
                 Span mySpan = new Span(myTextPointer1, myTextPointer2);
                 mySpan.Background = Brushes.Red;
                 this.Content = myFlowDocument;
             }
       }
   }
   Imports   System.Windows
   Imports   System.Windows.Media
   Imports   System.Windows.Controls
   Imports   System.Windows.Documents
   Namespace SDKSample
       Partial Public Class InsertInlineIntoTextExample
           Inherits Page
           Public Sub New()
                 ' Create two TextPointers that will specify the text range the Span will cover
                 Dim myTextPointer1 As TextPointer = myParagraph.ContentStart.GetPositionAtOffset(10)
                 Dim myTextPointer2 As TextPointer = myParagraph.ContentEnd.GetPositionAtOffset(-5)
                 ' Create a Span that covers the range between the two TextPointers.
                 Dim mySpan As New Span(myTextPointer1, myTextPointer2)
                 mySpan.Background = Brushes.Red
Me.Content = myFlowDocument
           End Sub
       End Class
   End Namespace
See also
   Flow Document Overview
      How to: Manipulate Flow Content Elements through
      the Blocks Property
      11/21/2022 • 2 minutes to read • Edit Online
These examples demonstrate some of the more common operations that can be performed on flow content
elements through the Blocks property. This property is used to add and remove items from BlockCollection.
Flow content elements that feature a Blocks property include:
   Figure
   Floater
   ListItem
   Section
   TableCell
These examples happen to use Section as the flow content element, but these techniques are applicable to all
elements that host a flow content element collection.
secx.Blocks.Remove(secx.Blocks.LastBlock);
secx.Blocks.Remove(secx.Blocks.LastBlock)
secx.Blocks.Clear();
secx.Blocks.Clear()
See also
   BlockCollection
   InlineCollection
   ListItemCollection
   Flow Document Overview
   Manipulate a Table's Row Groups through the RowGroups Property
   Manipulate a Table's Columns through the Columns Property
   Manipulate a Table's Row Groups through the RowGroups Property
       How to: Manipulate Flow Content Elements through
       the Inlines Property
       11/21/2022 • 2 minutes to read • Edit Online
These examples demonstrate some of the more common operations that can be performed on inline flow
content elements (and containers of such elements, such as TextBlock) through the Inlines property. This
property is used to add and remove items from InlineCollection. Flow content elements that feature an Inlines
property include:
   Bold
   Hyperlink
   Italic
   Paragraph
   Span
   Underline
These examples happen to use Span as the flow content element, but these techniques are applicable to all
elements or controls that host an InlineCollection collection.
spanx.Inlines.Remove(spanx.Inlines.LastInline);
spanx.Inlines.Remove(spanx.Inlines.LastInline)
spanx.Inlines.Clear();
spanx.Inlines.Clear()
See also
   BlockCollection
   InlineCollection
   ListItemCollection
   Flow Document Overview
   Manipulate a FlowDocument through the Blocks Property
   Manipulate a Table's Columns through the Columns Property
   Manipulate a Table's Row Groups through the RowGroups Property
      How to: Manipulate a FlowDocument through the
      Blocks Property
      11/21/2022 • 2 minutes to read • Edit Online
These examples demonstrate some of the more common operations that can be performed on a FlowDocument
through the Blocks property.
   flowDoc.Blocks.Remove(flowDoc.Blocks.LastBlock);
   flowDoc.Blocks.Remove(flowDoc.Blocks.LastBlock)
flowDoc.Blocks.Clear();
flowDoc.Blocks.Clear()
See also
   Manipulate a Table's Row Groups through the RowGroups Property
   Manipulate a Table's Columns through the Columns Property
   Manipulate a Table's Row Groups through the RowGroups Property
       How to: Manipulate a Table's Columns through the
       Columns Property
       11/21/2022 • 2 minutes to read • Edit Online
This example demonstrates some of the more common operations that can be performed on a table's columns
through the Columns property.
  NOTE
  The TableColumnCollection collection uses standard zero-based indexing.
tbl.Columns.Remove(tbl.Columns[3]);
tbl.Columns.Remove(tbl.Columns(3))
tbl.Columns.RemoveAt(2);
tbl.Columns.RemoveAt(2)
tbl.Columns.Clear();
tbl.Columns.Clear()
See also
   Table Overview
   Define a Table with XAML
   Build a Table Programmatically
   Manipulate a Table's Row Groups through the RowGroups Property
   Manipulate a FlowDocument through the Blocks Property
   Manipulate a Table's Row Groups through the RowGroups Property
       How to: Manipulate a Table's Row Groups through
       the RowGroups Property
       11/21/2022 • 2 minutes to read • Edit Online
This example demonstrates some of the more common operations that can be performed on a table's row
groups through the RowGroups property.
  NOTE
  The TableRowGroupCollection collection uses standard zero-based indexing.
tbl.RowGroups.Remove(tbl.RowGroups[0]);
tbl.RowGroups.Remove(tbl.RowGroups(0))
tbl.RowGroups.RemoveAt(0);
tbl.RowGroups.RemoveAt(0)
Remove all row groups from the table's row groups collection
The following example removes all row groups from the table's row groups collection.
tbl.RowGroups.Clear();
tbl.RowGroups.Clear()
See also
   How-to: Manipulate Flow Content Elements through the Inlines Property
   Manipulate a FlowDocument through the Blocks Property
   Manipulate a Table's Columns through the Columns Property
       How to: Use Flow Content Elements
      11/21/2022 • 2 minutes to read • Edit Online
The following example demonstrates declarative usage for various flow content elements and associated
attributes. Elements and attributes demonstrated include:
   Bold element
   BreakPageBefore attribute
   FontSize attribute
   Italic element
   LineBreak element
   List element
   ListItem element
   Paragraph element
   Run element
   Section element
   Span element
   Variants attribute (superscript and subscript)
   Underline element
Example
   <FlowDocument
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   >
       <Paragraph FontSize="18">Flow Format Example</Paragraph>
       <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.
       </Paragraph>
       <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.
       </Paragraph>
       <List>
         <ListItem><Paragraph>ListItem   1</Paragraph></ListItem>
         <ListItem><Paragraph>ListItem   2</Paragraph></ListItem>
         <ListItem><Paragraph>ListItem   3</Paragraph></ListItem>
         <ListItem><Paragraph>ListItem   4</Paragraph></ListItem>
      <ListItem><Paragraph>ListItem 4</Paragraph></ListItem>
      <ListItem><Paragraph>ListItem 5</Paragraph></ListItem>
    </List>
    <Paragraph><Bold>Bolded</Bold></Paragraph>
    <Paragraph><Underline>Underlined</Underline></Paragraph>
    <Paragraph><Bold><Underline>Bolded and Underlined</Underline></Bold></Paragraph>
    <Paragraph><Italic>Italic</Italic></Paragraph>
    <Paragraph>
      <Run Typography.Variants="Superscript">This text is Superscripted.</Run> This text isn't.
    </Paragraph>
    <Paragraph>
      <Run Typography.Variants="Subscript">This text is Subscripted.</Run> This text isn't.
    </Paragraph>
    <Paragraph>
      If a font does not support a particular form (such as Superscript) a default font form will be
displayed.
    </Paragraph>
    <Paragraph><LineBreak/></Paragraph>
    <Section><Paragraph>... and another section, preceded by a LineBreak</Paragraph></Section>
    <Section BreakPageBefore="True"/>
    <Section><Paragraph>... and another section, preceded by a PageBreak</Paragraph></Section>
<Paragraph><LineBreak/></Paragraph>
</FlowDocument>
      How to: Use FlowDocument Column-Separating
      Attributes
      11/21/2022 • 2 minutes to read • Edit Online
Example
The following example defines a FlowDocument, and sets the ColumnGap, ColumnRuleBrush, and
ColumnRuleWidth attributes. The FlowDocument contains a single paragraph of sample content.
   <FlowDocumentReader>
     <FlowDocument
       ColumnGap="20.0"
       ColumnRuleBrush="DodgerBlue"
       ColumnRuleWidth="5.0"
       ColumnWidth="140.0"
   >
       <Paragraph Background="AntiqueWhite" TextAlignment="Left">
         This paragraph has the background set to antique white to make its
         boundaries obvious.
         The column gap is the space between columns; this FlowDocument will
         have a column gap of 20 device-independend pixels. The column rule
         is a vertical line drawn in the column gap, and is used to visually
         separate columns; this FlowDocument a Dodger-blue column rule that
         is 5 pixels wide.
         The column rule and column gap both take space between columns. In
         this case, a column gap width of 20 plus a column rule of width of 5
         results in the space between columns being 25 pixels wide, 5 pixels
         for the column rule, and 10 pixels of column gap on either side of the column rule.
       </Paragraph>
     </FlowDocument>
   </FlowDocumentReader>
The following figure shows the effects of the ColumnGap, ColumnRuleBrush, and ColumnRuleWidth attributes
in a rendered FlowDocument.
      Typography
      11/21/2022 • 2 minutes to read • Edit Online
WPF is rendered using Microsoft ClearType, which enhances the clarity and readability of text. WPF also
supports OpenType fonts, which provide additional capabilities beyond those defined by the TrueType®
format.
In This Section
Typography in WPF
ClearType Overview
ClearType Registry Settings
Drawing Formatted Text
Advanced Text Formatting
Fonts
Glyphs
How-to Topics
See also
   Typography
   Documents in WPF
   OpenType Font Features
   Optimizing WPF Application Performance
       Typography in WPF
       11/21/2022 • 6 minutes to read • Edit Online
This topic introduces the major typographic features of WPF. These features include improved quality and
performance of text rendering, OpenType typography support, enhanced international text, enhanced font
support, and new text application programming interfaces (APIs).
In addition, animated text, whether by character or glyph, takes full advantage of the graphics hardware
capability enabled by WPF. This results in smooth text animation.
Rich Typography
The OpenType font format is an extension of the TrueType® font format. The OpenType font format was
developed jointly by Microsoft and Adobe, and provides a rich assortment of advanced typographic features.
The Typography object exposes many of the advanced features of OpenType fonts, such as stylistic alternates
and swashes. The Windows SDK provides a set of sample OpenType fonts that are designed with rich features,
such as the Pericles and Pescadero fonts. For more information, see Sample OpenType Font Pack.
The Pericles OpenType font contains additional glyphs that provide stylistic alternates to the standard set of
glyphs. The following text displays stylistic alternate glyphs.
Swashes are decorative glyphs that use elaborate ornamentation often associated with calligraphy. The
following text displays standard and swash glyphs for the Pescadero font.
The following example shows a drop shadow effect and noise applied to text.
The following example shows the second line of text scaled by 150% along the x-axis, and the third line of text
scaled by 150% along the y-axis.
A TextEffect object is a helper object that allows you to treat text as one or more groups of characters in a text
string. The following example shows an individual character being rotated. Each character is rotated
independently at 1-second intervals.
You can convert formatted text into Geometry objects, allowing you to create other types of visually interesting
text. For example, you could create a Geometry object based on the outline of a text string.
The following examples illustrate several ways of creating interesting visual effects by modifying the stroke, fill,
and highlight of converted text.
For more information on the FormattedText object, see Drawing Formatted Text.
Advanced Text Formatting
At the most advanced level of the text APIs, WPF offers you the ability to create custom text layout by using the
TextFormatter object and other types in the System.Windows.Media.TextFormatting namespace. The
TextFormatter and associated classes allow you to implement custom text layout that supports your own
definition of character formats, paragraph styles, line breaking rules, and other layout features for international
text. There are very few cases in which you would want to override the default implementation of the WPF text
layout support. However, if you were creating a text editing control or application, you might require a different
implementation than the default WPF implementation.
Unlike a traditional text API, the TextFormatter interacts with a text layout client through a set of callback
methods. It requires the client to provide these methods in an implementation of the TextSource class. The
following diagram illustrates the text layout interaction between the client application and TextFormatter.
For more details on creating custom text layout, see Advanced Text Formatting.
See also
   FormattedText
TextFormatter
ClearType Overview
OpenType Font Features
Drawing Formatted Text
Advanced Text Formatting
Text
Microsoft Typography
       ClearType Overview
       11/21/2022 • 3 minutes to read • Edit Online
This topic provides an overview of the Microsoft ClearType technology found in the Windows Presentation
Foundation (WPF).
Technology Overview
ClearType is a software technology developed by Microsoft that improves the readability of text on existing LCDs
(Liquid Crystal Displays), such as laptop screens, Pocket PC screens and flat panel monitors. ClearType works by
accessing the individual vertical color stripe elements in every pixel of an LCD screen. Before ClearType, the
smallest level of detail that a computer could display was a single pixel, but with ClearType running on an LCD
monitor, we can now display features of text as small as a fraction of a pixel in width. The extra resolution
increases the sharpness of the tiny details in text display, making it much easier to read over long durations.
The ClearType available in Windows Presentation Foundation (WPF) is the latest generation of ClearType which
has several improvements over version found in Microsoft Windows Graphics Device Interface (GDI).
Sub-pixel Positioning
A significant improvement over the previous version of ClearType is the use of sub-pixel positioning. Unlike the
ClearType implementation found in GDI, the ClearType found in Windows Presentation Foundation (WPF) allows
glyphs to start within the pixel and not just the beginning boundary of the pixel. Because of this extra resolution
in positioning glyphs, the spacing and proportions of the glyphs is more precise and consistent.
The following two examples show how glyphs may begin on any sub-pixel boundary when sub-pixel
positioning is used. The example on the left is rendered using the earlier version of the ClearType renderer,
which did not employ sub-pixel positioning. The example on the right is rendered using the new version of the
ClearType renderer, using sub-pixel positioning. Note how each e and l in the right-hand image is rendered
slightly differently because each starts on a different sub-pixel. When viewing the text at its normal size on the
screen, this difference is not noticeable because of the high contrast of the glyph image. This is only possible
because of sophisticated color filtering that is incorporated in ClearType.
Text displayed with earlier and later versions of ClearType
The following two examples compare output from the earlier ClearType renderer with the new version of the
ClearType renderer. The subpixel positioning, shown on the right, greatly improves the spacing of type on
screen, especially at small sizes where the difference between a sub-pixel and a whole pixel represents a
significant proportion of glyph width. Note that spacing between the letters is more even in the second image.
The cumulative benefit of sub-pixel positioning to the overall appearance of a screen of text is greatly increased,
and represents a significant evolution in ClearType technology.
Y-Direction Antialiasing
Another improvement of ClearType in Windows Presentation Foundation (WPF) is y-direction anti-aliasing. The
ClearType in GDI without y-direction anti-aliasing provides better resolution on the x-axis but not the y-axis. On
the tops and bottoms of shallow curves, the jagged edges detract from its readability.
The following example shows the effect of having no y-direction antialiasing. In this case, the jagged edges on
the top and bottom of the letter are apparent.
Hardware Acceleration
ClearType in Windows Presentation Foundation (WPF) can take advantage of hardware acceleration for better
performance and to reduce CPU load and system memory requirements. By using the pixel shaders and video
memory of a graphics card, ClearType provides faster rendering of text, particularly when animation is used.
ClearType in Windows Presentation Foundation (WPF) does not modify the system-wide ClearType settings.
Disabling ClearType in Windows sets Windows Presentation Foundation (WPF) antialiasing to grayscale mode.
In addition, ClearType in Windows Presentation Foundation (WPF) does not modify the settings of the ClearType
Tuner PowerToy.
One of the Windows Presentation Foundation (WPF) architectural design decisions is to have resolution
independent layout better support higher resolution DPI monitors, which are becoming more widespread. This
has the consequence of Windows Presentation Foundation (WPF) not supporting aliased text rendering or the
bitmaps in some East Asian fonts because they are both resolution dependent.
Further Information
ClearType Information
ClearType Tuner PowerToy
See also
   ClearType Registry Settings
        ClearType Registry Settings
        11/21/2022 • 4 minutes to read • Edit Online
This topic provides an overview of the Microsoft ClearType registry settings that are used by WPF applications.
Technology Overview
WPF applications that render text to a display device use ClearType features to provide an enhanced reading
experience. ClearType is a software technology developed by Microsoft that improves the readability of text on
existing LCDs (Liquid Crystal Displays), such as laptop screens, Pocket PC screens and flat panel monitors.
ClearType works by accessing the individual vertical color stripe elements in every pixel of an LCD screen. For
more information on ClearType, see ClearType Overview.
Text that is rendered with ClearType can appear significantly different when viewed on various display devices.
For example, a small number of monitors implement the color stripe elements in blue, green, red order rather
than the more common red, green, blue (RGB) order.
Text that is rendered with ClearType can also appear significantly different when viewed by individuals with
varying levels of color sensitivity. Some individuals can detect slight differences in color better than others.
In each of these cases, ClearType features need to be modified in order to provide the best reading experience
for each individual.
Registry Settings
WPF specifies four registry settings for controlling ClearType features:
  Gamma level                                                     Describes the level of the pixel color component for a display
                                                                  device.
Text contrast level Describes the level of contrast for displayed text.
These settings can be accessed by an external configuration utility that knows how to reference the identified
WPF ClearType registry settings. These settings can also be created or modified by accessing the values directly
by using the Windows Registry Editor.
If the WPF ClearType registry settings are not set (which is the default state), the WPF application queries the
Windows system parameters information for font smoothing settings.
  NOTE
  For information on enumerating display device names, see the   SystemParametersInfo     Win32 function.
ClearType Level
The ClearType level allows you to adjust the rendering of text based on the color sensitivity and perception of an
individual. For some individuals, the rendering of text that uses ClearType at its highest level does not produce
the best reading experience.
The ClearType level is an integer value that ranges from 0 to 100. The default level is 100, which means
ClearType uses the maximum capability of the color stripe elements of the display device. However, a ClearType
level of 0 renders text as gray scale. By setting the ClearType level somewhere between 0 and 100, you can
create an intermediate level that is suitable to an individual's color sensitivity.
Registry Setting
The registry setting location for the ClearType level is an individual user setting that corresponds to a specific
display device name:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\<displayName>
For each display device name for a user, a ClearTypeLevel DWORD value is defined. The following screenshot
shows the Registry Editor setting for the ClearType level.
  NOTE
  WPF applications render text in one of either two modes, with and without ClearType. When text is rendered without
  ClearType, it is referred to as gray scale rendering.
Gamma Level
The gamma level refers to the nonlinear relationship between a pixel value and luminance. The gamma level
setting should correspond to the physical characteristics of the display device; otherwise, distortions in rendered
output may occur. For example, text may appear too wide or too narrow, or color fringes may appear on the
edges of vertical stems of glyphs.
The gamma level is an integer value that ranges from 1000 to 2200. The default level is 1900.
Registry Setting
The registry setting location for the gamma level is a local machine setting that corresponds to a specific display
device name:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics\<displayName>
For each display device name for a user, a GammaLevel DWORD value is defined. The following screenshot shows
the Registry Editor setting for the gamma level.
Pixel Structure
The pixel structure describes the type of pixels that make up a display device. The pixel structure is defined as
one of three types:
The pixel structure corresponds to an integer value that ranges from 0 to 2. The default level is 0, which
represents a flat pixel structure.
  NOTE
  For information on enumerating display device names, see the   EnumDisplayDevices   Win32 function.
Registry Setting
The registry setting location for the pixel structure is a local machine setting that corresponds to a specific
display device name:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics\<displayName>
For each display device name for a user, a PixelStructure DWORD value is defined. The following screenshot
shows the Registry Editor setting for the pixel structure.
Text Contrast Level
The text contrast level allows you to adjust the rendering of text based on the stem widths of glyphs. The text
contrast level is an integer value that ranges from 0 to 6—the larger the integer value, the wider the stem. The
default level is 1.
Registry Setting
The registry setting location for the text contrast level is an individual user setting that corresponds to a specific
display device name:
HKEY_CURRENT_USER\Software\Microsoft\Avalon.Graphics\<displayName>
For each display device name for a user, a TextContrastLevel DWORD value is defined. The following
screenshot shows the Registry Editor setting for the text contrast level.
See also
   ClearType Overview
   ClearType Antialiasing
       Drawing Formatted Text
       11/21/2022 • 7 minutes to read • Edit Online
This topic provides an overview of the features of the FormattedText object. This object provides low-level
control for drawing text in Windows Presentation Foundation (WPF) applications.
Technology Overview
The FormattedText object allows you to draw multi-line text, in which each character in the text can be
individually formatted. The following example shows text that has several formats applied to it.
  NOTE
  For those developers migrating from the Win32 API, the table in the Win32 Migration section lists the Win32 DrawText
  flags and the approximate equivalent in Windows Presentation Foundation (WPF).
       // Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
       formattedText.MaxTextWidth = 300;
       formattedText.MaxTextHeight = 240;
       // Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
       // The font size is calculated in terms of points -- not as device-independent pixels.
       formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
       // Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
       formattedText.SetFontWeight(FontWeights.Bold, 6, 11);
       // Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
       formattedText.SetForegroundBrush(
                               new LinearGradientBrush(
                               Colors.Orange,
                               Colors.Teal,
                               90.0),
                               6, 11);
       // Use an Italic font style beginning at the 28th character and continuing for 28 characters.
       formattedText.SetFontStyle(FontStyles.Italic, 28, 28);
       ' Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
       formattedText.MaxTextWidth = 300
       formattedText.MaxTextHeight = 240
       ' Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
       ' The font size is calculated in terms of points -- not as device-independent pixels.
       formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5)
       ' Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
       formattedText.SetFontWeight(FontWeights.Bold, 6, 11)
       ' Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
       formattedText.SetForegroundBrush(New LinearGradientBrush(Colors.Orange, Colors.Teal, 90.0), 6, 11)
       ' Use an Italic font style beginning at the 28th character and continuing for 28 characters.
       formattedText.SetFontStyle(FontStyles.Italic, 28, 28)
       ' Draw the formatted text string to the DrawingContext of the control.
       drawingContext.DrawText(formattedText, New Point(10, 0))
   End Sub
   ' The font size is calculated in terms of points -- not as device-independent pixels.
   formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5)
The following examples illustrate several ways of creating interesting visual effects by modifying the stroke, fill,
and highlight of converted text.
When text is converted to a Geometry object, it is no longer a collection of characters—you cannot modify the
characters in the text string. However, you can affect the appearance of the converted text by modifying its
stroke and fill properties. The stroke refers to the outline of the converted text; the fill refers to the area inside
the outline of the converted text. For more information, see Create Outlined Text.
You can also convert formatted text to a PathGeometry object, and use the object for highlighting the text. For
example, you could apply an animation to the PathGeometry object so that the animation follows the outline of
the formatted text.
The following example shows formatted text that has been converted to a PathGeometry object. An animated
ellipse follows the path of the strokes of the rendered text.
Win32 Migration
The features of FormattedText for drawing text are similar to the features of the Win32 DrawText function. For
those developers migrating from the Win32 API, the following table lists the Win32 DrawText flags and the
approximate equivalent in Windows Presentation Foundation (WPF).
See also
  FormattedText
  Documents in WPF
  Typography in WPF
  Create Outlined Text
  How to: Create a PathGeometry Animation for Text
       Advanced Text Formatting
       11/21/2022 • 7 minutes to read • Edit Online
Windows Presentation Foundation (WPF) provides a robust set of APIs for including text in your application.
Layout and user interface (UI) APIs, such as TextBlock, provide the most common and general-use elements for
text presentation. Drawing APIs, such as GlyphRunDrawing and FormattedText, provide a means for including
formatted text in drawings. At the most advanced level, WPF provides an extensible text formatting engine to
control every aspect of text presentation, such as text store management, text run formatting management, and
embedded object management.
This topic provides an introduction to WPF text formatting. It focuses on client implementation and use of the
WPF text formatting engine.
  NOTE
  All code examples within this document can be found in the Advanced Text Formatting Sample.
Prerequisites
This topic assumes that you are familiar with the higher level APIs used for text presentation. Most user
scenarios will not require the advanced text formatting APIs discussed in this topic. For an introduction to the
different text APIs, see Documents in WPF.
// Format each line of text from the text store and draw it.
while (textStorePosition < _textStore.Text.Length)
{
   // Create a textline from the text store using the TextFormatter object.
   using (TextLine myTextLine = formatter.FormatLine(
       _textStore,
       textStorePosition,
       96*6,
       new GenericTextParagraphProperties(_currentRendering),
       null))
   {
       // Draw the formatted text into the drawing context.
       myTextLine.Draw(dc, linePosition, InvertAxes.None);
   ' Format each line of text from the text store and draw it.
   Do While textStorePosition < _textStore.Text.Length
      ' Create a textline from the text store using the TextFormatter object.
      Using myTextLine As TextLine = formatter.FormatLine(_textStore, textStorePosition, 96*6, New
   GenericTextParagraphProperties(_currentRendering), Nothing)
          ' Draw the formatted text into the drawing context.
          myTextLine.Draw(dc, linePosition, InvertAxes.None)
          ' Update the line position coordinate for the displayed line.
          linePosition.Y += myTextLine.Height
      End Using
   Loop
TextEndOfLine The specialized text run used to mark the end of a line.
  TextEndOfSegment                                             The specialized text run used to mark the end of a segment,
                                                               such as to end the scope affected by a previous TextModifier
                                                               run.
Any of the predefined TextRun objects can be subclassed. This allows your text source to provide the text
formatter with text runs that include custom data.
The following example demonstrates a GetTextRun method. This text store returns TextRun objects to the text
formatter for processing.
   // Used by the TextFormatter object to retrieve a run of text from the text source.
   public override TextRun GetTextRun(int textSourceCharacterIndex)
   {
      // Make sure text source index is in bounds.
      if (textSourceCharacterIndex < 0)
         throw new ArgumentOutOfRangeException("textSourceCharacterIndex", "Value must be greater than 0.");
      if (textSourceCharacterIndex >= _text.Length)
      {
         return new TextEndOfParagraph(1);
      }
  NOTE
  In this example, the text store provides the same text properties to all of the text. Advanced text stores would need to
  implement their own span management to allow individual characters to have different properties.
See also
   Typography in WPF
   Documents in WPF
      Fonts (WPF)
      11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) includes support for rich presentation of text using OpenType fonts. A
sample pack of OpenType fonts is included with the Windows SDK.
In This Section
OpenType Font Features
Packaging Fonts with Applications
Sample OpenType Font Pack
How-to Topics
See also
   FontStyle
   SystemFonts
   Documents in WPF
   Typography in WPF
       OpenType Font Features
       11/21/2022 • 12 minutes to read • Edit Online
This topic provides an overview of some of the key features of OpenType font technology in Windows
Presentation Foundation (WPF).
  NOTE
  The Windows SDK contains a set of sample OpenType fonts that you can use with Windows Presentation Foundation
  (WPF) applications. These fonts provide most of the features illustrated in the rest of this topic. For more information, see
  Sample OpenType Font Pack.
For details of the OpenType font format, see the OpenType specification.
Advanced Typographic Extensions
The Advanced Typographic tables (OpenType Layout tables) extend the functionality of fonts with either
TrueType or CFF outlines. OpenType Layout fonts contain additional information that extends the capabilities of
the fonts to support high-quality international typography. Most OpenType fonts expose only a subset of the
total OpenType features available. OpenType fonts provide the following features.
   Rich mapping between characters and glyphs that support ligatures, positional forms, alternates, and
   other font substitutions.
   Support for two-dimensional positioning and glyph attachment.
   Explicit script and language information contained in font, so a text-processing application can adjust its
   behavior accordingly.
The OpenType Layout tables are described in more detail in the "Font File Tables" section of the OpenType
specification.
The remainder of this overview introduces the breadth and flexibility of some of the visually-interesting
OpenType features that are exposed by the properties of the Typography object. For more information on this
object, see Typography Class.
Variants
Variants are used to render different typographic styles, such as superscripts and subscripts.
Superscripts and Subscripts
The Variants property allows you to set superscript and subscript values for an OpenType font.
The following text displays superscripts for the Palatino Linotype font.
The following markup example shows how to define superscripts for the Palatino Linotype font, using properties
of the Typography object.
The following text displays subscripts for the Palatino Linotype font.
The following markup example shows how to define subscripts for the Palatino Linotype font, using properties
of the Typography object.
The following markup example shows how to define superscripts and subscripts for a font, using properties of
the Typography object.
Capitals
Capitals are a set of typographical forms that render text in capital-styled glyphs. Typically, when text is rendered
as all capitals, the spacing between letters can appear too tight, and the weight and proportion of the letters too
heavy. OpenType supports a number of styling formats for capitals, including small capitals, petite capitals,
titling, and capital spacing. These styling formats allow you to control the appearance of capitals.
The following text displays standard capital letters for the Pescadero font, followed by the letters styled as
"SmallCaps" and "AllSmallCaps". In this case, the same font size is used for all three words.
The following markup example shows how to define capitals for the Pescadero font, using properties of the
Typography object. When the "SmallCaps" format is used, any leading capital letter is ignored.
Titling Capitals
Titling capitals are lighter in weight and proportion and designed to give a more elegant look than normal
capitals. Titling capitals are typically used in larger font sizes as headings. The following text displays normal and
titling capitals for the Pescadero font. Notice the narrower stem widths of the text on the second line.
The following markup example shows how to define titling capitals for the Pescadero font, using properties of
the Typography object.
   <Paragraph FontFamily="Pescadero">
     <Run Typography.Capitals="Titling">chapter one</Run>
   </Paragraph>
Capital Spacing
Capital spacing is a feature that allows you to provide more spacing when using all capitals in text. Capital letters
are typically designed to blend with lowercase letters. Spacing that appears attractive between and a capital
letter and a lowercase letter may look too tight when all capital letters are used. The following text displays
normal and capital spacing for the Pescadero font.
The following markup example shows how to define capital spacing for the Pescadero font, using properties of
the Typography object.
   <Paragraph FontFamily="Pescadero">
     <Run Typography.CapitalSpacing="True">CHAPTER ONE</Run>
   </Paragraph>
Ligatures
Ligatures are two or more glyphs that are formed into a single glyph in order to create more readable or
attractive text. OpenType fonts support four types of ligatures:
   Standard ligatures . Designed to enhance readability. Standard ligatures include "fi", "fl", and "ff".
   Contextual ligatures . Designed to enhance readability by providing better joining behavior between
   the characters that make up the ligature.
   Discretionar y ligatures . Designed to be ornamental, and not specifically designed for readability.
   Historical ligatures . Designed to be historical, and not specifically designed for readability.
The following text displays standard ligature glyphs for the Pericles font.
The following markup example shows how to define standard ligature glyphs for the Pericles font, using
properties of the Typography object.
The following text displays discretionary ligature glyphs for the Pericles font.
The following markup example shows how to define discretionary ligature glyphs for the Pericles font, using
properties of the Typography object.
By default, OpenType fonts in Windows Presentation Foundation (WPF) enable standard ligatures. For example,
if you use the Palatino Linotype font, the standard ligatures "fi", "ff", and "fl" appear as a combined character
glyph. Notice that the pair of characters for each standard ligature touch each other.
However, you can disable standard ligature features so that a standard ligature such as "ff" displays as two
separate glyphs, rather than as a combined character glyph.
The following markup example shows how to disable standard ligature glyphs for the Palatino Linotype font,
using properties of the Typography object.
Swashes
Swashes are decorative glyphs that use elaborate ornamentation often associated with calligraphy. The
following text displays standard and swash glyphs for the Pescadero font.
Swashes are often used as decorative elements in short phrases such as event announcements. The following
text uses swashes to emphasize the capital letters of the name of the event.
The following markup example shows how to define swashes for a font, using properties of the Typography
object.
Contextual Swashes
Certain combinations of swash glyphs can cause an unattractive appearance, such as overlapping descenders on
adjacent letters. Using a contextual swash allows you to use a substitute swash glyph that produces a better
appearance. The following text shows the same word before and after a contextual swash is applied.
The following markup example shows how to define a contextual swash for the Pescadero font, using properties
of the Typography object.
   <Paragraph FontFamily="Pescadero" Typography.StandardSwashes="1">
     Lyon <Run Typography.ContextualSwashes="1">L</Run>yon
   </Paragraph>
Alternates
Alternates are glyphs that can be substituted for a standard glyph. OpenType fonts, such as the Pericles font
used in the following examples, can contain alternate glyphs that you can use to create different appearances for
text. The following text displays standard glyphs for the Pericles font.
The Pericles OpenType font contains additional glyphs that provide stylistic alternates to the standard set of
glyphs. The following text displays stylistic alternate glyphs.
The following markup example shows how to define stylistic alternate glyphs for the Pericles font, using
properties of the Typography object.
   <Paragraph FontFamily="Pericles">
     <Run Typography.StylisticAlternates="1">A</Run>NCIENT
     GR<Run Typography.StylisticAlternates="1">EE</Run>K
     MYTH<Run Typography.StylisticAlternates="1">O</Run>LOGY
   </Paragraph>
The following text displays several other stylistic alternate glyphs for the Pericles font.
The following markup example shows how to define these other stylistic alternate glyphs.
   <Paragraph FontFamily="Pericles">
     <Run Typography.StylisticAlternates="1">A</Run>
     <Run Typography.StylisticAlternates="2">A</Run>
     <Run Typography.StylisticAlternates="3">A</Run>
     <Run Typography.StylisticAlternates="1">C</Run>
     <Run Typography.StylisticAlternates="1">E</Run>
     <Run Typography.StylisticAlternates="1">G</Run>
     <Run Typography.StylisticAlternates="1">O</Run>
     <Run Typography.StylisticAlternates="1">Q</Run>
     <Run Typography.StylisticAlternates="1">R</Run>
     <Run Typography.StylisticAlternates="2">R</Run>
     <Run Typography.StylisticAlternates="1">S</Run>
     <Run Typography.StylisticAlternates="1">Y</Run>
   </Paragraph>
   <TextBlock FontFamily="Lindsey">
     <Run Typography.ContextualAlternates="True">
       a banana in a cabana
     </Run>
   </TextBlock>
Historical Forms
Historical forms are typographic conventions that were common in the past. The following text displays the
phrase, "Boston, Massachusetts", using an historical form of glyphs for the Palatino Linotype font.
The following markup example shows how to define historical forms for the Palatino Linotype font, using
properties of the Typography object.
Numerical Styles
OpenType fonts support a large number of features that can be used with numerical values in text.
Fractions
OpenType fonts support styles for fractions, including slashed and stacked.
The following text displays fraction styles for the Palatino Linotype font.
The following markup example shows how to define fraction styles for the Palatino Linotype font, using
properties of the Typography object.
The following markup example shows how to define old style numerals for the Palatino Linotype font, using
properties of the Typography object.
The following markup example shows how to define proportional and tabular figures for the Miramonte font,
using properties of the Typography object.
   <TextBlock FontFamily="Miramonte">
     <Run Typography.NumeralAlignment="Proportional">114,131</Run>
   </TextBlock>
   <TextBlock FontFamily="Miramonte">
     <Run Typography.NumeralAlignment="Tabular">114,131</Run>
   </TextBlock>
Slashed Zero
OpenType fonts support a slashed zero numeral format to emphasize the difference between the letter "O" and
the numeral "0". The slashed zero numeral is often used for identifiers in financial and business information.
The following text displays a sample order identifier using the Miramonte font. The first line uses standard
numerals. The second line used slashed zero numerals to provide better contrast with the uppercase "O" letter.
The following markup example shows how to define slashed zero numerals for the Miramonte font, using
properties of the Typography object.
   <Paragraph FontFamily="Miramonte">
     <Run>Order #0048-OTC-390</Run>
     <LineBreak/>
     <Run Typography.SlashedZero="True">Order #0048-OTC-390</Run>
   </Paragraph>
Typography Class
The Typography object exposes the set of features that an OpenType font supports. By setting the properties of
Typography in markup, you can easily author documents that take advantage of OpenType features.
The following text displays standard capital letters for the Pescadero font, followed by the letters styled as
"SmallCaps" and "AllSmallCaps". In this case, the same font size is used for all three words.
The following markup example shows how to define capitals for the Pescadero font, using properties of the
Typography object. When the "SmallCaps" format is used, any leading capital letter is ignored.
The following code example accomplishes the same task as the previous markup example.
   MyParagraph.Inlines.Add(new LineBreak());
   MyParagraph.FontFamily = New FontFamily("Pescadero")
   MyParagraph.FontSize = 48
MyParagraph.Inlines.Add(New LineBreak())
See also
  Typography
  OpenType specification
  Typography in WPF
  Sample OpenType Font Pack
  Packaging Fonts with Applications
       Packaging Fonts with Applications
       11/21/2022 • 7 minutes to read • Edit Online
This topic provides an overview of how to package fonts with your Windows Presentation Foundation (WPF)
application.
  NOTE
  As with most types of software, font files are licensed, rather than sold. Licenses that govern the use of fonts vary from
  vendor to vendor but in general most licenses, including those covering the fonts Microsoft supplies with applications and
  Windows, do not allow the fonts to be embedded within applications or otherwise redistributed. Therefore, as a developer
  it is your responsibility to ensure that you have the required license rights for any font you embed within an application
  or otherwise redistribute.
   <Project DefaultTargets="Build"
                   xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     <!-- Other project build settings ... -->
     <ItemGroup>
       <Content Include="Peric.ttf" />
       <Content Include="Pericl.ttf" />
     </ItemGroup>
   </Project>
In order to ensure that the application can use the fonts at run time, the fonts must be accessible in the
application's deployment directory. The <CopyToOutputDirectory> element in the application's project file allows
you to automatically copy the fonts to the application deployment directory during the build process. The
following project file example shows how to copy fonts to the deployment directory.
   <ItemGroup>
     <Content Include="Peric.ttf">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
     <Content Include="Pericl.ttf">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
   </ItemGroup>
The following code example shows how to reference the application's font as a content item—the referenced
content item must be in the same directory as the application's assembly files.
   <Project DefaultTargets="Build"
                   xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     <!-- Other project build settings ... -->
     <ItemGroup>
       <Resource Include="resources\Peric.ttf" />
       <Resource Include="resources\Pericl.ttf" />
     </ItemGroup>
   </Project>
  NOTE
  When you add fonts as resources to your application, make sure you are setting the <Resource> element, and not the
   <EmbeddedResource> element in your application's project file. The <EmbeddedResource> element for the build action is
  not supported.
The following markup example shows how to reference the application's font resources.
   ' The font resource reference includes the base URI reference (application directory level),
   ' and a relative URI reference.
   myTextBlock.FontFamily = New FontFamily(New Uri("pack://application:,,,/"), "./resources/#Pericles Light")
The base uniform resource identifier (URI) can include the application subdirectory where the font resource
resides. In this case, the font location reference would not need to specify a directory, but would have to include
a leading " ./ ", which indicates the font resource is in the same directory specified by the base uniform
resource identifier (URI). The following code example shows an alternate way of referencing the font resource
item—it is equivalent to the previous code example.
   <ItemGroup>
     <Page Include="pages\HomePage.xaml" />
   </ItemGroup>
   <ItemGroup>
     <Resource Include="pages\Peric.ttf" />
     <Resource Include="pages\Pericl.ttf" />
   </ItemGroup>
Since the application content and font are in the same subdirectory, the font reference is relative to the
application content. The following examples show how to reference the application's font resource when the font
is in the same directory as the application.
   // The font resource reference includes the base Uri (application directory level),
   // and the file resource location, which is relative to the base Uri.
   myTextBlock.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "/pages/#Pericles Light");
   ' The font resource reference includes the base Uri (application directory level),
   ' and the file resource location, which is relative to the base Uri.
   myTextBlock.FontFamily = New FontFamily(New Uri("pack://application:,,,/"), "/pages/#Pericles Light")
The following example shows how to use the GetTypefaces method to return the collection of Typeface objects
from the application font location. In this case, the application contains a subdirectory named "resources".
   <PropertyGroup>
     <AssemblyName>FontLibrary</AssemblyName>
     <OutputType>library</OutputType>
     ...
   </PropertyGroup>
   ...
   <ItemGroup>
     <Resource Include="Kooten.ttf" />
     <Resource Include="Pesca.ttf" />
   </ItemGroup
  NOTE
  This SDK contains a set of sample OpenType fonts that you can use with WPF applications. The fonts are defined in a
  resource-only library. For more information, see Sample OpenType Font Pack.
See also
   Typography
   FontFamily
   Microsoft Typography: Links, News, and Contacts
   OpenType Specification
   OpenType Font Features
   Sample OpenType Font Pack
        Sample OpenType Font Pack
        11/21/2022 • 2 minutes to read • Edit Online
This topic provides an overview of the sample OpenType fonts that are distributed with the Windows SDK. The
sample fonts support extended OpenType features that can be used by Windows Presentation Foundation
(WPF) applications.
NAME F IL E
Kootenay Kooten.ttf
Lindsey Linds.ttf
Miramonte Miramo.ttf
Pericles Peric.ttf
Pescadero Pesca.ttf
The following illustration shows what the sample OpenType fonts look like.
The sample fonts are supplied under license from Ascender Corporation. Ascender is a provider of advanced
font products. To license extended or custom versions of the sample fonts, see Ascender Corporation's Web site.
  NOTE
  As a developer it is your responsibility to ensure that you have the required license rights for any font you embed within
  an application or otherwise redistribute.
See also
   Typography
   OpenType Font Features
   Packaging Fonts with Applications
      Fonts How-to Topics
      11/21/2022 • 2 minutes to read • Edit Online
The topics in this section demonstrate how to use the font features included with Windows Presentation
Foundation (WPF).
In This Section
Enumerate System Fonts
Use the FontSizeConverter Class
See also
   FontStyle
   SystemFonts
   Documents in WPF
   Typography in WPF
       How to: Enumerate System Fonts
       11/21/2022 • 2 minutes to read • Edit Online
Example
The following example shows how to enumerate the fonts in the system font collection. The font family name of
each FontFamily within SystemFontFamilies is added as an item to a combo box.
       comboBoxFonts.SelectedIndex = 0;
   }
       comboBoxFonts.SelectedIndex = 0
   End Sub
If multiple versions of the same font family reside in the same directory, the Windows Presentation Foundation
(WPF) font enumeration returns the most recent version of the font. If the version information does not provide
resolution, the font with latest timestamp is returned. If the timestamp information is equivalent, the font file
that is first in alphabetical order is returned.
       How to: Use the FontSizeConverter Class
       11/21/2022 • 2 minutes to read • Edit Online
Example
This example shows how to create an instance of FontSizeConverter and use it to change a font size.
The example defines a custom method called changeSize that converts the contents of a ListBoxItem, as defined
in a separate Extensible Application Markup Language (XAML) file, to an instance of Double, and later into a
String. This method passes the ListBoxItem to a FontSizeConverter object, which converts the Content of a
ListBoxItem to an instance of Double. This value is then passed back as the value of the FontSize property of the
TextBlock element.
This example also defines a second custom method that is called changeFamily . This method converts the
Content of the ListBoxItem to a String, and then passes that value to the FontFamily property of the TextBlock
element.
This example does not run.
See also
   FontSizeConverter
      Glyphs
      11/21/2022 • 2 minutes to read • Edit Online
Glyphs are a low-level depiction of a character to be drawn on-screen. Windows Presentation Foundation (WPF)
provides direct access to glyphs for customers who want to intercept and persist text after formatting.
In This Section
Introduction to the GlyphRun Object and Glyphs Element
How to: Draw Text Using Glyphs
See also
   GlyphRun
   DrawText
   Glyphs
   Documents in WPF
   Typography in WPF
       Introduction to the GlyphRun Object and Glyphs
       Element
       11/21/2022 • 3 minutes to read • Edit Online
This topic describes the GlyphRun object and the Glyphs element.
Introduction to GlyphRun
Windows Presentation Foundation (WPF) provides advanced text support including glyph-level markup with
direct access to Glyphs for customers who want to intercept and persist text after formatting. These features
provide critical support for the different text rendering requirements in each of the following scenarios.
1. Screen display of fixed-format documents.
2. Print scenarios.
      Extensible Application Markup Language (XAML) as a device printer language.
      Microsoft XPS Document Writer.
      Previous printer drivers, output from Win32 applications to the fixed format.
      Print spool format.
3. Fixed-format document representation, including clients for previous versions of Windows and other
   computing devices.
  NOTE
  Glyphs and GlyphRun are designed for fixed-format document presentation and print scenarios. UI scenarios, see the
  Typography in WPF.
<StackPanel Background="PowderBlue">
            <Glyphs
               FontUri               =   "C:\WINDOWS\Fonts\TIMES.TTF"
               FontRenderingEmSize   =   "100"
               StyleSimulations      =   "BoldSimulation"
               UnicodeString         =   "Hello World!"
               Fill                  =   "Black"
               OriginX               =   "100"
               OriginY               =   "200"
            />
      </StackPanel>
   </Page>
The following property definitions correspond to the first four attributes in the sample markup.
  FontRenderingEmSize                                             Specifies the font size in drawing surface units (default is .96
                                                                  inches).
Indices property
The Indices property is a string of glyph specifications. Where a sequence of glyphs forms a single cluster, the
specification of the first glyph in the cluster is preceded by a specification of how many glyphs and how many
code points combine to form the cluster. The Indices property collects in one string the following properties.
   Glyph indices
   Glyph advance widths
   Combining glyph attachment vectors
   Cluster mapping from code points to glyphs
   Glyph flags
Each glyph specification has the following form.
[GlyphIndex][,[Advance][,[uOffset][,[vOffset][,[Flags]]]]]
Glyph Metrics
Each glyph defines metrics that specify how it aligns with other Glyphs. The following graphic defines the
various typographic qualities of two different glyph characters.
Glyphs Markup
The following code example shows how to use various properties of the Glyphs element in XAML.
   <!-- The example shows how to use different property settings of Glyphs objects. -->
   <Canvas
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Background="PowderBlue"
     >
   <Glyphs
      FontUri               =   "C:\WINDOWS\Fonts\ARIAL.TTF"
      FontRenderingEmSize   =   "36"
      StyleSimulations      =   "ItalicSimulation"
      UnicodeString         =   "Hello World!"
      Fill                  =   "SteelBlue"
      OriginX               =   "50"
      OriginY               =   "75"
   />
   <!-- "Hello World!" with     explicit character widths for proportional font -->
   <Glyphs
      FontUri             =     "C:\WINDOWS\Fonts\ARIAL.TTF"
      FontRenderingEmSize =     "36"
      UnicodeString       =     "Hello World!"
      Indices             =     ",80;,80;,80;,80;,80;,80;,80;,80;,80;,80;,80"
      Fill                =     "Maroon"
      OriginX             =     "50"
      OriginY             =     "225"
   />
 <!-- "Hello World!" with   fixed-width font -->
 <Glyphs
      FontUri               =   "C:\WINDOWS\Fonts\COUR.TTF"
      FontRenderingEmSize   =   "36"
      StyleSimulations      =   "BoldSimulation"
      UnicodeString         =   "Hello World!"
      Fill                  =   "Maroon"
      OriginX               =   "50"
      OriginY               =   "300"
 />
</Canvas>
See also
 Typography in WPF
 Documents in WPF
 Text
       Draw Text Using Glyphs
       11/21/2022 • 2 minutes to read • Edit Online
This topic explains how to use the low-level Glyphs object to display text in Extensible Application Markup
Language (XAML).
Example
The following examples show how to define properties for a Glyphs object in XAML. The examples assume that
the Arial, Courier New, and Times New Roman fonts are installed in the C:\WINDOWS\Fonts folder on the local
computer.
<StackPanel Background="PowderBlue">
         <Glyphs
            FontUri                 =   "C:\WINDOWS\Fonts\TIMES.TTF"
            FontRenderingEmSize     =   "100"
            StyleSimulations        =   "BoldSimulation"
            UnicodeString           =   "Hello World!"
            Fill                    =   "Black"
            OriginX                 =   "100"
            OriginY                 =   "200"
         />
      </StackPanel>
   </Page>
This example shows how to define other properties of Glyphs objects in XAML.
   <!-- The example shows how to use different property settings of Glyphs objects. -->
   <Canvas
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Background="PowderBlue"
     >
   <Glyphs
      FontUri               =   "C:\WINDOWS\Fonts\ARIAL.TTF"
      FontRenderingEmSize   =   "36"
      StyleSimulations      =   "ItalicSimulation"
      UnicodeString         =   "Hello World!"
      Fill                  =   "SteelBlue"
      OriginX               =   "50"
      OriginY               =   "75"
   />
 <!-- "Hello World!" with   explicit character widths for proportional font -->
 <Glyphs
    FontUri             =   "C:\WINDOWS\Fonts\ARIAL.TTF"
    FontRenderingEmSize =   "36"
    UnicodeString       =   "Hello World!"
    Indices             =   ",80;,80;,80;,80;,80;,80;,80;,80;,80;,80;,80"
    Fill                =   "Maroon"
    OriginX             =   "50"
    OriginY             =   "225"
 />
</Canvas>
See also
 Typography in WPF
      Typography How-to Topics
      11/21/2022 • 2 minutes to read • Edit Online
The topics in this section describe how to use Windows Presentation Foundation (WPF) support for rich
presentation of text in your applications.
In This Section
Create a Text Decoration
Specify Whether a Hyperlink is Underlined
Apply Transforms to Text
Apply Animations to Text
Create Text with a Shadow
Create Outlined Text
Draw Text to a Control's Background
Draw Text to a Visual
Use Special Characters in XAML
See also
   Typography
   Documents in WPF
   OpenType Font Features
       How to: Create a Text Decoration
       11/21/2022 • 4 minutes to read • Edit Online
A TextDecoration object is a visual ornamentation you can add to text. There are four types of text decorations:
underline, baseline, strikethrough, and overline. The following example shows the locations of the text
decorations relative to the text.
To add a text decoration to text, create a TextDecoration object and modify its properties. Use the Location
property to specify where the text decoration appears, such as underline. Use the Pen property to specify the
appearance of the text decoration, such as a solid fill or gradient color. If you do not specify a value for the Pen
property, the decorations defaults to the same color as the text. Once you have defined a TextDecoration object,
add it to the TextDecorations collection of the desired text object.
The following example shows a text decoration that has been styled with a linear gradient brush and a dashed
pen.
The Hyperlink object is an inline-level flow content element that allows you to host hyperlinks within the flow
content. By default, Hyperlink uses a TextDecoration object to display an underline. TextDecoration objects can be
performance intensive to instantiate, particularly if you have many Hyperlink objects. If you make extensive use
of Hyperlink elements, you may want to consider showing an underline only when triggering an event, such as
the MouseEnter event.
In the following example, the underline for the "My MSN" link is dynamic—it only appears when the
MouseEnter event is triggered.
Example
In the following code example, an underline text decoration uses the default font value.
   // Use the default font values for the strikethrough text decoration.
   private void SetDefaultStrikethrough()
   {
       // Set the underline decoration directly to the text block.
       TextBlock1.TextDecorations = TextDecorations.Strikethrough;
   }
   ' Use the default font values for the strikethrough text decoration.
   Private Sub SetDefaultStrikethrough()
       ' Set the underline decoration directly to the text block.
       TextBlock1.TextDecorations = TextDecorations.Strikethrough
   End Sub
   <!-- Use the default font values for the strikethrough text decoration. -->
   <TextBlock
     TextDecorations="Strikethrough"
     FontSize="36" >
     The quick red fox
   </TextBlock>
In the following code example, an underline text decoration is created with a solid color brush for the pen.
       // Set the underline decoration to a TextDecorationCollection and add it to the text block.
       TextDecorationCollection myCollection = new TextDecorationCollection();
       myCollection.Add(myUnderline);
       TextBlock2.TextDecorations = myCollection;
   }
       ' Create a solid color brush pen for the text decoration.
       myUnderline.Pen = New Pen(Brushes.Red, 1)
       myUnderline.PenThicknessUnit = TextDecorationUnit.FontRecommended
       ' Set the underline decoration to a TextDecorationCollection and add it to the text block.
       Dim myCollection As New TextDecorationCollection()
       myCollection.Add(myUnderline)
       TextBlock2.TextDecorations = myCollection
   End Sub
   <!-- Use a Red pen for the underline text decoration -->
   <TextBlock
     FontSize="36" >
     jumps over
     <TextBlock.TextDecorations>
       <TextDecorationCollection>
         <TextDecoration
           PenThicknessUnit="FontRecommended">
           <TextDecoration.Pen>
              <Pen Brush="Red" Thickness="1" />
           </TextDecoration.Pen>
         </TextDecoration>
       </TextDecorationCollection>
     </TextBlock.TextDecorations>
   </TextBlock>
In the following code example, an underline text decoration is created with a linear gradient brush for the
dashed pen.
       // Set the underline decoration to a TextDecorationCollection and add it to the text block.
       TextDecorationCollection myCollection = new TextDecorationCollection();
       myCollection.Add(myUnderline);
       TextBlock3.TextDecorations = myCollection;
   }
   ' Use a linear gradient pen for the underline text decoration.
   Private Sub SetLinearGradientUnderline()
       ' Create an underline text decoration. Default is underline.
       Dim myUnderline As New TextDecoration()
       ' Set the underline decoration to a TextDecorationCollection and add it to the text block.
       Dim myCollection As New TextDecorationCollection()
       myCollection.Add(myUnderline)
       TextBlock3.TextDecorations = myCollection
   End Sub
 <!-- Use a linear gradient pen for the underline text decoration. -->
 <TextBlock FontSize="36">the lazy brown dog.
   <TextBlock.TextDecorations>
     <TextDecorationCollection>
       <TextDecoration
         PenThicknessUnit="FontRecommended">
         <TextDecoration.Pen>
           <Pen Thickness="1.5">
              <Pen.Brush>
                <LinearGradientBrush Opacity="0.5"
                  StartPoint="0,0.5" EndPoint="1,0.5">
                  <LinearGradientBrush.GradientStops>
                    <GradientStop Color="Yellow" Offset="0" />
                    <GradientStop Color="Red" Offset="1" />
                  </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
              </Pen.Brush>
              <Pen.DashStyle>
                <DashStyle Dashes="2"/>
              </Pen.DashStyle>
           </Pen>
         </TextDecoration.Pen>
       </TextDecoration>
     </TextDecorationCollection>
   </TextBlock.TextDecorations>
 </TextBlock>
See also
 TextDecoration
 Hyperlink
 Specify Whether a Hyperlink is Underlined
       How to: Specify Whether a Hyperlink is Underlined
       11/21/2022 • 2 minutes to read • Edit Online
The Hyperlink object is an inline-level flow content element that allows you to host hyperlinks within the flow
content. By default, Hyperlink uses a TextDecoration object to display an underline. TextDecoration objects can be
performance intensive to instantiate, particularly if you have many Hyperlink objects. If you make extensive use
of Hyperlink elements, you may want to consider showing an underline only when triggering an event, such as
the MouseEnter event.
In the following example, the underline for the "My MSN" link is dynamic, that is, it only appears when the
MouseEnter event is triggered.
Example
The following markup sample shows a Hyperlink defined with and without an underline:
The following code sample shows how to create an underline for the Hyperlink on the MouseEnter event, and
remove it on the MouseLeave event.
See also
 TextDecoration
 Hyperlink
 Optimizing WPF Application Performance
 Create a Text Decoration
       How to: Apply Transforms to Text
       11/21/2022 • 2 minutes to read • Edit Online
Transforms can alter the display of text in your application. The following examples use different types of
rendering transforms to affect the display of text in a TextBlock control.
Example
The following example shows text rotated about a specified point in the two-dimensional x-y plane.
The following code example uses a RotateTransform to rotate text. An Angle value of 90 rotates the element 90
degrees clockwise.
The following example shows the second line of text scaled by 150% along the x-axis, and the third line of text
scaled by 150% along the y-axis.
The following code example uses a ScaleTransform to scale text from its original size.
   <!-- Scale the text using a ScaleTransform. -->
   <TextBlock
     Name="textblockScaleMaster"
     FontSize="32"
     Foreground="SteelBlue"
     Text="Scaled Text"
     Margin="100, 0, 0, 0"
     Grid.Column="0" Grid.Row="0">
   </TextBlock>
   <TextBlock
     FontSize="32"
     FontWeight="Bold"
     Foreground="SteelBlue"
     Text="{Binding Path=Text, ElementName=textblockScaleMaster}"
     Margin="100, 0, 0, 0"
     Grid.Column="0" Grid.Row="1">
     <TextBlock.RenderTransform>
       <ScaleTransform ScaleX="1.5" ScaleY="1.0" />
     </TextBlock.RenderTransform>
   </TextBlock>
   <TextBlock
     FontSize="32"
     FontWeight="Bold"
     Foreground="SteelBlue"
     Text="{Binding Path=Text, ElementName=textblockScaleMaster}"
     Margin="100, 0, 0, 0"
     Grid.Column="0" Grid.Row="2">
     <TextBlock.RenderTransform>
       <ScaleTransform ScaleX="1.0" ScaleY="1.5" />
     </TextBlock.RenderTransform>
   </TextBlock>
  NOTE
  Scaling text is not the same as increasing the font size of text. Font sizes are calculated independently of each other in
  order to provide the best resolution at different sizes. Scaled text, on the other hand, preserves the proportions of the
  original-sized text.
The following code example uses a SkewTransform to skew text. A skew, also known as a shear, is a
transformation that stretches the coordinate space in a non-uniform manner. In this example, the two text
strings are skewed -30° and 30° along the x-coordinate.
   <!-- Skew the text using a SkewTransform. -->
   <TextBlock
     Name="textblockSkewMaster"
     FontSize="32"
     FontWeight="Bold"
     Foreground="Maroon"
     Text="Skewed Text"
     Margin="125, 0, 0, 0"
     Grid.Column="0" Grid.Row="0">
     <TextBlock.RenderTransform>
       <SkewTransform AngleX="-30" AngleY="0" />
     </TextBlock.RenderTransform>
   </TextBlock>
   <TextBlock
     FontSize="32"
     FontWeight="Bold"
     Foreground="Maroon"
     Text="{Binding Path=Text, ElementName=textblockSkewMaster}"
     Margin="100, 0, 0, 0"
     Grid.Column="0" Grid.Row="1">
     <TextBlock.RenderTransform>
       <SkewTransform AngleX="30" AngleY="0" />
     </TextBlock.RenderTransform>
   </TextBlock>
The following example shows text translated, or moved, along the x- and y-axis.
The following code example uses a TranslateTransform to offset text. In this example, a slightly offset copy of text
below the primary text creates a shadow effect.
  NOTE
  The DropShadowBitmapEffect provides a rich set of features for providing shadow effects. For more information, see
  Create Text with a Shadow.
See also
Apply Animations to Text
       How to: Apply Animations to Text
      11/21/2022 • 2 minutes to read • Edit Online
Animations can alter the display and appearance of text in your application. The following examples use
different types of animations to affect the display of text in a TextBlock control.
Example
The following example uses a DoubleAnimation to animate the width of the text block. The width value changes
from the width of the text block to 0 over a duration of 10 seconds, and then reverses the width values and
continues. This type of animation creates a wipe effect.
   <TextBlock
     Name="MyWipedText"
     Margin="20"
     Width="480" Height="100" FontSize="48" FontWeight="Bold" Foreground="Maroon">
     This is wiped text
The following example uses a DoubleAnimation to animate the opacity of the text block. The opacity value
changes from 1.0 to 0 over a duration of 5 seconds, and then reverses the opacity values and continues.
   <TextBlock
     Name="MyFadingText"
     Margin="20"
     Width="640" Height="100" FontSize="48" FontWeight="Bold" Foreground="Maroon">
     This is fading text
The following diagram shows the effect of the TextBlock control changing its opacity from   1.00   to   0.00   during
the 5-second interval defined by the Duration.
The following example uses a ColorAnimation to animate the foreground color of the text block. The foreground
color value changes from one color to a second color over a duration of 5 seconds, and then reverses the color
values and continues.
   <TextBlock
     Name="MyChangingColorText"
     Margin="20"
     Width="640" Height="100" FontSize="48" FontWeight="Bold">
     This is changing color text
     <TextBlock.Foreground>
       <SolidColorBrush x:Name="MySolidColorBrush" Color="Maroon" />
     </TextBlock.Foreground>
The following example uses a DoubleAnimation to rotate the text block. The text block performs a full rotation
over a duration of 20 seconds, and then continues to repeat the rotation.
   <TextBlock
     Name="MyRotatingText"
     Margin="20"
     Width="640" Height="100" FontSize="48" FontWeight="Bold" Foreground="Teal"
     >
     This is rotating text
     <TextBlock.RenderTransform>
       <RotateTransform x:Name="MyRotateTransform" Angle="0" CenterX="230" CenterY="25"/>
     </TextBlock.RenderTransform>
See also
   Animation Overview
       How to: Create Text with a Shadow
       11/21/2022 • 2 minutes to read • Edit Online
The examples in this section show how to create a shadow effect for displayed text.
Example
The DropShadowEffect object allows you to create a variety of drop shadow effects for Windows Presentation
Foundation (WPF) objects. The following example shows a drop shadow effect applied to text. In this case, the
shadow is a soft shadow, which means the shadow color blurs.
You can control the width of a shadow by setting the ShadowDepth property. A value of 4.0 indicates a shadow
width of 4 pixels. You can control the softness, or blur, of a shadow by modifying the BlurRadius property. A
value of 0.0 indicates no blurring. The following code example shows how to create a soft shadow.
  NOTE
  These shadow effects do not go through the Windows Presentation Foundation (WPF) text rendering pipeline. As a result,
  ClearType is disabled when using these effects.
The following example shows a hard drop shadow effect applied to text. In this case, the shadow is not blurred.
You can create a hard shadow by setting the BlurRadius property to 0.0 , which indicates that no blurring is
used. You can control the direction of the shadow by modifying the Direction property. Set the directional value
of this property to a degree between 0 and 360 . The following illustration shows the directional values of the
Direction property setting.
The following code example shows how to create a hard shadow.
The following code example shows how to create a transform for a shadow effect.
In most cases, when you're adding ornamentation to text strings in your Windows Presentation Foundation
(WPF) application, you are using text in terms of a collection of discrete characters, or glyphs. For example, you
could create a linear gradient brush and apply it to the Foreground property of a TextBox object. When you
display or edit the text box, the linear gradient brush is automatically applied to the current set of characters in
the text string.
However, you can also convert text into Geometry objects, allowing you to create other types of visually rich text.
For example, you could create a Geometry object based on the outline of a text string.
When text is converted to a Geometry object, it is no longer a collection of characters—you cannot modify the
characters in the text string. However, you can affect the appearance of the converted text by modifying its
stroke and fill properties. The stroke refers to the outline of the converted text; the fill refers to the area inside
the outline of the converted text.
The following examples illustrate several ways of creating visual effects by modifying the stroke and fill of
converted text.
It is also possible to modify the bounding box rectangle, or highlight, of the converted text. The following
example illustrates a way to create visual effects by modifying the stroke and highlight of converted text.
Example
The key to converting text to a Geometry object is to use the FormattedText object. Once you have created this
object, you can use the BuildGeometry and BuildHighlightGeometry methods to convert the text to Geometry
objects. The first method returns the geometry of the formatted text; the second method returns the geometry
of the formatted text's bounding box. The following code example shows how to create a FormattedText object
and to retrieve the geometries of the formatted text and its bounding box.
   /// <summary>
   /// Create the outline geometry based on the formatted text.
   /// </summary>
   public void CreateText()
   {
       System.Windows.FontStyle fontStyle = FontStyles.Normal;
       FontWeight fontWeight = FontWeights.Medium;
   ''' <summary>
   ''' Create the outline geometry based on the formatted text.
   ''' </summary>
   Public Sub CreateText()
       Dim fontStyle As FontStyle = FontStyles.Normal
       Dim fontWeight As FontWeight = FontWeights.Medium
       ' Build the geometry object that represents the text highlight.
       If Highlight = True Then
           _textHighLightGeometry = formattedText.BuildHighlightGeometry(New Point(0, 0))
       End If
   End Sub
In order to display the retrieved the Geometry objects, you need to access the DrawingContext of the object
that's displaying the converted text. In these code examples, this access is achieved by creating a custom control
object that's derived from a class that supports user-defined rendering.
To display Geometry objects in the custom control, provide an override for the OnRender method. Your
overridden method should use the DrawGeometry method to draw the Geometry objects.
   /// <summary>
   /// OnRender override draws the geometry of the text and optional highlight.
   /// </summary>
   /// <param name="drawingContext">Drawing context of the OutlineText control.</param>
   protected override void OnRender(DrawingContext drawingContext)
   {
       // Draw the outline based on the properties that are set.
       drawingContext.DrawGeometry(Fill, new System.Windows.Media.Pen(Stroke, StrokeThickness), _textGeometry);
       // Draw the text highlight based on the properties that are set.
       if (Highlight == true)
       {
           drawingContext.DrawGeometry(null, new System.Windows.Media.Pen(Stroke, StrokeThickness),
   _textHighLightGeometry);
       }
   }
   ''' <summary>
   ''' OnRender override draws the geometry of the text and optional highlight.
   ''' </summary>
   ''' <param name="drawingContext">Drawing context of the OutlineText control.</param>
   Protected Overrides Sub OnRender(ByVal drawingContext As DrawingContext)
       ' Draw the outline based on the properties that are set.
       drawingContext.DrawGeometry(Fill, New Pen(Stroke, StrokeThickness), _textGeometry)
       ' Draw the text highlight based on the properties that are set.
       If Highlight = True Then
           drawingContext.DrawGeometry(Nothing, New Pen(Stroke, StrokeThickness), _textHighLightGeometry)
       End If
   End Sub
For the source of the example custom user control object, see OutlineTextControl.cs for C# and
OutlineTextControl.vb for Visual Basic.
See also
   Drawing Formatted Text
       How to: Draw Text to a Control's Background
       11/21/2022 • 2 minutes to read • Edit Online
You can draw text directly to the background of a control by converting a text string to a FormattedText object,
and then drawing the object to the control's DrawingContext. You can also use this technique for drawing to the
background of objects derived from Panel, such as Canvas and StackPanel.
Example
To draw to the background of a control, create a new DrawingBrush object and draw the converted text to the
object's DrawingContext. Then, assign the new DrawingBrush to the control's background property.
The following code example shows how to create a FormattedText object and draw to the background of a Label
and Button object.
 // Handle the WindowLoaded event for the window.
 private void WindowLoaded(object sender, EventArgs e)
 {
     // Update the background property of the label and button.
     myLabel.Background = new DrawingBrush(DrawMyText("My Custom Label"));
     myButton.Background = new DrawingBrush(DrawMyText("Display Text"));
 }
 // Convert the text string to a geometry and draw it to the control's DrawingContext.
 private Drawing DrawMyText(string textString)
 {
     // Create a new DrawingGroup of the control.
     DrawingGroup drawingGroup = new DrawingGroup();
         // Draw a rounded rectangle under the text that is slightly larger than the text.
         drawingContext.DrawRoundedRectangle(System.Windows.Media.Brushes.PapayaWhip, null, new Rect(new
 System.Windows.Size(formattedText.Width + 50, formattedText.Height + 5)), 5.0, 5.0);
See also
 FormattedText
 Drawing Formatted Text
       How to: Draw Text to a Visual
       11/21/2022 • 2 minutes to read • Edit Online
The following example shows how to draw text to a DrawingVisual using a DrawingContext object. A drawing
context is returned by calling the RenderOpen method of a DrawingVisual object. You can draw graphics and
text into a drawing context.
To draw text into the drawing context, use the DrawText method of a DrawingContext object. When you are
finished drawing content into the drawing context, call the Close method to close the drawing context and
persist the content.
Example
   // Create a DrawingVisual that contains text.
   private DrawingVisual CreateDrawingVisualText()
   {
       // Create an instance of a DrawingVisual.
       DrawingVisual drawingVisual = new DrawingVisual();
       return drawingVisual;
   }
       Return drawingVisual
   End Function
NOTE
For the complete code sample from which the preceding code example was extracted, see Hit Test Using DrawingVisuals
Sample.
        How to: Use Special Characters in XAML
        11/21/2022 • 2 minutes to read • Edit Online
Markup files that are created in Visual Studio are automatically saved in the Unicode UTF-8 file format, which
means that most special characters, such as accent marks, are encoded correctly. However, there is a set of
commonly-used special characters that are handled differently. These special characters follow the World Wide
Web Consortium (W3C) XML standard for encoding.
The following table shows the syntax for encoding this set of special characters:
C H A RA C T ER SY N TA X DESC RIP T IO N
  NOTE
  If you create a markup file using a text editor, such as Windows Notepad, you must save the file in the Unicode UTF-8 file
  format in order to preserve any encoded special characters.
The following example shows how you can use special characters in text when creating markup.
Example
   <!-- Display special characters that require special encoding: < > & " -->
   <TextBlock>
     <    <!-- Less than symbol -->
     >    <!-- Greater than symbol -->
     & <!-- Ampersand symbol -->
     " <!-- Double quote symbol -->
   </TextBlock>
Windows Vista and Microsoft .NET Framework introduce a new print path — an alternative to Microsoft
Windows Graphics Device Interface (GDI) printing — and a vastly expanded set of print system management
APIs.
In This Section
Printing Overview
A discussion of the new print path and APIs.
How-to Topics
A set of articles showing how to use the new print path and APIs.
See also
   System.Printing
   System.Printing.IndexedProperties
   System.Printing.Interop
   Documents in WPF
   XPS Documents
       Printing Overview
       11/21/2022 • 11 minutes to read • Edit Online
With Microsoft .NET Framework, application developers using Windows Presentation Foundation (WPF) have a
rich new set of printing and print system management APIs. With Windows Vista, some of these print system
enhancements are also available to developers creating Windows Forms applications and developers using
unmanaged code. At the core of this new functionality is the new XML Paper Specification (XPS) file format and
the XPS print path.
This topic contains the following sections.
About XPS
XPS is an electronic document format, a spool file format and a page description language. It is an open
document format that uses XML, Open Packaging Conventions (OPC), and other industry standards to create
cross-platform documents. XPS simplifies the process by which digital documents are created, shared, printed,
viewed, and archived. For additional information on XPS, see XPS Documents.
Several techniques for printing XPS-based content using WPF are demonstrated in Programmatically Print XPS
Files. You may find it useful to reference these samples during review of content contained in this topic.
(Unmanaged code developers should see documentation for the MXDC_ESCAPE function. Windows Forms
developers must use the API in the System.Drawing.Printing namespace which does not support the full XPS
print path, but does support a hybrid GDI-to-XPS print path. See Print Path Architecture below.)
   if (localPrinterEnumerator->MoveNext())
   {
      // Get PrintQueue from first available printer
      printQueue = ((PrintQueue^)localPrinterEnumerator->Current);
   } else
   {
      return nullptr;
   }
   // Get default PrintTicket from printer
   PrintTicket^ printTicket = printQueue->DefaultPrintTicket;
   // Modify PrintTicket
   if (printCapabilites->CollationCapability->Contains(Collation::Collated))
   {
      printTicket->Collation = Collation::Collated;
   }
   if (printCapabilites->DuplexingCapability->Contains(Duplexing::TwoSidedLongEdge))
   {
      printTicket->Duplexing = Duplexing::TwoSidedLongEdge;
   }
   if (printCapabilites->StaplingCapability->Contains(Stapling::StapleDualLeft))
   {
      printTicket->Stapling = Stapling::StapleDualLeft;
   }
   return printTicket;
};// end:GetPrintTicketFromPrinter()
// ---------------------- GetPrintTicketFromPrinter -----------------------
/// <summary>
/// Returns a PrintTicket based on the current default printer.</summary>
/// <returns>
/// A PrintTicket for the current local default printer.</returns>
private PrintTicket GetPrintTicketFromPrinter()
{
    PrintQueue printQueue = null;
    System.Collections.IEnumerator localPrinterEnumerator =
        localPrinterCollection.GetEnumerator();
    if (localPrinterEnumerator.MoveNext())
    {
         // Get PrintQueue from first available printer
         printQueue = (PrintQueue)localPrinterEnumerator.Current;
    }
    else
    {
         // No printer exist, return null PrintTicket
         return null;
    }
    // Modify PrintTicket
    if (printCapabilites.CollationCapability.Contains(Collation.Collated))
    {
        printTicket.Collation = Collation.Collated;
    }
    if ( printCapabilites.DuplexingCapability.Contains(
            Duplexing.TwoSidedLongEdge) )
    {
        printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
    }
    if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
    {
        printTicket.Stapling = Stapling.StapleDualLeft;
    }
    return printTicket;
}// end:GetPrintTicketFromPrinter()
   ' ---------------------- GetPrintTicketFromPrinter -----------------------
   ''' <summary>
   ''' Returns a PrintTicket based on the current default printer.</summary>
   ''' <returns>
   ''' A PrintTicket for the current local default printer.</returns>
   Private Function GetPrintTicketFromPrinter() As PrintTicket
       Dim printQueue As PrintQueue = Nothing
       If localPrinterEnumerator.MoveNext() Then
            ' Get PrintQueue from first available printer
            printQueue = CType(localPrinterEnumerator.Current, PrintQueue)
       Else
            ' No printer exist, return null PrintTicket
            Return Nothing
       End If
       If printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) Then
           printTicket.Duplexing = Duplexing.TwoSidedLongEdge
       End If
       If printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft) Then
           printTicket.Stapling = Stapling.StapleDualLeft
       End If
       Return printTicket
   End Function ' end:GetPrintTicketFromPrinter()
XpsDocumentWriter
An XpsDocumentWriter, with its many the Write and WriteAsync methods, is used to write XPS documents to a
PrintQueue. For example, the Write(FixedPage, PrintTicket) method is used to output an XPS document and
PrintTicket synchronously. The WriteAsync(FixedDocument, PrintTicket) method is used to output an XPS
document and PrintTicket asynchronously.
The following example demonstrates how to create an XpsDocumentWriter using code.
The AddJob methods also provide ways to print. See Programmatically Print XPS Files. for details.
See also
 PrintDialog
 XpsDocumentWriter
 XpsDocument
 PrintTicket
 PrintCapabilities
 PrintServer
 PrintQueue
 How-to Topics
 Documents in WPF
 XPS Documents
 Document Serialization and Storage
 Microsoft XPS Document Converter (MXDC)
       Printing How-to Topics
       11/21/2022 • 2 minutes to read • Edit Online
The topics in this section demonstrate how to use the printing and print system management features included
with Windows Presentation Foundation (WPF) as well as the new XML Paper Specification (XPS) print path.
In This Section
Invoke a Print Dialog
Instructions for XAML markup to declare a Microsoft Windows print dialog object and using code to invoke the
dialog from within a Windows Presentation Foundation (WPF) application.
Clone a Printer
Instructions for how to install a second print queue with exactly the same properties as an existing print queue.
Diagnose Problematic Print Job
Instructions for using the properties of print queues and print jobs to diagnose a print job that is not printing.
Discover Whether a Print Job Can Be Printed At This Time of Day
Instructions for using the properties of print queues and print jobs to programmatically decide what times of
day the job can be printed.
Enumerate a Subset of Print Queues
Instructions for generating a list of printers having certain characteristics.
Get Print System Object Properties Without Reflection
Instructions for how to discover at runtime print system object's properties and their types.
Programmatically Print XPS Files
Instructions for rapid printing of XML Paper Specification (XPS) files without the need for a user interface (UI).
Remotely Survey the Status of Printers
Instructions for creating a utility that will survey printers to discover those experiencing a paper jam or other
problem.
Validate and Merge PrintTickets
Instructions for checking that a print ticket is valid and that it does not request anything that is not supported by
the printer.
See also
   System.Printing
   System.Printing.IndexedProperties
   System.Printing.Interop
   Printing Overview
   Documents in WPF
   XPS Documents
       How to: Invoke a Print Dialog
       11/21/2022 • 2 minutes to read • Edit Online
To provide the ability to print from you application, you can simply create and open a PrintDialog object.
Example
The PrintDialog control provides a single entry point for UI, configuration, and XPS job submission. The control
is easy to use and can be instantiated by using Extensible Application Markup Language (XAML) markup or
code. The following example demonstrates how to instantiate and open the control in code and how to print
from it. It also shows how to ensure that the dialog will give the user the option of setting a specific range of
pages. The example code assumes that there is a file FixedDocumentSequence.xps in the root of the C: drive.
           // Display the dialog. This returns true if the user presses the Print button.
           Nullable<Boolean> print = pDialog.ShowDialog();
           if (print == true)
           {
               XpsDocument xpsDocument = new XpsDocument("C:\\FixedDocumentSequence.xps",
   FileAccess.ReadWrite);
               FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
               pDialog.PrintDocument(fixedDocSeq.DocumentPaginator, "Test print job");
           }
       }
             ' Display the dialog. This returns true if the user presses the Print button.
             Dim print? As Boolean = pDialog.ShowDialog()
             If print = True Then
                 Dim xpsDocument As New XpsDocument("C:\FixedDocumentSequence.xps", FileAccess.ReadWrite)
                 Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
                 pDialog.PrintDocument(fixedDocSeq.DocumentPaginator, "Test print job")
             End If
   End Sub
Once the dialog is open, users will be able to select from the printers installed on their computer. They will also
have the option of selecting the Microsoft XPS Document Writer to create an XML Paper Specification (XPS) file
instead of printing.
  NOTE
  The System.Windows.Controls.PrintDialog control of WPF, which is discussed in this topic, should not be confused with
  the System.Windows.Forms.PrintDialog component of Windows Forms.
Strictly speaking, you can use the PrintDocument method without ever opening the dialog. In that sense, the
control can be used as an unseen printing component. But for performance reasons, it would be better to use
either the AddJob method or one of the many Write and WriteAsync methods of the XpsDocumentWriter. For
more about this, see Programmatically Print XPS Files.
See also
   PrintDialog
   Documents in WPF
   Printing Overview
   Microsoft XPS Document Writer
        How to: Clone a Printer
        11/21/2022 • 3 minutes to read • Edit Online
 Most businesses will, at some point, buy multiple printers of the same model. Typically, these are all installed
 with virtually identical configuration settings. Installing each printer can be time-consuming and error prone.
 The System.Printing.IndexedProperties namespace and the InstallPrintQueue class that are exposed with
 Microsoft .NET Framework makes it possible to instantly install any number of additional print queues that are
 cloned from an existing print queue.
 Example
 In the example below, a second print queue is cloned from an existing print queue. The second differs from the
 first only in its name, location, port, and shared status. The major steps for doing this are as follows.
 1. Create a PrintQueue object for the existing printer that is going to be cloned.
 2. Create a PrintPropertyDictionary from the PropertiesCollection of the PrintQueue. The Value property of
    each entry in this dictionary is an object of one of the types derived from PrintProperty. There are two
    ways to set the value of an entry in this dictionary.
       Use the dictionary's Remove and Add methods to remove the entry and then re-add it with the
       desired value.
       Use the dictionary's SetProperty method.
    The example below illustrates both ways.
 3. Create a PrintBooleanProperty object and set its Name to "IsShared" and its Value to   true   .
 4. Use the PrintBooleanProperty object to be the value of the PrintPropertyDictionary's "IsShared" entry.
 5. Create a PrintStringProperty object and set its Name to "ShareName" and its Value to an appropriate
    String.
 6. Use the PrintStringProperty object to be the value of the PrintPropertyDictionary's "ShareName" entry.
 7. Create another PrintStringProperty object and set its Name to "Location" and its Value to an appropriate
    String.
 8. Use the second PrintStringProperty object to be the value of the PrintPropertyDictionary's "Location"
    entry.
 9. Create an array of Strings. Each item is the name of a port on the server.
10. Use InstallPrintQueue to install the new printer with the new values.
 An example is below.
LocalPrintServer myLocalPrintServer = new LocalPrintServer(PrintSystemDesiredAccess.AdministrateServer);
PrintQueue sourcePrintQueue = myLocalPrintServer.DefaultPrintQueue;
PrintPropertyDictionary myPrintProperties = sourcePrintQueue.PropertiesCollection;
// Give the new printer its share name using SetProperty method
PrintStringProperty theShareName = new PrintStringProperty("ShareName", "\"Son of " + sourcePrintQueue.Name
+"\"");
myPrintProperties.SetProperty("ShareName", theShareName);
// Specify the physical location of the new printer using Remove/Add methods
PrintStringProperty theLocation = new PrintStringProperty("Location", "the supply room");
myPrintProperties.Remove("Location");
myPrintProperties.Add("Location", theLocation);
// Report outcome
Console.WriteLine("{0} in {1} has been installed and shared as {2}", clonedPrinter.Name,
clonedPrinter.Location, clonedPrinter.ShareName);
Console.WriteLine("Press Return to continue ...");
Console.ReadLine();
' Give the new printer its share name using SetProperty method
Dim theShareName As New PrintStringProperty("ShareName", """Son of " & sourcePrintQueue.Name & """")
myPrintProperties.SetProperty("ShareName", theShareName)
' Specify the physical location of the new printer using Remove/Add methods
Dim theLocation As New PrintStringProperty("Location", "the supply room")
myPrintProperties.Remove("Location")
myPrintProperties.Add("Location", theLocation)
Network administrators often field complaints from users about print jobs that do not print or print slowly. The
rich set of print job properties exposed in the APIs of Microsoft .NET Framework provide a means for
performing a rapid remote diagnosis of print jobs.
Example
The major steps for creating this kind of utility are as follows.
1. Identify the print job that the user is complaining about. Users often cannot do this precisely. They may
   not know the names of the print servers or printers. They may describe the location of the printer in
   different terminology than was used in setting its Location property. Accordingly, it is a good idea to
   generate a list of the user's currently submitted jobs. If there is more than one, then communication
   between the user and the print system administrator can be used to pinpoint the job that is having
   problems. The substeps are as follows.
   a. Obtain a list of all print servers.
   b. Loop through the servers to query their print queues.
   c. Within each pass of the server loop, loop through all the server's queues to query their jobs
   d. Within each pass of the queue loop, loop through its jobs and gather identifying information about
      those that were submitted by the complaining user.
2. When the problematic print job has been identified, examine relevant properties to see what might be the
   problem. For example, is job in an error state or did the printer servicing the queue go offline before the
   job could print?
The code below is series of code examples. The first code example contains the loop through the print queues.
(Step 1c above.) The variable myPrintQueues is the PrintQueueCollection object for the current print server.
The code example begins by refreshing the current print queue object with PrintQueue.Refresh. This ensures
that the object's properties accurately represent the state of the physical printer that it represents. Then the
application gets the collection of print jobs currently in the print queue by using GetPrintJobInfoCollection.
Next the application loops through the PrintSystemJobInfo collection and compares each Submitter property
with the alias of the complaining user. If they match, the application adds identifying information about the job
to the string that will be presented. (The userName and jobList variables are initialized earlier in the
application.)
   for each (PrintQueue^ pq in myPrintQueues)
   {
      pq->Refresh();
      PrintJobInfoCollection^ jobs = pq->GetPrintJobInfoCollection();
      for each (PrintSystemJobInfo^ job in jobs)
      {
         // Since the user may not be able to articulate which job is problematic,
         // present information about each job the user has submitted.
         if (job->Submitter == userName)
         {
            atLeastOne = true;
            jobList = jobList + "\nServer:" + line;
            jobList = jobList + "\n\tQueue:" + pq->Name;
            jobList = jobList + "\n\tLocation:" + pq->Location;
            jobList = jobList + "\n\t\tJob: " + job->JobName + " ID: " + job->JobIdentifier;
         }
      }
   }
The next code example picks up the application at Step 2. (See above.) The problematic job has been identified
and the application prompts for the information that will identify it. From this information it creates PrintServer,
PrintQueue, and PrintSystemJobInfo objects.
At this point the application contains a branching structure corresponding to the two ways of checking a print
job's status:
   You can read the flags of the JobStatus property which is of type PrintJobStatus.
   You can read each relevant property such as IsBlocked and IsInError.
This example demonstrates both methods, so the user was previously prompted as to which method to use and
responded with "Y" if they wanted to use the flags of the JobStatus property. See below for the details of the two
methods. Finally, the application uses a method called Repor tQueueAndJobAvailability to report on whether
the job can be printed at this time of day. This method is discussed in Discover Whether a Print Job Can Be
Printed At This Time of Day.
   // When the problematic print job has been identified, enter information about it.
   Console::Write("\nEnter the print server hosting the job (including leading slashes \\\\): " + "\n(press
   Return for the current computer \\\\{0}): ", Environment::MachineName);
   String^ pServer = Console::ReadLine();
   if (pServer == "")
   {
      pServer = "\\\\" + Environment::MachineName;
   }
   Console::Write("\nEnter the print queue hosting the job: ");
   String^ pQueue = Console::ReadLine();
   Console::Write("\nEnter the job ID: ");
   Int16 jobID = Convert::ToInt16(Console::ReadLine());
   if (useAttributesResponse == "Y")
   {
      TroubleSpotter::SpotTroubleUsingJobAttributes(theJob);
      // TroubleSpotter class is defined in the complete example.
   } else
   {
      TroubleSpotter::SpotTroubleUsingProperties(theJob);
   }
   TroubleSpotter::ReportQueueAndJobAvailability(theJob);
   // When the problematic print job has been identified, enter information about it.
   Console.Write("\nEnter the print server hosting the job (including leading slashes \\\\): " +
   "\n(press Return for the current computer \\\\{0}): ", Environment.MachineName);
   String pServer = Console.ReadLine();
   if (pServer == "")
   {
       pServer = "\\\\" +Environment.MachineName;
   }
   Console.Write("\nEnter the print queue hosting the job: ");
   String pQueue = Console.ReadLine();
   Console.Write("\nEnter the job ID: ");
   Int16 jobID = Convert.ToInt16(Console.ReadLine());
   if (useAttributesResponse == "Y")
   {
        TroubleSpotter.SpotTroubleUsingJobAttributes(theJob);
        // TroubleSpotter class is defined in the complete example.
   }
   else
   {
        TroubleSpotter.SpotTroubleUsingProperties(theJob);
   }
TroubleSpotter.ReportQueueAndJobAvailability(theJob);
   ' When the problematic print job has been identified, enter information about it.
   Console.Write(vbLf & "Enter the print server hosting the job (including leading slashes \\): " & vbLf & "
   (press Return for the current computer \\{0}): ", Environment.MachineName)
   Dim pServer As String = Console.ReadLine()
   If pServer = "" Then
       pServer = "\\" & Environment.MachineName
   End If
   Console.Write(vbLf & "Enter the print queue hosting the job: ")
   Dim pQueue As String = Console.ReadLine()
   Console.Write(vbLf & "Enter the job ID: ")
   Dim jobID As Int16 = Convert.ToInt16(Console.ReadLine())
   ' Create objects to represent the server, queue, and print job.
   Dim hostingServer As New PrintServer(pServer, PrintSystemDesiredAccess.AdministrateServer)
   Dim hostingQueue As New PrintQueue(hostingServer, pQueue, PrintSystemDesiredAccess.AdministratePrinter)
   Dim theJob As PrintSystemJobInfo = hostingQueue.GetJob(jobID)
TroubleSpotter.ReportQueueAndJobAvailability(theJob)
To check print job status using the flags of the JobStatus property, you check each relevant flag to see if it is set.
The standard way to see if one bit is set in a set of bit flags is to perform a logical AND operation with the set of
flags as one operand and the flag itself as the other. Since the flag itself has only one bit set, the result of the
logical AND is that, at most, that same bit is set. To find out whether it is or not, just compare the result of the
logical AND with the flag itself. For more information, see PrintJobStatus, the & Operator (C# Reference), and
FlagsAttribute.
For each attribute whose bit is set, the code reports this to the console screen and sometimes suggests a way to
respond. (The HandlePausedJob method that is called if the job or queue is paused is discussed below.)
   // Check for possible trouble states of a print job using the flags of the JobStatus property
   static void SpotTroubleUsingJobAttributes (PrintSystemJobInfo^ theJob)
   {
      if ((theJob->JobStatus & PrintJobStatus::Blocked) == PrintJobStatus::Blocked)
      {
         Console::WriteLine("The job is blocked.");
      }
      if (((theJob->JobStatus & PrintJobStatus::Completed) == PrintJobStatus::Completed)
         ||
         ((theJob->JobStatus & PrintJobStatus::Printed) == PrintJobStatus::Printed))
      {
         Console::WriteLine("The job has finished. Have user recheck all output bins and be sure the correct
   printer is being checked.");
      }
      if (((theJob->JobStatus & PrintJobStatus::Deleted) == PrintJobStatus::Deleted)
         ||
         ((theJob->JobStatus & PrintJobStatus::Deleting) == PrintJobStatus::Deleting))
      {
         Console::WriteLine("The user or someone with administration rights to the queue has deleted the job.
   It must be resubmitted.");
      }
      if ((theJob->JobStatus & PrintJobStatus::Error) == PrintJobStatus::Error)
      {
         Console::WriteLine("The job has errored.");
      }
      if ((theJob->JobStatus & PrintJobStatus::Offline) == PrintJobStatus::Offline)
      {
         Console::WriteLine("The printer is offline. Have user put it online with printer front panel.");
      }
      if ((theJob->JobStatus & PrintJobStatus::PaperOut) == PrintJobStatus::PaperOut)
      {
         Console::WriteLine("The printer is out of paper of the size required by the job. Have user add
   paper.");
      }
      if (((theJob->JobStatus & PrintJobStatus::Paused) == PrintJobStatus::Paused)
         ||
         ((theJob->HostingPrintQueue->QueueStatus & PrintQueueStatus::Paused) == PrintQueueStatus::Paused))
      {
         HandlePausedJob(theJob);
         //HandlePausedJob is defined in the complete example.
      }
End Sub
To check print job status using separate properties, you simply read each property and, if the property is true ,
report to the console screen and possibly suggest a way to respond. (The HandlePausedJob method that is
called if the job or queue is paused is discussed below.)
// Check for possible trouble states of a print job using its properties
static void SpotTroubleUsingProperties (PrintSystemJobInfo^ theJob)
{
   if (theJob->IsBlocked)
   {
      Console::WriteLine("The job is blocked.");
   }
   if (theJob->IsCompleted || theJob->IsPrinted)
   {
      Console::WriteLine("The job has finished. Have user recheck all output bins and be sure the correct
printer is being checked.");
   }
   if (theJob->IsDeleted || theJob->IsDeleting)
   {
      Console::WriteLine("The user or someone with administration rights to the queue has deleted the job.
It must be resubmitted.");
   }
   if (theJob->IsInError)
   {
      Console::WriteLine("The job has errored.");
   }
   if (theJob->IsOffline)
   {
      Console::WriteLine("The printer is offline. Have user put it online with printer front panel.");
   }
   if (theJob->IsPaperOut)
   {
      Console::WriteLine("The printer is out of paper of the size required by the job. Have user add
paper.");
   }
     if (theJob->IsPaused || theJob->HostingPrintQueue->IsPaused)
     {
        HandlePausedJob(theJob);
        //HandlePausedJob is defined in the complete example.
     }
     if (theJob->IsPrinting)
     {
        Console::WriteLine("The job is printing now.");
     }
     if (theJob->IsSpooling)
     {
        Console::WriteLine("The job is spooling now.");
     }
     if (theJob->IsUserInterventionRequired)
     {
        Console::WriteLine("The printer needs human intervention.");
     }
};
// Check for possible trouble states of a print job using its properties
internal static void SpotTroubleUsingProperties(PrintSystemJobInfo theJob)
{
    if (theJob.IsBlocked)
    {
        Console.WriteLine("The job is blocked.");
    }
    if (theJob.IsCompleted || theJob.IsPrinted)
    {
        Console.WriteLine("The job has finished. Have user recheck all output bins and be sure the correct
printer is being checked.");
    }
    if (theJob.IsDeleted || theJob.IsDeleting)
    {
        Console.WriteLine("The user or someone with administration rights to the queue has deleted the job.
It must be resubmitted.");
    }
    if (theJob.IsInError)
    {
        Console.WriteLine("The job has errored.");
    }
    if (theJob.IsOffline)
    {
        Console.WriteLine("The printer is offline. Have user put it online with printer front panel.");
    }
    if (theJob.IsPaperOut)
    {
        Console.WriteLine("The printer is out of paper of the size required by the job. Have user add
paper.");
    }
    if (theJob.IsPaused || theJob.HostingPrintQueue.IsPaused)
    {
        HandlePausedJob(theJob);
        //HandlePausedJob is defined in the complete example.
    }
    if (theJob.IsPrinting)
    {
        Console.WriteLine("The job is printing now.");
    }
    if (theJob.IsSpooling)
    {
        Console.WriteLine("The job is spooling now.");
    }
    if (theJob.IsUserInterventionRequired)
    {
        Console.WriteLine("The printer needs human intervention.");
    }
}//end SpotTroubleUsingProperties
   ' Check for possible trouble states of a print job using its properties
   Friend Shared Sub SpotTroubleUsingProperties(ByVal theJob As PrintSystemJobInfo)
       If theJob.IsBlocked Then
            Console.WriteLine("The job is blocked.")
       End If
       If theJob.IsCompleted OrElse theJob.IsPrinted Then
            Console.WriteLine("The job has finished. Have user recheck all output bins and be sure the correct
   printer is being checked.")
       End If
       If theJob.IsDeleted OrElse theJob.IsDeleting Then
            Console.WriteLine("The user or someone with administration rights to the queue has deleted the job.
   It must be resubmitted.")
       End If
       If theJob.IsInError Then
            Console.WriteLine("The job has errored.")
       End If
       If theJob.IsOffline Then
            Console.WriteLine("The printer is offline. Have user put it online with printer front panel.")
       End If
       If theJob.IsPaperOut Then
            Console.WriteLine("The printer is out of paper of the size required by the job. Have user add
   paper.")
       End If
       If theJob.IsPrinting Then
           Console.WriteLine("The job is printing now.")
       End If
       If theJob.IsSpooling Then
           Console.WriteLine("The job is spooling now.")
       End If
       If theJob.IsUserInterventionRequired Then
           Console.WriteLine("The printer needs human intervention.")
       End If
End Sub
The HandlePausedJob method enables the application's user to remotely resume paused jobs. Because there
might be a good reason why the print queue was paused, the method begins by prompting for a user decision
about whether to resume it. If the answer is "Y", then the PrintQueue.Resume method is called.
Next the user is prompted to decide if the job itself should be resumed, just in case it is paused independently of
the print queue. (Compare PrintQueue.IsPaused and PrintSystemJobInfo.IsPaused.) If the answer is "Y", then
PrintSystemJobInfo.Resume is called; otherwise Cancel is called.
static void HandlePausedJob (PrintSystemJobInfo^ theJob)
{
   // If there's no good reason for the queue to be paused, resume it and
   // give user choice to resume or cancel the job.
   Console::WriteLine("The user or someone with administrative rights to the queue" + "\nhas paused the job
or queue." + "\nResume the queue? (Has no effect if queue is not paused.)" + "\nEnter \"Y\" to resume,
otherwise press return: ");
   String^ resume = Console::ReadLine();
   if (resume == "Y")
   {
      theJob->HostingPrintQueue->Resume();
      // It is possible the job is also paused. Find out how the user wants to handle that.
      Console::WriteLine("Does user want to resume print job or cancel it?" + "\nEnter \"Y\" to resume (any
other key cancels the print job): ");
      String^ userDecision = Console::ReadLine();
      if (userDecision == "Y")
      {
         theJob->Resume();
      } else
      {
         theJob->Cancel();
      }
   }
};
        // It is possible the job is also paused. Find out how the user wants to handle that.
        Console.WriteLine("Does user want to resume print job or cancel it?" +
             "\nEnter \"Y\" to resume (any other key cancels the print job): ");
        String userDecision = Console.ReadLine();
        if (userDecision == "Y")
        {
             theJob.Resume();
        }
        else
        {
             theJob.Cancel();
        }
    }//end if the queue should be resumed
}//end HandlePausedJob
 Friend Shared Sub HandlePausedJob(ByVal theJob As PrintSystemJobInfo)
     ' If there's no good reason for the queue to be paused, resume it and
     ' give user choice to resume or cancel the job.
     Console.WriteLine("The user or someone with administrative rights to the queue" & vbLf & "has paused the
 job or queue." & vbLf & "Resume the queue? (Has no effect if queue is not paused.)" & vbLf & "Enter ""Y"" to
 resume, otherwise press return: ")
     Dim [resume] As String = Console.ReadLine()
     If [resume] = "Y" Then
         theJob.HostingPrintQueue.Resume()
         ' It is possible the job is also paused. Find out how the user wants to handle that.
         Console.WriteLine("Does user want to resume print job or cancel it?" & vbLf & "Enter ""Y"" to resume
 (any other key cancels the print job): ")
         Dim userDecision As String = Console.ReadLine()
         If userDecision = "Y" Then
              theJob.Resume()
         Else
              theJob.Cancel()
         End If
     End If 'end if the queue should be resumed
End Sub
See also
 PrintJobStatus
 PrintSystemJobInfo
 FlagsAttribute
 PrintQueue
 & Operator (C# Reference)
 Documents in WPF
 Printing Overview
       How to: Discover Whether a Print Job Can Be
       Printed At This Time of Day
       11/21/2022 • 8 minutes to read • Edit Online
Print queues are not always available for 24 hours a day. They have start and end time properties that can be set
to make them unavailable at certain times of day. This feature can be used, for example, to reserve a printer for
the exclusive use of a certain department after 5 P.M.. That department would have a different queue servicing
the printer than other departments use. The queue for the other departments would be set to be unavailable
after 5 P.M., while queue for the favored department could be set to be available at all times.
Moreover, print jobs themselves can be set to be printable only within a specified span of time.
The PrintQueue and PrintSystemJobInfo classes exposed in the APIs of Microsoft .NET Framework provide a
means for remotely checking whether a given print job can print on a given queue at the current time.
Example
The example below is a sample that can diagnose problems with a print job.
There are two major steps for this kind of function as follows.
1. Read the StartTimeOfDay and UntilTimeOfDay properties of the PrintQueue to determine whether the
   current time is between them.
2. Read the StartTimeOfDay and UntilTimeOfDay properties of the PrintSystemJobInfo to determine
   whether the current time is between them.
But complications arise from the fact that these properties are not DateTime objects. Instead they are Int32
objects that express the time of day as the number of minutes since midnight. Moreover, this is not midnight in
the current time zone, but midnight UTC (Coordinated Universal Time).
The first code example presents the static method Repor tQueueAndJobAvailability , which is passed a
PrintSystemJobInfo and calls helper methods to determine whether the job can print at the current time and, if
not, when it can print. Notice that a PrintQueue is not passed to the method. This is because the
PrintSystemJobInfo includes a reference to the queue in its HostingPrintQueue property.
The subordinate methods include the overloaded Repor tAvailabilityAtThisTime method which can take
either a PrintQueue or a PrintSystemJobInfo as a parameter. There is also a
TimeConver ter.Conver tToLocalHumanReadableTime . All of these methods are discussed below.
The Repor tQueueAndJobAvailability method begins by checking to see if either the queue or the print job is
unavailable at this time. If either of them is unavailable, it then checks to see if the queue unavailable. If it is not
available, then the method reports this fact and the time when the queue will become available again. It then
checks the job and if it is unavailable, it reports the next time span when it when it can print. Finally, the method
reports the earliest time when the job can print. This is the later of following two times.
   The time when the print queue is next available.
   The time when the print job is next available.
When reporting times of day, the ToShortTimeString method is also called because this method suppresses the
years, months, and days from the output. You cannot restrict the availability of either a print queue or a print job
to particular years, months, or days.
static void ReportQueueAndJobAvailability (PrintSystemJobInfo^ theJob)
{
   if (!(ReportAvailabilityAtThisTime(theJob->HostingPrintQueue) && ReportAvailabilityAtThisTime(theJob)))
   {
      if (!ReportAvailabilityAtThisTime(theJob->HostingPrintQueue))
      {
         Console::WriteLine("\nThat queue is not available at this time of day." + "\nJobs in the queue will
start printing again at {0}", TimeConverter::ConvertToLocalHumanReadableTime(theJob->HostingPrintQueue-
>StartTimeOfDay).ToShortTimeString());
         // TimeConverter class is defined in the complete sample
      }
      if (!ReportAvailabilityAtThisTime(theJob))
      {
         Console::WriteLine("\nThat job is set to print only between {0} and {1}",
TimeConverter::ConvertToLocalHumanReadableTime(theJob->StartTimeOfDay).ToShortTimeString(),
TimeConverter::ConvertToLocalHumanReadableTime(theJob->UntilTimeOfDay).ToShortTimeString());
      }
      Console::WriteLine("\nThe job will begin printing as soon as it reaches the top of the queue after:");
      if (theJob->StartTimeOfDay > theJob->HostingPrintQueue->StartTimeOfDay)
      {
         Console::WriteLine(TimeConverter::ConvertToLocalHumanReadableTime(theJob-
>StartTimeOfDay).ToShortTimeString());
      } else
      {
         Console::WriteLine(TimeConverter::ConvertToLocalHumanReadableTime(theJob->HostingPrintQueue-
>StartTimeOfDay).ToShortTimeString());
      }
     }
};
TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString());
            // TimeConverter class is defined in the complete sample
        }
        if (!ReportAvailabilityAtThisTime(theJob))
        {
            Console.WriteLine("\nThat job is set to print only between {0} and {1}",
                TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString(),
                TimeConverter.ConvertToLocalHumanReadableTime(theJob.UntilTimeOfDay).ToShortTimeString());
        }
        Console.WriteLine("\nThe job will begin printing as soon as it reaches the top of the queue
after:");
        if (theJob.StartTimeOfDay > theJob.HostingPrintQueue.StartTimeOfDay)
        {
Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString());
        }
        else
        {
Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToS
hortTimeString());
        }
    }//end if at least one is not available
}//end ReportQueueAndJobAvailability
   Friend Shared Sub ReportQueueAndJobAvailability(ByVal theJob As PrintSystemJobInfo)
       If Not(ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) AndAlso
   ReportAvailabilityAtThisTime(theJob)) Then
           If Not ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) Then
               Console.WriteLine(vbLf & "That queue is not available at this time of day." & vbLf & "Jobs in
   the queue will start printing again at {0}",
   TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString())
               ' TimeConverter class is defined in the complete sample
           End If
   Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString())
           Else
   Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToS
   hortTimeString())
           End If
End Sub
The two overloads of the Repor tAvailabilityAtThisTime method are identical except for the type passed to
them, so only the PrintQueue version is presented below.
  NOTE
  The fact that the methods are identical except for type raises the question of why the sample does not create a generic
  method Repor tAvailabilityAtThisTime<T> . The reason is that such a method would have to be restricted to a class
  that has the Star tTimeOfDay and UntilTimeOfDay properties that the method calls, but a generic method can only be
  restricted to a single class and the only class common to both PrintQueue and PrintSystemJobInfo in the inheritance tree
  is PrintSystemObject which has no such properties.
The Repor tAvailabilityAtThisTime method (presented in the code example below) begins by initializing a
Boolean sentinel variable to true . It will be reset to false , if the queue is not available.
Next, the method checks to see if the start and "until" times are identical. If they are, the queue is always
available, so the method returns true .
If the queue is not available all the time, the method uses the static UtcNow property to get the current time as a
DateTime object. (We do not need local time because the StartTimeOfDay and UntilTimeOfDay properties are
themselves in UTC time.)
However, these two properties are not DateTime objects. They are Int32s expressing the time as the number of
minutes-after-UTC-midnight. So we do have to convert our DateTime object to minutes-after-midnight. When
that is done, the method simply checks to see whether "now" is between the queue's start and "until" times, sets
the sentinel to false if "now" is not between the two times, and returns the sentinel.
   static Boolean ReportAvailabilityAtThisTime (PrintQueue^ pq)
   {
      Boolean available = true;
      if (pq->StartTimeOfDay != pq->UntilTimeOfDay)
      {
         DateTime utcNow = DateTime::UtcNow;
         Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes;
The TimeConver ter.Conver tToLocalHumanReadableTime method (presented in the code example below)
does not use any methods introduced with Microsoft .NET Framework, so the discussion is brief. The method
has a double conversion task: it must take an integer expressing minutes-after-midnight and convert it to a
human-readable time and it must convert this to the local time. It accomplishes this by first creating a DateTime
object that is set to midnight UTC and then it uses the AddMinutes method to add the minutes that were passed
to the method. This returns a new DateTime expressing the original time that was passed to the method. The
ToLocalTime method then converts this to local time.
private ref class TimeConverter {
internal:
   static DateTime ConvertToLocalHumanReadableTime (Int32 timeInMinutesAfterUTCMidnight)
   {
      // Construct a UTC midnight object.
      // Must start with current date so that the local Daylight Savings system, if any, will be taken into
account.
      DateTime utcNow = DateTime::UtcNow;
      DateTime utcMidnight = DateTime(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind::Utc);
          // Add the minutes passed into the method in order to get the intended UTC time.
          Double minutesAfterUTCMidnight = ((Double)timeInMinutesAfterUTCMidnight);
          DateTime utcTime = utcMidnight.AddMinutes(minutesAfterUTCMidnight);
          return localTime;
     };
};
class TimeConverter
{
    // Convert time as minutes past UTC midnight into human readable time in local time zone.
    internal static DateTime ConvertToLocalHumanReadableTime(Int32 timeInMinutesAfterUTCMidnight)
    {
        // Construct a UTC midnight object.
        // Must start with current date so that the local Daylight Savings system, if any, will be taken
into account.
        DateTime utcNow = DateTime.UtcNow;
        DateTime utcMidnight = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0,
DateTimeKind.Utc);
            // Add the minutes passed into the method in order to get the intended UTC time.
            Double minutesAfterUTCMidnight = (Double)timeInMinutesAfterUTCMidnight;
            DateTime utcTime = utcMidnight.AddMinutes(minutesAfterUTCMidnight);
        return localTime;
    }// end ConvertToLocalHumanReadableTime
}//end TimeConverter class
 Friend Class TimeConverter
      ' Convert time as minutes past UTC midnight into human readable time in local time zone.
      Friend Shared Function ConvertToLocalHumanReadableTime(ByVal timeInMinutesAfterUTCMidnight As Int32) As
 Date
          ' Construct a UTC midnight object.
          ' Must start with current date so that the local Daylight Savings system, if any, will be taken into
 account.
          Dim utcNow As Date = Date.UtcNow
          Dim utcMidnight As New Date(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind.Utc)
         ' Add the minutes passed into the method in order to get the intended UTC time.
         Dim minutesAfterUTCMidnight As Double = CType(timeInMinutesAfterUTCMidnight, Double)
         Dim utcTime As Date = utcMidnight.AddMinutes(minutesAfterUTCMidnight)
Return localTime
End Class
See also
 DateTime
 PrintSystemJobInfo
 PrintQueue
 Documents in WPF
 Printing Overview
       How to: Enumerate a Subset of Print Queues
       11/21/2022 • 2 minutes to read • Edit Online
A common situation faced by information technology (IT) professionals managing a company-wide set of
printers is to generate a list of printers having certain characteristics. This functionality is provided by the
GetPrintQueues method of a PrintServer object and the EnumeratedPrintQueueTypes enumeration.
Example
In the example below, the code begins by creating an array of flags that specify the characteristics of the print
queues we want to list. In this example, we are looking for print queues that are installed locally on the print
server and are shared. The EnumeratedPrintQueueTypes enumeration provides many other possibilities.
The code then creates a LocalPrintServer object, a class derived from PrintServer. The local print server is the
computer on which the application is running.
The last significant step is to pass the array to the GetPrintQueues method.
Finally, the results are presented to the user.
   // Specify that the list will contain only the print queues that are installed as local and are shared
   array<System::Printing::EnumeratedPrintQueueTypes>^ enumerationFlags =
   {EnumeratedPrintQueueTypes::Local,EnumeratedPrintQueueTypes::Shared};
   // Specify that the list will contain only the print queues that are installed as local and are shared
   EnumeratedPrintQueueTypes[] enumerationFlags = {EnumeratedPrintQueueTypes.Local,
                                                   EnumeratedPrintQueueTypes.Shared};
Console.WriteLine("These are your shared, local print queues:" & vbLf & vbLf)
You could extend this example by having the foreach loop that steps through each print queue do further
screening. For example, you could screen out printers that do not support two-sided printing by having the loop
call each print queue's GetPrintCapabilities method and test the returned value for the presence of duplexing.
See also
   GetPrintQueues
   PrintServer
   LocalPrintServer
   EnumeratedPrintQueueTypes
   PrintQueue
   GetPrintCapabilities
   Documents in WPF
   Printing Overview
   Microsoft XPS Document Writer
       How to: Get Print System Object Properties Without
       Reflection
       11/21/2022 • 2 minutes to read • Edit Online
Using reflection to itemize the properties (and the types of those properties) on an object can slow application
performance. The System.Printing.IndexedProperties namespace provides a means to getting this information
without using reflection.
Example
The steps for doing this are as follows.
1. Create an instance of the type. In the example below, the type is the PrintQueue type that ships with
   Microsoft .NET Framework, but nearly identical code should work for types that you derive from
   PrintSystemObject.
2. Create a PrintPropertyDictionary from the type's PropertiesCollection. The Value property of each entry
   in this dictionary is an object of one of the types derived from PrintProperty.
3. Enumerate the members of the dictionary. For each of them, do the following.
4. Up-cast the value of each entry to PrintProperty and use it to create a PrintProperty object.
5. Get the type of the Value of each of the PrintProperty object.
   // Enumerate the properties, and their types, of a queue without using Reflection
   LocalPrintServer localPrintServer = new LocalPrintServer();
   PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();
   Console.WriteLine("These are the properties, and their types, of {0}, a {1}", defaultPrintQueue.Name,
   defaultPrintQueue.GetType().ToString() +"\n");
       if (property.Value != null)
       {
           Console.WriteLine(property.Name + "\t(Type: {0})", property.Value.GetType().ToString());
       }
   }
   Console.WriteLine("\n\nPress Return to continue...");
   Console.ReadLine();
 ' Enumerate the properties, and their types, of a queue without using Reflection
 Dim localPrintServer As New LocalPrintServer()
 Dim defaultPrintQueue As PrintQueue = LocalPrintServer.GetDefaultPrintQueue()
 Console.WriteLine("These are the properties, and their types, of {0}, a {1}", defaultPrintQueue.Name,
 defaultPrintQueue.GetType().ToString() + vbLf)
See also
 PrintProperty
 PrintSystemObject
 System.Printing.IndexedProperties
 PrintPropertyDictionary
 LocalPrintServer
 PrintQueue
 DictionaryEntry
 Documents in WPF
 Printing Overview
       How to: Programmatically Print XPS Files
       11/21/2022 • 7 minutes to read • Edit Online
You can use one overload of the AddJob method to print XML Paper Specification (XPS) files without opening a
PrintDialog or, in principle, any user interface (UI) at all.
You can also print XPS files using the many XpsDocumentWriter.Write and XpsDocumentWriter.WriteAsync
methods. For more information, see Printing an XPS Document.
Another way of printing XPS is to use the PrintDialog.PrintDocument or PrintDialog.PrintVisual methods. See
Invoke a Print Dialog.
Example
The main steps to using the three-parameter AddJob(String, String, Boolean) method are as follows. The
example below gives details.
1. Determine if the printer is an XPSDrv printer. See Printing Overview for more about XPSDrv.
2. If the printer is not an XPSDrv printer, set the thread's apartment to single thread.
3. Instantiate a print server and print queue object.
4. Call the method, specifying a job name, the file to be printed, and a Boolean flag indicating whether or
   not the printer is an XPSDrv printer.
The example below shows how to batch print all XPS files in a directory. Although the application prompts the
user to specify the directory, the three-parameter AddJob(String, String, Boolean) method does not require a
user interface (UI). It can be used in any code path where you have an XPS file name and path that you can pass
to it.
The three-parameter AddJob(String, String, Boolean) overload of AddJob must run in a single thread apartment
whenever the Boolean parameter is false , which it must be when a non-XPSDrv printer is being used.
However, the default apartment state for .NET is multiple thread. This default must be reversed since the
example assumes a non-XPSDrv printer.
There are two ways to change the default. One way is to simply add the STAThreadAttribute (that is, "
 [System.STAThreadAttribute()] ") just above the first line of the application's Main method (usually "
 static void Main(string[] args) "). However, many applications require that the Main method have a multi-
threaded apartment state, so there is a second method: put the call to AddJob(String, String, Boolean) in a
separate thread whose apartment state is set to STA with SetApartmentState. The example below uses this
second technique.
Accordingly, the example begins by instantiating a Thread object and passing it a PrintXPS method as the
ThreadStart parameter. (The PrintXPS method is defined later in the example.) Next the thread is set to a single
thread apartment. The only remaining code of the Main method starts the new thread.
The meat of the example is in the static BatchXPSPrinter.PrintXPS method. After creating a print server and
queue, the method prompts the user for a directory containing XPS files. After validating the existence of the
directory and the presence of *.xps files in it, the method adds each such file to the print queue. The example
assumes that the printer is non-XPSDrv, so we are passing false to the last parameter of AddJob(String, String,
Boolean) method. For this reason, the method will validate the XPS markup in the file before it attempts to
convert it to the printer's page description language. If the validation fails, an exception is thrown. The example
code will catch the exception, notify the user about it, and then go on to process the next XPS file.
   class Program
   {
       [System.MTAThreadAttribute()] // Added for clarity, but this line is redundant because MTA is the
   default.
       static void Main(string[] args)
       {
            // Create the secondary thread and pass the printing method for
            // the constructor's ThreadStart delegate parameter. The BatchXPSPrinter
            // class is defined below.
            Thread printingThread = new Thread(BatchXPSPrinter.PrintXPS);
           // Prompt user to identify the directory, and then create the directory object.
           Console.Write("Enter the directory containing the XPS files: ");
           String directoryPath = Console.ReadLine();
           DirectoryInfo dir = new DirectoryInfo(directoryPath);
           // If the user mistyped, end the thread and return to the Main thread.
           if (!dir.Exists)
           {
                Console.WriteLine("There is no such directory.");
           }
           else
           {
                // If there are no XPS files in the directory, end the thread
                // and return to the Main thread.
                if (dir.GetFiles("*.xps").Length == 0)
                {
                     Console.WriteLine("There are no XPS files in the directory.");
                }
                else
                {
                     Console.WriteLine("\nJobs will now be added to the print queue.");
                     Console.WriteLine("If the queue is not paused and the printer is working, jobs will begin
   printing.");
                        try
                        {
                              // Print the Xps file while providing XPS validation and progress notifications.
                              PrintSystemJobInfo xpsPrintJob = defaultPrintQueue.AddJob(f.Name, nextFile, false);
                        }
                        catch (PrintJobException e)
                        {
                            Console.WriteLine("\n\t{0} could not be added to the print queue.", f.Name);
                            Console.WriteLine("\n\t{0} could not be added to the print queue.", f.Name);
                            if (e.InnerException.Message == "File contains corrupted data.")
                            {
                                Console.WriteLine("\tIt is not a valid XPS file. Use the isXPS Conformance Tool
to debug it.");
                            }
                            Console.WriteLine("\tContinuing with next XPS file.\n");
                    }
                }// end for each XPS file
            }//end if there are no XPS files in the directory
        }//end if the directory does not exist
        ' Set the thread that will use PrintQueue.AddJob to single threading.
        printingThread.SetApartmentState(ApartmentState.STA)
        ' Start the printing thread. The method passed to the Thread
        ' constructor will execute.
        printingThread.Start()
End Sub
End Class
        ' Prompt user to identify the directory, and then create the directory object.
        Console.Write("Enter the directory containing the XPS files: ")
        Dim directoryPath As String = Console.ReadLine()
        Dim dir As New DirectoryInfo(directoryPath)
        ' If the user mistyped, end the thread and return to the Main thread.
        If Not dir.Exists Then
             Console.WriteLine("There is no such directory.")
        Else
             ' If there are no XPS files in the directory, end the thread
             ' and return to the Main thread.
             If dir.GetFiles("*.xps").Length = 0 Then
                  Console.WriteLine("There are no XPS files in the directory.")
             Else
                  Console.WriteLine(vbLf & "Jobs will now be added to the print queue.")
                  Console.WriteLine("If the queue is not paused and the printer is working, jobs will begin
printing.")
                      Try
                            ' Print the Xps file while providing XPS validation and progress notifications.
                               Dim xpsPrintJob As PrintSystemJobInfo = defaultPrintQueue.AddJob(f.Name, nextFile,
   False)
                           Catch e As PrintJobException
                               Console.WriteLine(vbLf & vbTab & "{0} could not be added to the print queue.",
   f.Name)
                               If e.InnerException.Message = "File contains corrupted data." Then
                                   Console.WriteLine(vbTab & "It is not a valid XPS file. Use the isXPS Conformance
   Tool to debug it.")
                               End If
                               Console.WriteLine(vbTab & "Continuing with next XPS file." & vbLf)
                           End Try
End Sub
End Class
If you are using an XPSDrv printer, then you can set the final parameter to true . In that case, since XPS is the
printer's page description language, the method will send the file to the printer without validating it or
converting it to another page description language. If you are uncertain at design time whether the application
will be using an XPSDrv printer, you can modify the application to have it read the IsXpsDevice property and
branch according to what it finds.
Since there will initially be few XPSDrv printers available immediately after the release of Windows Vista and
Microsoft .NET Framework, you may need to disguise a non-XPSDrv printer as an XPSDrv printer. To do so, add
Pipelineconfig.xml to the list of files in the following registry key of the computer running your application:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT
x86\Drivers\Version-3\<PseudoXPSPrinter>\DependentFiles
where <PseudoXPSPrinter> is any print queue. The machine must then be rebooted.
This disguise will enable you to pass true as the final parameter of AddJob(String, String, Boolean) without
causing an exception, but since <PseudoXPSPrinter> is not really an XPSDrv printer, only garbage will print.
  NOTE
  For simplicity, the example above uses the presence of an *.xps extension as its test that a file is XPS. However, XPS files do
  not have to have this extension. The isXPS.exe (isXPS Conformance Tool) is one way of testing a file for XPS validity.
See also
   PrintQueue
   AddJob
   ApartmentState
   STAThreadAttribute
   XPS Documents
   Printing an XPS Document
   Managed and Unmanaged Threading
   isXPS.exe (isXPS Conformance Tool)
Documents in WPF
Printing Overview
       How to: Remotely Survey the Status of Printers
       11/21/2022 • 13 minutes to read • Edit Online
At any given time at medium and large companies there may be multiple printers that are not working due to a
paper jam or being out of paper or some other problematic situation. The rich set of printer properties exposed
in the APIs of Microsoft .NET Framework provide a means for performing a rapid survey of the states of printers.
Example
The major steps for creating this kind of utility are as follows.
1. Obtain a list of all print servers.
2. Loop through the servers to query their print queues.
3. Within each pass of the server loop, loop through all the server's queues and read each property that
   might indicate that the queue is not currently working.
The code below is a series of snippets. For simplicity, this example assumes that there is a CRLF-delimited list of
print servers. The variable fileOfPrintServers is a StreamReader object for this file. Since each server name is
on its own line, any call of ReadLine gets the name of the next server and moves the StreamReader's cursor to
the beginning of the next line.
Within the outer loop, the code creates a PrintServer object for the latest print server and specifies that the
application is to have administrative rights to the server.
  NOTE
  If there are a lot of servers, you can improve performance by using the PrintServer(String, String[],
  PrintSystemDesiredAccess) constructors that only initialize the properties you are going to need.
The example then uses GetPrintQueues to create a collection of all of the server's queues and begins to loop
through them. This inner loop contains a branching structure corresponding to the two ways of checking a
printer's status:
   You can read the flags of the QueueStatus property which is of type PrintQueueStatus.
   You can read each relevant property such as IsOutOfPaper, and IsPaperJammed.
This example demonstrates both methods, so the user was previously prompted as to which method to use and
responded with "y" if they wanted to use the flags of the QueueStatus property. See below for the details of the
two methods.
Finally, the results are presented to the user.
// Survey queue status for every queue on every print server
System::String^ line;
System::String^ statusReport = "\n\nAny problem states are indicated below:\n\n";
while ((line = fileOfPrintServers->ReadLine()) != nullptr)
{
   System::Printing::PrintServer^ myPS = gcnew System::Printing::PrintServer(line,
PrintSystemDesiredAccess::AdministrateServer);
   System::Printing::PrintQueueCollection^ myPrintQueues = myPS->GetPrintQueues();
   statusReport = statusReport + "\n" + line;
   for each (System::Printing::PrintQueue^ pq in myPrintQueues)
   {
      pq->Refresh();
      statusReport = statusReport + "\n\t" + pq->Name + ":";
      if (useAttributesResponse == "y")
      {
         TroubleSpotter::SpotTroubleUsingQueueAttributes(statusReport, pq);
         // TroubleSpotter class is defined in the complete example.
      } else
      {
         TroubleSpotter::SpotTroubleUsingProperties(statusReport, pq);
      }
   }
}
fileOfPrintServers->Close();
Console::WriteLine(statusReport);
Console::WriteLine("\nPress Return to continue.");
Console::ReadLine();
fileOfPrintServers.Close();
Console.WriteLine(statusReport);
Console.WriteLine("\nPress Return to continue.");
Console.ReadLine();
   ' Survey queue status for every queue on every print server
   Dim line As String
   Dim statusReport As String = vbLf & vbLf & "Any problem states are indicated below:" & vbLf & vbLf
   line = fileOfPrintServers.ReadLine()
   Do While line IsNot Nothing
        Dim myPS As New PrintServer(line, PrintSystemDesiredAccess.AdministrateServer)
        Dim myPrintQueues As PrintQueueCollection = myPS.GetPrintQueues()
        statusReport = statusReport & vbLf & line
        For Each pq As PrintQueue In myPrintQueues
            pq.Refresh()
            statusReport = statusReport & vbLf & vbTab & pq.Name & ":"
            If useAttributesResponse = "y" Then
                 TroubleSpotter.SpotTroubleUsingQueueAttributes(statusReport, pq)
                 ' TroubleSpotter class is defined in the complete example.
            Else
                 TroubleSpotter.SpotTroubleUsingProperties(statusReport, pq)
            End If
       line = fileOfPrintServers.ReadLine()
   Loop ' end while list of print servers is not yet exhausted
   fileOfPrintServers.Close()
   Console.WriteLine(statusReport)
   Console.WriteLine(vbLf & "Press Return to continue.")
   Console.ReadLine()
To check printer status using the flags of the QueueStatus property, you check each relevant flag to see if it is set.
The standard way to see if one bit is set in a set of bit flags is to perform a logical AND operation with the set of
flags as one operand and the flag itself as the other. Since the flag itself has only one bit set, the result of the
logical AND is that, at most, that same bit is set. To find out whether it is or not, just compare the result of the
logical AND with the flag itself. For more information, see PrintQueueStatus, the & Operator (C# Reference), and
FlagsAttribute.
For each attribute whose bit is set, the code adds a notice to the final report that will be presented to the user.
(The Repor tAvailabilityAtThisTime method that is called at the end of the code is discussed below.)
internal:
    // Check for possible trouble states of a printer using the flags of the QueueStatus property
    static void SpotTroubleUsingQueueAttributes (System::String^% statusReport, System::Printing::PrintQueue^
pq)
    {
       if ((pq->QueueStatus & PrintQueueStatus::PaperProblem) == PrintQueueStatus::PaperProblem)
       {
          statusReport = statusReport + "Has a paper problem. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::NoToner) == PrintQueueStatus::NoToner)
       {
          statusReport = statusReport + "Is out of toner. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::DoorOpen) == PrintQueueStatus::DoorOpen)
       {
          statusReport = statusReport + "Has an open door. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::Error) == PrintQueueStatus::Error)
       {
          statusReport = statusReport + "Is in an error state. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::NotAvailable) == PrintQueueStatus::NotAvailable)
       {
          statusReport = statusReport + "Is not available. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::Offline) == PrintQueueStatus::Offline)
       {
          statusReport = statusReport + "Is off line. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::OutOfMemory) == PrintQueueStatus::OutOfMemory)
       {
          statusReport = statusReport + "Is out of memory. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::PaperOut) == PrintQueueStatus::PaperOut)
       {
          statusReport = statusReport + "Is out of paper. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::OutputBinFull) == PrintQueueStatus::OutputBinFull)
       {
          statusReport = statusReport + "Has a full output bin. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::PaperJam) == PrintQueueStatus::PaperJam)
       {
          statusReport = statusReport + "Has a paper jam. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::Paused) == PrintQueueStatus::Paused)
       {
          statusReport = statusReport + "Is paused. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::TonerLow) == PrintQueueStatus::TonerLow)
       {
          statusReport = statusReport + "Is low on toner. ";
       }
       if ((pq->QueueStatus & PrintQueueStatus::UserIntervention) == PrintQueueStatus::UserIntervention)
       {
          statusReport = statusReport + "Needs user intervention. ";
       }
To check printer status using each property, you simply read each property and add a note to the final report
that will be presented to the user if the property is true . (The Repor tAvailabilityAtThisTime method that is
called at the end of the code is discussed below.)
internal:
   // Check for possible trouble states of a printer using its properties
   static void SpotTroubleUsingProperties (System::String^% statusReport, System::Printing::PrintQueue^ pq)
   {
      if (pq->HasPaperProblem)
      {
          statusReport = statusReport + "Has a paper problem. ";
      }
      if (!(pq->HasToner))
      {
          statusReport = statusReport + "Is out of toner. ";
      }
      if (pq->IsDoorOpened)
      {
          statusReport = statusReport + "Has an open door. ";
      }
      if (pq->IsInError)
      {
          statusReport = statusReport + "Is in an error state. ";
      }
      if (pq->IsNotAvailable)
      {
          statusReport = statusReport + "Is not available. ";
      }
      if (pq->IsOffline)
      {
          statusReport = statusReport + "Is off line. ";
      }
      if (pq->IsOutOfMemory)
      {
          statusReport = statusReport + "Is out of memory. ";
      }
      if (pq->IsOutOfPaper)
      {
          statusReport = statusReport + "Is out of paper. ";
      }
      if (pq->IsOutputBinFull)
      {
          statusReport = statusReport + "Has a full output bin. ";
      }
      if (pq->IsPaperJammed)
      {
          statusReport = statusReport + "Has a paper jam. ";
      }
      if (pq->IsPaused)
      {
          statusReport = statusReport + "Is paused. ";
      }
      if (pq->IsTonerLow)
      {
          statusReport = statusReport + "Is low on toner. ";
      }
      if (pq->NeedUserIntervention)
      {
          statusReport = statusReport + "Needs user intervention. ";
      }
End Sub
The Repor tAvailabilityAtThisTime method was created in case you need to determine if the queue is
available at the current time of day.
The method will do nothing if the StartTimeOfDay and UntilTimeOfDay properties are equal; because in that
case the printer is available at all times. If they are different, the method gets the current time which then has to
be converted into total minutes past midnight because the StartTimeOfDay and UntilTimeOfDay properties are
Int32s representing minutes-after-midnight, not DateTime objects. Finally, the method checks to see if the
current time is between the start and "until" times.
 private:
     static void ReportAvailabilityAtThisTime (System::String^% statusReport, System::Printing::PrintQueue^
 pq)
     {
        if (pq->StartTimeOfDay != pq->UntilTimeOfDay)
        {
           System::DateTime utcNow = DateTime::UtcNow;
           System::Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) +
 utcNow.TimeOfDay.Minutes;
See also
 StartTimeOfDay
 UntilTimeOfDay
 DateTime
 PrintQueueStatus
 FlagsAttribute
 GetPrintQueues
 PrintServer
 LocalPrintServer
EnumeratedPrintQueueTypes
PrintQueue
& Operator (C# Reference)
Documents in WPF
Printing Overview
       How to: Validate and Merge PrintTickets
       11/21/2022 • 8 minutes to read • Edit Online
The Microsoft Windows Print Schema includes the flexible and extensible PrintCapabilities and PrintTicket
elements. The former itemizes the capabilities of a print device and the latter specifies how the device should
use those capabilities with respect to a particular sequence of documents, individual document, or individual
page.
A typical sequence of tasks for an application that supports printing would be as follows.
1. Determine a printer's capabilities.
2. Configure a PrintTicket to use those capabilities.
3. Validate the PrintTicket.
This article shows how to do this.
Example
In the simple example below, we are interested only in whether a printer can support duplexing — two-sided
printing. The major steps are as follows.
1. Get a PrintCapabilities object with the GetPrintCapabilities method.
2. Test for the presence of the capability you want. In the example below, we test the DuplexingCapability
   property of the PrintCapabilities object for the presence of the capability of printing on both sides of a
   sheet of paper with the "page turning" along the long side of the sheet. Since DuplexingCapability is a
   collection, we use the Contains method of ReadOnlyCollection<T>.
     NOTE
     This step is not strictly necessary. The MergeAndValidatePrintTicket method used below will check each request in
     the PrintTicket against the capabilities of the printer. If the requested capability is not supported by printer, the
     printer driver will substitute an alternative request in the PrintTicket returned by the method.
3. If the printer supports duplexing, the sample code creates a PrintTicket that asks for duplexing. But the
   application does not specify every possible printer setting available in the PrintTicket element. That would
   be wasteful of both programmer and program time. Instead, the code sets only the duplexing request and
   then merges this PrintTicket with an existing, fully configured and validated, PrintTicket, in this case, the
   user's default PrintTicket.
4. Accordingly, the sample calls the MergeAndValidatePrintTicket method to merge the new, minimal,
   PrintTicket with the user's default PrintTicket. This returns a ValidationResult that includes the new
   PrintTicket as one of its properties.
5. The sample then tests that the new PrintTicket requests duplexing. If it does, then the sample makes it the
   new default print ticket for the user. If step 2 above had been left out and the printer did not support
   duplexing along the long side, then the test would have resulted in false . (See the note above.)
6. The last significant step is to commit the change to the UserPrintTicket property of the PrintQueue with
   the Commit method.
/// <summary>
/// Changes the user-default PrintTicket setting of the specified print queue.
/// </summary>
/// <param name="queue">the printer whose user-default PrintTicket setting needs to be changed</param>
static private void ChangePrintTicketSetting(PrintQueue queue)
{
    //
    // Obtain the printer's PrintCapabilities so we can determine whether or not
    // duplexing printing is supported by the printer.
    //
    PrintCapabilities printcap = queue.GetPrintCapabilities();
    //
    //   The printer's duplexing capability is returned as a read-only collection of duplexing options
    //   that can be supported by the printer. If the collection returned contains the duplexing
    //   option we want to set, it means the duplexing option we want to set is supported by the printer,
    //   so we can make the user-default PrintTicket setting change.
    //
    if   (printcap.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
    {
           //
           // To change the user-default PrintTicket, we can first create a delta PrintTicket with
           // the new duplexing setting.
           //
           PrintTicket deltaTicket = new PrintTicket();
           deltaTicket.Duplexing = Duplexing.TwoSidedLongEdge;
           //
           // Then merge the delta PrintTicket onto the printer's current user-default PrintTicket,
           // and validate the merged PrintTicket to get the new PrintTicket we want to set as the
           // printer's new user-default PrintTicket.
           //
           ValidationResult result = queue.MergeAndValidatePrintTicket(queue.UserPrintTicket, deltaTicket);
           //
           //   The duplexing option we want to set could be constrained by other PrintTicket settings
           //   or device settings. We can check the validated merged PrintTicket to see whether the
           //   the validation process has kept the duplexing option we want to set unchanged.
           //
           if   (result.ValidatedPrintTicket.Duplexing == Duplexing.TwoSidedLongEdge)
           {
                  //
                  // Set the printer's user-default PrintTicket and commit the set operation.
                  //
                  queue.UserPrintTicket = result.ValidatedPrintTicket;
                  queue.Commit();
                  Console.WriteLine("PrintTicket new duplexing setting is set on '{0}'.", queue.FullName);
           }
           else
           {
                  //
                  // The duplexing option we want to set has been changed by the validation process
                  // when it was resolving setting constraints.
                  //
                  Console.WriteLine("PrintTicket new duplexing setting is constrained on '{0}'.", queue.FullName);
           }
    }
    else
    {
           //
           // If the printer doesn't support the duplexing option we want to set, skip it.
           //
           Console.WriteLine("PrintTicket new duplexing setting is not supported on '{0}'.", queue.FullName);
    }
}
   ''' <summary>
   ''' Changes the user-default PrintTicket setting of the specified print queue.
   ''' </summary>
   ''' <param name="queue">the printer whose user-default PrintTicket setting needs to be changed</param>
   Private Shared Sub ChangePrintTicketSetting(ByVal queue As PrintQueue)
       '
       ' Obtain the printer's PrintCapabilities so we can determine whether or not
       ' duplexing printing is supported by the printer.
       '
       Dim printcap As PrintCapabilities = queue.GetPrintCapabilities()
       '
       ' The printer's duplexing capability is returned as a read-only collection of duplexing options
       ' that can be supported by the printer. If the collection returned contains the duplexing
       ' option we want to set, it means the duplexing option we want to set is supported by the printer,
       ' so we can make the user-default PrintTicket setting change.
       '
       If printcap.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) Then
           '
           ' To change the user-default PrintTicket, we can first create a delta PrintTicket with
           ' the new duplexing setting.
           '
           Dim deltaTicket As New PrintTicket()
           deltaTicket.Duplexing = Duplexing.TwoSidedLongEdge
           '
           ' Then merge the delta PrintTicket onto the printer's current user-default PrintTicket,
           ' and validate the merged PrintTicket to get the new PrintTicket we want to set as the
           ' printer's new user-default PrintTicket.
           '
           Dim result As ValidationResult = queue.MergeAndValidatePrintTicket(queue.UserPrintTicket,
   deltaTicket)
              '
              ' The duplexing option we want to set could be constrained by other PrintTicket settings
              ' or device settings. We can check the validated merged PrintTicket to see whether the
              ' the validation process has kept the duplexing option we want to set unchanged.
              '
              If result.ValidatedPrintTicket.Duplexing = Duplexing.TwoSidedLongEdge Then
                   '
                   ' Set the printer's user-default PrintTicket and commit the set operation.
                   '
                   queue.UserPrintTicket = result.ValidatedPrintTicket
                   queue.Commit()
                   Console.WriteLine("PrintTicket new duplexing setting is set on '{0}'.", queue.FullName)
              Else
                   '
                   ' The duplexing option we want to set has been changed by the validation process
                   ' when it was resolving setting constraints.
                   '
                   Console.WriteLine("PrintTicket new duplexing setting is constrained on '{0}'.", queue.FullName)
              End If
       Else
           '
           ' If the printer doesn't support the duplexing option we want to set, skip it.
           '
           Console.WriteLine("PrintTicket new duplexing setting is not supported on '{0}'.", queue.FullName)
       End If
   End Sub
So that you can quickly test this example, the remainder of it is presented below. Create a project and a
namespace and then paste both the code snippets in this article into the namespace block.
   /// <summary>
   /// Displays the correct command line syntax to run this sample program.
   /// </summary>
/// </summary>
static private void DisplayUsage()
{
    Console.WriteLine();
    Console.WriteLine("Usage #1: printticket.exe -l \"<printer_name>\"");
    Console.WriteLine("      Run program on the specified local printer");
    Console.WriteLine();
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in printer_name.");
    Console.WriteLine();
    Console.WriteLine("Usage #2: printticket.exe -r \"\\\\<server_name>\\<printer_name>\"");
    Console.WriteLine("      Run program on the specified network printer");
    Console.WriteLine();
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in server_name or
printer_name.");
    Console.WriteLine();
    Console.WriteLine("Usage #3: printticket.exe -a");
    Console.WriteLine("      Run program on all installed printers");
    Console.WriteLine();
}
[STAThread]
static public void Main(string[] args)
{
    try
    {
        if ((args.Length == 1) && (args[0] == "-a"))
        {
            //
            // Change PrintTicket setting for all local and network printer connections.
            //
            LocalPrintServer server = new LocalPrintServer();
            //
            // Enumerate through all the printers.
            //
            foreach (PrintQueue queue in server.GetPrintQueues(queue_types))
            {
                //
                // Change the PrintTicket setting queue by queue.
                //
                ChangePrintTicketSetting(queue);
            }
        }//end if -a
        else
        else
        {
               //
               // Unrecognized command line.
               // Show user the correct command line syntax to run this sample program.
               //
               DisplayUsage();
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        Console.WriteLine(e.StackTrace);
        //
        // Show inner exception information if it's provided.
        //
        if (e.InnerException != null)
        {
            Console.WriteLine("--- Inner Exception ---");
            Console.WriteLine(e.InnerException.Message);
            Console.WriteLine(e.InnerException.StackTrace);
        }
    }
    finally
    {
        Console.WriteLine("Press Return to continue...");
        Console.ReadLine();
    }
}//end Main
''' <summary>
''' Displays the correct command line syntax to run this sample program.
''' </summary>
Private Shared Sub DisplayUsage()
    Console.WriteLine()
    Console.WriteLine("Usage #1: printticket.exe -l ""<printer_name>""")
    Console.WriteLine("      Run program on the specified local printer")
    Console.WriteLine()
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in printer_name.")
    Console.WriteLine()
    Console.WriteLine("Usage #2: printticket.exe -r ""\\<server_name>\<printer_name>""")
    Console.WriteLine("      Run program on the specified network printer")
    Console.WriteLine()
    Console.WriteLine("      Quotation marks may be omitted if there are no spaces in server_name or
printer_name.")
    Console.WriteLine()
    Console.WriteLine("Usage #3: printticket.exe -a")
    Console.WriteLine("      Run program on all installed printers")
    Console.WriteLine()
End Sub
<STAThread>
Public Shared Sub Main(ByVal args() As String)
    Try
        If (args.Length = 1) AndAlso (args(0) = "-a") Then
            '
            ' Change PrintTicket setting for all local and network printer connections.
            '
            Dim server As New LocalPrintServer()
               '
               ' Enumerate through all the printers.
               '
                '
                For Each queue As PrintQueue In server.GetPrintQueues(queue_types)
                    '
                    ' Change the PrintTicket setting queue by queue.
                    '
                    ChangePrintTicketSetting(queue)
                Next queue 'end if -a
         Else
             '
             ' Unrecognized command line.
             ' Show user the correct command line syntax to run this sample program.
             '
             DisplayUsage()
         End If
     Catch e As Exception
         Console.WriteLine(e.Message)
         Console.WriteLine(e.StackTrace)
         '
         ' Show inner exception information if it's provided.
         '
         If e.InnerException IsNot Nothing Then
             Console.WriteLine("--- Inner Exception ---")
             Console.WriteLine(e.InnerException.Message)
             Console.WriteLine(e.InnerException.StackTrace)
         End If
     Finally
         Console.WriteLine("Press Return to continue...")
         Console.ReadLine()
     End Try
 End Sub
See also
 PrintCapabilities
 PrintTicket
 GetPrintQueues
 PrintServer
 EnumeratedPrintQueueTypes
 PrintQueue
 GetPrintCapabilities
 Documents in WPF
 Printing Overview
 Print Schema
      Globalization and Localization
      11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) provides extensive support for the development of world-ready
applications.
In This Section
WPF Globalization and Localization Overview
Globalization for WPF
Use Automatic Layout Overview
Localization Attributes and Comments
Bidirectional Features in WPF Overview
How-to Topics
Reference
System.Globalization
FlowDirection
NeutralResourcesLanguageAttribute
xml:lang Handling in XAML
Related Sections
       WPF Globalization and Localization Overview
       11/21/2022 • 14 minutes to read • Edit Online
When you limit your product's availability to only one language, you limit your potential customer base to a
fraction of our world's 7.5 billion population. If you want your applications to reach a global audience, cost-
effective localization of your product is one of the best and most economical ways to reach more customers.
This overview introduces globalization and localization in WPF provides globalized design features, including
automatic layout, satellite assemblies, and localized attributes and commenting.
Localization is the translation of application resources into localized versions for the specific cultures that the
application supports. When you localize in WPF, you use the APIs in the System.Windows.Markup.Localizer
namespace. These APIs power the LocBaml Tool Sample command-line tool. For information about how to build
and use LocBaml, see Localize an Application.
      If you decide to include your source language in the main assembly by omitting the <UICulture>
      tag in your project file, set the UltimateResourceFallback location as the main assembly instead of
      the satellite (for example,
       [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)] ).
German:
The previous Window property automatically resizes the window according to the size of the content. This
property prevents the window from cutting off content that increases in size after localization; it also removes
unneeded space when content decreases in size after localization.
 <Grid x:Uid="Grid_1">
Uid properties are needed in order for WPF localization APIs to work correctly.
They are used by UI with an older localization of the UI. You add a Uid property by running
 msbuild -t:updateuid RunDialog.csproj in a command shell. This is the recommended method of adding Uid
properties because manually adding them is typically time-consuming and less accurate. You can check that Uid
properties are correctly set by running msbuild -t:checkuid RunDialog.csproj .
The UI is structured by using the Grid control, which is a useful control for taking advantage of the automatic
layout in UI elements that are positioned in each cell can adapt to increases and decreases in size during
localization.
   <Grid.ColumnDefinitions>
     <ColumnDefinition x:Uid="ColumnDefinition_1" />
     <ColumnDefinition x:Uid="ColumnDefinition_2" />
The first two columns where the Open: label and ComboBox are placed use 10 percent of the UI total width.
Note that of the example uses the shared-sizing feature of Grid. The last three columns take advantage of this by
placing themselves in the same SharedSizeGroup. As one would expect from the name of the property, this
allows the columns to share the same size. So when the "Browse…" gets localized to the longer string
"Durchsuchen…", all buttons grow in width instead of having a small "OK" button and a disproportionately large
"Durchsuchen…" button.
xml:lang
 xml:lang="en-US"
Notice the xml:lang Handling in XAML placed at the root element of the UI. This property describes the culture of
a given element and its children. This value is used by several features in WPF and should be changed
appropriately during localization. This value changes what language dictionary is use to hyphenate and spell
check words. It also affects the display of digits and how the font fallback system selects which font to use.
Finally, the property affects the way numbers are displayed and the way texts written in complex scripts are
shaped. The default value is "en-US".
Building a Satellite Resource Assembly
In .csproj:
Edit the   .csproj   file and add the following tag to an unconditional   <PropertyGroup>   :
<UICulture>en-US</UICulture>
Notice the addition of a UICulture value. When this is set to a valid CultureInfo value such as en-US, building
the project will generate a satellite assembly with all localizable resources in it.
<Resource Include="RunIcon.JPG">
<Localizable>False</Localizable>
</Resource>
The RunIcon.JPG does not need to be localized because it should appear the same for all cultures. Localizable
is set to false so that it remains in the language neutral main assembly instead of the satellite assembly. The
default value of all noncompilable resources is Localizable set to true .
Localizing the Run Dialog
Parse
After building the application, the first step in localizing it is parsing the localizable resources out of the satellite
assembly. For the purposes of this topic, use the sample LocBaml tool which can be found at LocBaml Tool
Sample. Note that LocBaml is only a sample tool meant to help you get started in building a localization tool
that fits into your localization process. Using LocBaml, run the following to parse: LocBaml /parse
RunDialog.resources.dll /out: to generate a "RunDialog.resources.dll.CSV" file.
Localize
Use your favorite CSV editor that supports Unicode to edit this file. Filter out all entries with a localization
category of "None". You should see the following entries:
  Button_1:System.Windows.Controls.Bu       Button                                    OK
  tton.$Content
  ComboBox_1:System.Windows.Control         ComboBox
  s.ComboBox.$Content
  Button_1:System.Windows.Controls.Bu    Button                                     OK
  tton.$Content
  ComboBox_1:System.Windows.Control      ComboBox
  s.ComboBox.$Content
Generate
The last step of localization involves creating the newly localized satellite assembly. This can be accomplished
with the following LocBaml command:
LocBaml.exe /generate RunDialog.resources.dll /trans:RunDialog.resources.dll.CSV /out: . /cul:de-
DE
On German Windows, if this resources.dll is placed in a de-DE folder next to the main assembly, this resource
will automatically load instead of the one in the en-US folder. If you do not have a German version of Windows
to test this, set the culture to whatever culture of Windows you are using (for example, en-US ), and replace the
original resources DLL.
Satellite Resource Loading
M Y DIA LO G. EXE EN - US\ M Y DIA LO G. RESO URC ES. DL L DE- DE\ M Y DIA LO G. RESO URC ES. DL L
Culturally neutral resources Other resources in English Other resources localized to German
.NET automatically chooses which satellite resources assembly to load based on the application's
Thread.CurrentUICulture. This defaults to the culture of your Windows OS. If you're using German Windows, the
de-DE\MyDialog.resources.dll file loads. If you're using English Windows, the en-US\MyDialog.resources.dll file
loads. You can set the ultimate fallback resource for your application by specifying the NeutralResourcesLanguage
attribute in your project’s AssemblyInfo file. For example, if you specify:
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
then the en-US\MyDialog.resources.dll file is used with German Windows if neither of the following files are
available: de-DE\MyDialog.resources.dll or de\MyDialog.resources.dll.
Microsoft Saudi Arabia Homepage
The following graphics show an English and Arabic Homepage. For the complete sample that produces these
graphics see Globalization Homepage Sample.
English:
Arabic:
Designing a Global Microsoft home page
This mock up of the Microsoft Saudi Arabia web site illustrates the globalization features provided for
RightToLeft languages. Languages such as Hebrew and Arabic have a right-to-left reading order so the layout of
UI must often be laid out quite differently than it would be in left-to-right languages such as English. Localizing
from a left-to-right language to a right-to-left language or vice versa can be quite challenging. WPF has been
designed to make such localizations much easier.
FlowDirection
Homepage.xaml:
Notice the FlowDirection property on Page. Changing this property to RightToLeft will change the FlowDirection
of the Page and its children elements so that the layout of this UI is flipped to become right-to-left as an Arabic
user would expect. One can override the inheritance behavior by specifying an explicit FlowDirection on any
element. The FlowDirection property is available on any FrameworkElement or document related element and
has an implicit value of LeftToRight.
Observe that even the background gradient brushes are flipped correctly when the root FlowDirection is
changed:
FlowDirection="LeftToRight"
FlowDirection="RightToLeft"
   <TextBlock
     x:Uid="TextBlock_2"
     DockPanel.Dock="Right"
     Foreground="White"
     Margin="5,0,5,0"
     Localization.Comments="$Content(This character is used as a decorative rule.)">
     |
   </TextBlock>
This comment becomes associated with TextBlock_1's content and in the case of the LocBaml Tool, ( see Localize
an Application), it can be seen in the 6th column of the TextBlock_1 row in the output .csv file:
Comments can be placed on the content or property of any element using the following syntax:
   <TextBlock
     x:Uid="TextBlock_1"
     DockPanel.Dock="Right"
     Foreground="White"
     Margin="5,0,5,0"
     Localization.Comments="$Content(This is a comment on the TextBlock's content.)
        Margin(This is a comment on the TextBlock's Margin property.)">
     |
    </TextBlock>
Localization Attributes
Often the developer or localization manager needs control of what localizers can read and modify. For example,
you might not want the localizer to translate the name of your company or legal wording. WPF provides
attributes that enable you to set the readability, modifiability, and category of an element's content or property
which your localization tool can use to lock, hide, or sort elements. For more information, see Attributes. For the
purposes of this sample, the LocBaml Tool just outputs the values of these attributes. WPF controls all have
default values for these attributes, but you the can override them. For example, the following example overrides
the default localization attributes for TextBlock_1 and sets the content to be readable but unmodifiable for
localizers.
   <TextBlock
   x:Uid="TextBlock_1"
   Localization.Attributes=
   "$Content(Readable Unmodifiable)">
     Microsoft Corporation
   </TextBlock>
In addition to the readability and modifiability attributes, WPF provides an enumeration of common UI
categories (LocalizationCategory) that can be used to give localizers more context. The WPF default categories
for platform controls can be overridden in XAML as well:
   <TextBlock x:Uid="TextBlock_2">
   <TextBlock.ToolTip>
   <TextBlock
   x:Uid="TextBlock_3"
   Localization.Attributes=
   "$Content(ToolTip Readable Unmodifiable)">
   Microsoft Corporation
   </TextBlock>
   </TextBlock.ToolTip>
   Windows Vista
   </TextBlock>
The default localization attributes that WPF provides can also be overridden through code, so you can correctly
set the right default values for custom controls. For example:
The per instance attributes set in XAML will take precedence over the values set in code on custom controls. For
more information on attributes and comments, see Localization Attributes and Comments.
Font Fallback and Composite Fonts
If you specify a font that does not support a given codepoint range, WPF will automatically fallback to one that
does by using the Global User Interface.compositefont that is located in your Windows\Fonts directory.
Composite fonts work just as any other font and can be used explicitly by setting an element's FontFamily (for
instance, FontFamily="Global User Interface" ). You can specify your own font fallback preference by creating
your own composite font and specifying what font to use for specific codepoint ranges and languages.
For more information on composite fonts see FontFamily.
Localizing the Microsoft Homepage
You can follow the same steps as the Run Dialog example to localize this application. The localized .csv file for
Arabic is available for you in the Globalization Homepage Sample.
       Globalization for WPF
       11/21/2022 • 6 minutes to read • Edit Online
This topic introduces issues that you should be aware of when writing Windows Presentation Foundation (WPF)
applications for the global market. The globalization programming elements are defined in .NET in the
System.Globalization namespace.
XAML Globalization
Extensible Application Markup Language (XAML) is based on XML and takes advantage of the globalization
support defined in the XML specification. The following sections describe some XAML features that you should
be aware of.
Character References
A character reference gives the UTF16 code unit of the particular Unicode character it represents, in either
decimal or hexadecimal. The following example shows a decimal character reference for the COPTIC CAPITAL
LETTER HORI, or 'Ϩ':
Ϩ
The following example shows a hexadecimal character reference. Notice that it has an x in front of the
hexadecimal number.
Ϩ
Encoding
The encoding supported by XAML are ASCII, Unicode UTF-16, and UTF-8. The encoding statement is at the
beginning of XAML document. If no encoding attribute exists and there is no byte-order, the parser defaults to
UTF-8. UTF-8 and UTF-16 are the preferred encodings. UTF-7 is not supported. The following example
demonstrates how to specify a UTF-8 encoding in a XAML file.
?xml encoding="UTF-8"?
Language Attribute
XAML uses xml:lang to represent the language attribute of an element. To take advantage of the CultureInfo
class, the language attribute value needs to be one of the culture names predefined by CultureInfo. xml:lang is
inheritable in the element tree (by XML rules, not necessarily because of dependency property inheritance) and
its default value is an empty string if it is not assigned explicitly.
The language attribute is very useful for specifying dialects. For example, French has different spelling,
vocabulary, and pronunciation in France, Quebec, Belgium, and Switzerland. Also Chinese, Japanese, and Korean
share code points in Unicode, but the ideographic shapes are different and they use totally different fonts.
The following Extensible Application Markup Language (XAML) example uses the      fr-CA   language attribute to
specify Canadian French.
   <TextBlock xml:lang="fr-CA">Découvrir la France</TextBlock>
Unicode
WPF application can use StringInfo to manipulate strings without understanding whether they have surrogate
pairs or combining characters.
International Text
WPF includes built-in processing for all Microsoft .NET Framework supported writing systems.
The following scripts are currently supported:
   Arabic
   Bengali
   Devanagari
   Cyrillic
   Greek
   Gujarati
   Gurmukhi
   Hebrew
   Ideographic scripts
   Kannada
   Lao
   Latin
   Malayalam
   Mongolian
   Odia
   Syriac
   Tamil
   Telugu
   Thaana
   Thai*
   Tibetan
*In this release the display and editing of Thai text is supported; word breaking is not.
The following scripts are not currently supported:
   Khmer
   Korean Old Hangul
   Myanmar
   Sinhala
All the writing system engines support OpenType fonts. OpenType fonts can include the OpenType layout tables
that enable font creators to design better international and high-end typographic fonts. The OpenType font
layout tables contain information about glyph substitutions, glyph positioning, justification, and baseline
positioning, enabling text-processing applications to improve text layout.
OpenType fonts allow the handling of large glyph sets using Unicode encoding. Such encoding enables broad
international support as well as for typographic glyph variants.
WPF text rendering is powered by Microsoft ClearType sub-pixel technology that supports resolution
independence. This significantly improves legibility and provides the ability to support high quality magazine
style documents for all scripts.
International Layout
WPF provides a very convenient way to support horizontal, bidirectional, and vertical layouts. In presentation
framework the FlowDirection property can be used to define layout. The flow direction patterns are:
   LeftToRight - horizontal layout for Latin, East Asian and so forth.
   RightToLeft - bidirectional for Arabic, Hebrew and so forth.
  NOTE
  WPF applications support all the FrameworkCLR resources including string tables, images, and so forth.
Building Localizable Applications
Localization means to adapt a UI to different cultures. To make a WPF application localizable, developers need to
build all the localizable resources into a resource assembly. The resource assembly is localized into different
languages, and the code-behind uses resource management API to load. One of the files required for a WPF
application is a project file (.proj). All resources that you use in your application should be included in the project
file. The following example from a .csproj file shows how to do this.
   <Resource Include="data\picture1.jpg"/>
   <EmbeddedResource Include="data\stringtable.en-US.restext"/>
To use a resource in your application instantiate a ResourceManager and load the resource you want to use. The
following example demonstrates how to do this.
   [assembly: NeutralResourcesLanguageAttribute(
       "de" , UltimateResourceFallbackLocation.Satellite)]
See also
   WPF Globalization and Localization Overview
       Use Automatic Layout Overview
       11/21/2022 • 4 minutes to read • Edit Online
This topic introduces guidelines for developers on how to write WPF application design.
   <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       x:Class="ButtonLoc.Pane1"
       Name="myWindow"
       SizeToContent="WidthAndHeight"
       >
   <DockPanel>
       <Button FontSize="28" Height="50">My name is Hope.</Button>
   </DockPanel>
   </Window>
In the example, all you have to do to make a Spanish button is change the text. For example,
   <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       x:Class="ButtonLoc.Pane1"
       Name="myWindow"
       SizeToContent="WidthAndHeight"
       >
    <DockPanel>
       <Button FontSize="28" Height="50">Me llamo Esperanza.</Button>
     </DockPanel>
   </Window>
      <StackPanel
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          x:Class="GridLoc.Pane1"
      >
Add a FlowDirection
   Add a FlowDirection to the root element of your application.
   WPF provides a convenient way to support horizontal, bidirectional, and vertical layouts. In presentation
   framework, the FlowDirection property can be used to define layout. The flow-direction patterns are:
      FlowDirection.LeftToRight (LrTb) — horizontal layout for Latin, East Asian, and so forth.
      FlowDirection.RightToLeft (RlTb) — bidirectional for Arabic, Hebrew, and so forth.
Use composite fonts instead of physical fonts
   With composite fonts, the FontFamily property does not need to be localized.
   Developers can use one of the following fonts or create their own.
      Global User Interface
      Global San Serif
      Global Serif
Add xml:lang
   Add the xml:lang attribute in the root element of your UI, such as   xml:lang="en-US"   for an English
   application.
   Because composite fonts use    xml:lang   to determine what font to use, set this property to support
   multilingual scenarios.
The following graphic shows the grid produced by the previous code.
Grid
     <Grid ShowGridLines="True">
       <Grid.ColumnDefinitions>
         <ColumnDefinition SharedSizeGroup="FirstColumn"/>
         <ColumnDefinition SharedSizeGroup="SecondColumn"/>
       </Grid.ColumnDefinitions>
       <Grid.RowDefinitions>
         <RowDefinition Height="Auto" SharedSizeGroup="FirstRow"/>
       </Grid.RowDefinitions>
</StackPanel>
 NOTE
 For the complete code sample, see Share Sizing Properties Between Grids.
See also
  Globalization for WPF
  Use Automatic Layout to Create a Button
  Use a Grid for Automatic Layout
       Localization Attributes and Comments
       11/21/2022 • 3 minutes to read • Edit Online
WPF Localization API to indicate which resources are to be localized. Free-form comments are any information
that the application author wants to include.
FontSize = "12"
Microsoft
</TextBlock>
In the previous sample the Localization.Attributes section contains the localization attributes and the
Localization.Comments section the free-form comments. The following tables show the attributes and
comments and their meaning to the localizer.
LO C A L IZ AT IO N AT T RIB UT ES M EA N IN G
  $Content (Unmodifiable Readable Text)                        Contents of the TextBlock element cannot be modified.
                                                               Localizers cannot change the word "Microsoft". The content
                                                               is visible (Readable) to the localizer. The category of the
                                                               content is text.
  FontFamily (Unmodifiable Readable)                           The font family property of the TextBlock element cannot be
                                                               changed but it is visible to the localizer.
LO C A L IZ AT IO N F REE- F O RM C O M M EN T S M EA N IN G
  $Content (Trademark)                                         The application author tells the localizer that the content in
                                                               the TextBlock element is a trademark.
  FontSize (Trademark font size)                               The application author indicates that the font size property
                                                               should follow the standard trademark size.
Localizability Attributes
The information in Localization.Attributes contains a list of pairs: the targeted value name and the associated
localizability values. The target name can be a property name or the special $Content name. If it is a property
name, the targeted value is the value of the property. If it is $Content, the target value is the content of the
element.
There are three types of attributes:
   Categor y . This specifies whether a value should be modifiable from a localizer tool. See Category.
   Readability . This specifies whether a localizer tool should read (and display) a value. See Readability.
   Modifiability . This specifies whether a localizer tool allows a value to be modified. See Modifiability.
These attributes can be specified in any order delimited by a space. In case duplicate attributes are specified, the
last attribute will override former ones. For example, Localization.Attributes = "Unmodifiable Modifiable" sets
Modifiability to Modifiable because it is the last value.
Modifiability and Readability are self-explanatory. The Category attribute provides predefined categories that
help the localizer when translating text. Categories, such as, Text, Label, and Title give the localizer information
about how to translate the text. There are also special categories: None, Inherit, Ignore, and NeverLocalize.
The following table shows the meaning of the special categories.
C AT EGO RY M EA N IN G
Localization Comments
Localization.Comments contains free-form strings concerning the targeted value. Application developers can
add information to give localizers hints about how the applications text should be translated. The format of the
comments can be any string surrounded by "()". Use '\' to escape characters.
See also
   Globalization for WPF
   Use Automatic Layout to Create a Button
   Use a Grid for Automatic Layout
   Localize an Application
       Bidirectional Features in WPF Overview
       11/21/2022 • 14 minutes to read • Edit Online
Unlike any other development platform, WPF has many features that support rapid development of
bidirectional content, for example, mixed left to right and right to left data in the same document. At the same
time, WPF creates an excellent experience for users who require bidirectional features such as Arabic and
Hebrew speaking users.
The following sections explain many bidirectional features together with examples illustrating how to achieve
the best display of bidirectional content. Most of the samples use XAML, though you can easily apply the
concepts to C# or Microsoft Visual Basic code.
FlowDirection
The basic property that defines the content flow direction in a WPF application is FlowDirection. This property
can be set to one of two enumeration values, LeftToRight or RightToLeft. The property is available to all WPF
elements that inherit from FrameworkElement.
The following examples set the flow direction of a TextBox element.
Left-to-right flow direction
An element within a user interface (UI) tree will inherit the FlowDirection from its container. In the following
example, the TextBlock is inside a Grid, which resides in a Window. Setting the FlowDirection for the Window
implies setting it for the Grid and TextBlock as well.
The following example demonstrates setting FlowDirection.
   <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       x:Class="FlowDirectionApp.Window1"
       Title="BidiFeatures" Height="200" Width="700"
       FlowDirection="RightToLeft">
       <Grid>
         <Grid.ColumnDefinitions>
           <ColumnDefinition/>
           <ColumnDefinition/>
         </Grid.ColumnDefinitions>
         <TextBlock Grid.Column="0" >
              This is a right-to-left TextBlock
         </TextBlock>
The top level Window has a RightToLeftFlowDirection, so all elements contained within it also inherit the same
FlowDirection. For an element to override a specified FlowDirection it must add an explicit direction change such
as the second TextBlock in the previous example which changes to LeftToRight. When no FlowDirection is
defined, the default LeftToRight applies.
The following graphic shows the output of the previous example:
FlowDocument
Many development platforms such as HTML, Win32 and Java provide special support for bidirectional content
development. Markup languages such as HTML give content writers the necessary markup to display text in any
required direction, for example the HTML 4.0 tag, "dir" that takes "rtl" or "ltr" as values. This tag is similar to the
FlowDirection property, but the FlowDirection property works in a more advanced way to layout textual content
and can be used for content other than text.
In UI element that can host a combination of text, tables, images and other elements. The samples in the
following sections use this element.
Adding text to a FlowDocument can be done in more that one way. A simple way to do so is through a
Paragraph which is a block-level element used to group content such as text. To add text to inline-level elements
the samples use Span and Run. Span is an inline-level flow content element used for grouping other inline
elements, while a Run is an inline-level flow content element intended to contain a run of unformatted text. A
Span can contain multiple Run elements.
The first document example contains a document that has a number of network share names; for example
 \\server1\folder\file.ext . Whether you have this network link in an Arabic or English document, you always
want it to appear in the same way. The following graphic illustrates using the Span element and shows the link
in an Arabic RightToLeft document:
Because the text is RightToLeft, all special characters, such as the "\", separate the text in a right to left order. That
results in the link not being shown in the correct order, therefore to solve the problem, the text must be
embedded to preserve a separate Run flowing LeftToRight. Instead of having a separate Run for each language,
a better way to solve the problem is to embed the less frequently used English text into a larger Arabic Span.
The following graphic illustrates this by using the Run element embedded in a Span element:
The following example demonstrates using Run and Span elements in documents.
   <Page
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       FlowDirection="RightToLeft">
     <FlowDocument>
       <Paragraph>
         <Span FlowDirection="RightToLeft" >
           ﺳﺘﺠﺪ اﻟﻤﻠﻒ ھﻨﺎ:
           <Run FlowDirection="LeftToRight">
              \\server1\filename\filename1.txt</Run>
           !ﺛﻢ ﺑﺎﻗﻰ اﻟﻨﺺ
         </Span>
       </Paragraph>
     </FlowDocument>
   </Page>
Span Elements
The Span element works as a boundary separator between texts with different flow directions. Even Span
elements with the same flow direction are considered to have different bidirectional scopes which means that
the Span elements are ordered in the container’s FlowDirection, only the content within the Span element
follows the FlowDirection of the Span.
The following graphic shows the flow direction of several TextBlock elements.
The following example shows how to use the Span and Run elements to produce the results shown in the
previous graphic.
   <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
     <StackPanel >
<Separator/>
</StackPanel>
</Page>
In the TextBlock elements in the sample, the Span elements are laid out according to the FlowDirection of their
parents, but the text within each Span element flows according to its own FlowDirection. This is applicable to
Latin and Arabic – or any other language.
Adding xml:lang
The following graphic shows another example that uses numbers and arithmetic expressions, such as
 "200.0+21.4=221.4" . Notice that only the FlowDirection is set.
Users of this application will be disappointed by the output, even though the FlowDirection is correct the
numbers are not shaped as Arabic numbers should be shaped.
XAML elements can include an XML attribute ( xml:lang ) that defines the language of each element. XAML also
supports a XML language principle whereby xml:lang values applied to parent elements in the tree are used by
child elements. In the previous example, because a language was not defined for the Run element or any of its
top level elements, the default xml:lang was used, which is en-US for XAML. The internal number shaping
algorithm of Windows Presentation Foundation (WPF) selects numbers in the corresponding language – in this
case English. To make the Arabic numbers render correctly xml:lang needs to be set.
The following graphic shows the example with     xml:lang     added.
   <Page
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       FlowDirection="RightToLeft">
         <FlowDocument>
            <Paragraph>
               <Span FlowDirection="RightToLeft" Language="ar-SA">
                 221.4=21.4+200.0" :"اﻟﻌﻤﻠﯿﺔ اﻟﺤﺴﺎﺑﯿﺔ
               </Span>
            </Paragraph>
         </FlowDocument>
   </Page>
Be aware that many languages have different xml:lang values depending on the targeted region, for example,
 "ar-SA" and "ar-EG" represent two variations of Arabic. The previous examples illustrate that you need to
define both the xml:lang and FlowDirection values.
The following example draws a RightToLeftToolBar. (To draw it left to right, remove the FlowDirection attribute
on the ToolBar.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
FlowDirection Exceptions
There are a few cases where FlowDirection does not behave as expected. This section covers two of these
exceptions.
Image
An Image represents a control that displays an image. In XAML it can be used with a Source property that
defines the uniform resource identifier (URI) of the Image to display.
Unlike other UI elements, an Image does not inherit the FlowDirection from the container. However, if the
FlowDirection is set explicitly to RightToLeft, an Image is displayed flipped horizontally. This is implemented as a
convenient feature for developers of bidirectional content; because in some cases, horizontally flipping the
image produces the desired effect.
The following graphic shows a flipped Image.
The following example demonstrates that the Image fails to inherit the FlowDirection from the StackPanel that
contains it.
  NOTE
  You must have a file named ms_logo.jpg on your C:\ drive to run this example.
   <StackPanel
     xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
     FlowDirection="RightToLeft">
     <Image Source="file://c:/ms_logo.jpg"
            Width="147" Height="50"/>
     <Separator Height="10"/>
     <Image Source="file://c:/ms_logo.jpg"
            Width="147" Height="50" FlowDirection="LeftToRight" />
     <Separator Height="10"/>
     <Image Source="file://c:/ms_logo.jpg"
            Width="147" Height="50" FlowDirection="RightToLeft"/>
   </StackPanel>
  NOTE
  Included in the download files is an ms_logo.jpg file. The code assumes that the .jpg file is not inside your project but
  somewhere on the C:\ drive. You must copy the .jpg from the project files to your C:\ drive or change the code to look for
  the file inside the project. To do this change Source="file://c:/ms_logo.jpg" to Source="ms_logo.jpg" .
Paths
In addition to an Image, another interesting element is Path. A Path is an object that can draw a series of
connected lines and curves. It behaves in a manner similar to an Image regarding its FlowDirection; for example
its RightToLeftFlowDirection is a horizontal mirror of its LeftToRight one. However, unlike an Image, Path inherits
its FlowDirection from the container and one does not need to specify it explicitly.
The following example draws a simple arrow using 3 lines. The first arrow inherits the RightToLeft flow direction
from the StackPanel so that its start and end points are measured from a root on the right side. The second
arrow which has an explicit RightToLeftFlowDirection also starts on the right side. However, the third arrow has
its starting root on the left side. For more information on drawing see LineGeometry and GeometryGroup.
   <StackPanel
     xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
     FlowDirection="RightToLeft">
The following graphic shows the output of the previous example with arrows drawn using the Path element:
The Image and Path are two examples of a how UI elements in a specific direction within a container,
FlowDirection can be used with elements such as InkPresenter which renders ink on a surface,
LinearGradientBrush, RadialGradientBrush. Whenever you need a right to left behavior for your content that
mimics a left to right behavior, or vice versa, Windows Presentation Foundation (WPF) provides that capability.
Number Substitution
Historically, Windows has supported number substitution by allowing the representation of different cultural
shapes for the same digits while keeping the internal storage of these digits unified among different locales, for
example numbers are stored in their well known hexadecimal values, 0x40, 0x41, but displayed according to the
selected language.
This has allowed applications to process numerical values without the need to convert them from one language
to another, for example a user can open an Microsoft Excel spreadsheet in a localized Arabic Windows and see
the numbers shaped in Arabic, but open it in a European version of Windows and see European representation
of the same numbers. This is also necessary for other symbols such as comma separators and percentage
symbol because they usually accompany numbers in the same document.
Windows Presentation Foundation (WPF) continues the same tradition, and adds further support for this feature
that allows more user control over when and how substitution is used. While this feature is designed for any
language, it is particularly useful in bidirectional content where shaping digits for a specific language is usually a
challenge for application developers because of the various cultures an application might run on.
The core property controlling how number substitution works in Windows Presentation Foundation (WPF) is the
Substitution dependency property. The NumberSubstitution class specifies how numbers in text are to be
displayed. It has three public properties that define its behavior. The following is a summary of each of the
properties:
CultureSource:
This property specifies how the culture for numbers is determined. It takes one of three NumberCultureSource
enumeration values.
   Override: Number culture is that of CultureOverride property.
   Text: Number culture is the culture of the text run. In markup, this would be xml:lang , or its alias
    Language property (Language or Language). Also, it is the default for classes deriving from
   FrameworkContentElement. Such classes include System.Windows.Documents.Paragraph,
   System.Windows.Documents.Table, System.Windows.Documents.TableCell and so forth.
   User: Number culture is the culture of the current thread. This property is the default for all subclasses of
   FrameworkElement such as Page, Window and TextBlock.
CultureOverride :
The CultureOverride property is used only if the CultureSource property is set to Override and is ignored
otherwise. It specifies the number culture. A value of null , the default value, is interpreted as en-US.
Substitution :
This property specifies the type of number substitution to perform. It takes one of the following
NumberSubstitutionMethod enumeration values:
   AsCulture: The substitution method is determined based on the number culture's
   NumberFormatInfo.DigitSubstitution property. This is the default.
   Context: If the number culture is an Arabic or Persian culture, it specifies that the digits depend on the
   context.
   European: Numbers are always rendered as European digits.
   NativeNational: Numbers are rendered using the national digits for the number culture, as specified by
   the culture's NumberFormat.
   Traditional: Numbers are rendered using the traditional digits for the number culture. For most cultures,
   this is the same as NativeNational. However, NativeNational results in Latin digits for some Arabic
   cultures, whereas this value results in Arabic digits for all Arabic cultures.
What do those values mean for a bidirectional content developer? In most cases, the developer might need only
to define FlowDirection and the language of each textual UI element, for example Language="ar-SA" and the
NumberSubstitution logic takes care of displaying the numbers according to the correct UI. The following
example demonstrates using Arabic and English numbers in a Windows Presentation Foundation (WPF)
application running in an Arabic version of Windows.
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
     <StackPanel>
      <TextBlock Background="LightGreen" FontSize="32"
         Language="ar-SA" FlowDirection="RightToLeft">1+2=3</TextBlock>
      <TextBox Background="LightGreen" FontSize="32"
         Language="ar-SA" FlowDirection="RightToLeft">1+2=3</TextBox>
      <TextBlock Background="LightBlue" FontSize="32">1+2=3</TextBlock>
      <TextBox Background="LightBlue" FontSize="32">1+2=3</TextBox>
    </StackPanel>
   </Page>
The following graphic shows the output of the previous sample if you're running in an Arabic version of
Windows with Arabic and English numbers displayed:
The FlowDirection was important in this case because setting the FlowDirection to LeftToRight instead would
have yielded European digits. The following sections discuss how to have a unified display of digits throughout
your document. If this example is not running on Arabic Windows, all the digits display as European digits.
Defining Substitution Rules
In a real application you might need to set the Language programmatically. For example, you want to set the
 xml:lang attribute to be the same as the one used by the system’s UI, or maybe change the language
depending on the application state.
If you want to make changes based on the application's state, make use of other features provided by Windows
Presentation Foundation (WPF).
First, set the application component’s   NumberSubstitution.CultureSource="Text"   . Using this setting makes sure
that the settings do not come from the UI for text elements that have "User" as the default, such as TextBlock.
For example:
   <TextBlock
      Name="text1" NumberSubstitution.CultureSource="Text">
      1234+5679=6913
   </TextBlock>
In the corresponding C# code, set the Language property, for example, to "ar-SA" .
text1.Language = System.Windows.Markup.XmlLanguage.GetLanguage("ar-SA");
If you need to set the Language property to the current user’s UI language use the following code.
   text1.Language =
   System.Windows.Markup.XmlLanguage.GetLanguage(System.Globalization.CultureInfo.CurrentUICulture.IetfLanguage
   Tag);
CultureInfo.CurrentCulture represents the current culture used by the current thread at run time.
Your final XAML example should be similar to the following example.
   <Page x:Class="WindowsApplication.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="Code Sample" Height="300" Width="300"
   >
       <StackPanel>
         <TextBlock Language="ar-SA"
            FlowDirection="RightToLeft">3=2+1 :ﻋﺮﺑﻰ
         </TextBlock>
         <TextBlock Language="ar-SA"
            FlowDirection="RightToLeft"
            NumberSubstitution.Substitution="European">3=2+1 :ﻋﺮﺑﻰ
         </TextBlock>
       </StackPanel>
   </Page>
           public Window1()
           {
               InitializeComponent();
               string currentLanguage =
                   System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag;
text1.Language = System.Windows.Markup.XmlLanguage.GetLanguage(currentLanguage);
               if (currentLanguage.ToLower().StartsWith("ar"))
               {
                    text1.FlowDirection = FlowDirection.RightToLeft;
               }
               else
               {
                    text1.FlowDirection = FlowDirection.LeftToRight;
               }
           }
       }
   }
The following graphic shows what the window looks like for either programming language, displaying Arabic
numbers:
   <Page x:Class="WindowsApplication.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="Code Sample" Height="300" Width="300"
   >
       <StackPanel>
         <TextBlock Language="ar-SA"
            FlowDirection="RightToLeft">3=2+1 :ﻋﺮﺑﻰ
         </TextBlock>
         <TextBlock Language="ar-SA"
            FlowDirection="RightToLeft"
            NumberSubstitution.Substitution="European">3=2+1 :ﻋﺮﺑﻰ
         </TextBlock>
       </StackPanel>
   </Page>
       How to: Localize an application
       11/21/2022 • 6 minutes to read • Edit Online
This tutorial explains how to create a localized application by using the LocBaml tool.
  NOTE
  The LocBaml tool is not a production-ready application. It is presented as a sample that uses some of the localization APIs
  and illustrates how you might write a localization tool.
Overview
This article gives you a step-by-step approach to localizing an application. First, you prepare your application so
that the text that will be translated can be extracted. After the text is translated, you merge the translated text
into a new copy of the original application.
3. Add Uids to your XAML files. Uids are used to keep track of changes to files and to identify items that
   must be translated. To add Uids to your files, run updateuid on your project file:
    msbuild -t:updateuid helloapp.csproj
   After running updateuid , your files should contain Uids. For example, in the Pane1.xaml file of HelloApp,
   you should find the following:
      <StackPanel x:Uid="StackPanel_1">
        <TextBlock x:Uid="TextBlock_1">Hello World</TextBlock>
        <TextBlock x:Uid="TextBlock_2">Goodbye World</TextBlock>
      </StackPanel>
2. The newly created main application assembly, HelloApp.exe, is created in the following folder:
   C:\HelloApp\Bin\Debug
3. The newly created neutral-language resources satellite assembly, HelloApp.resources.dll, is created in the
   following folder: C:\HelloApp\Bin\Debug\en-US
3. Go to the Bin\Release directory to find the newly created executable file (locbaml.exe). Example:
   C:\LocBaml\Bin\Release\locbaml.exe
4. The options that you can specify when you run LocBaml are as follows.
O P T IO N DESC RIP T IO N
      asmpath          or    -asmpath     {filedirectory]          If your XAML code contains custom controls, you must
                                                                   supply the asmpath to the custom control assembly.
     NOTE
     If you need a list of the options when you are running the tool, enter   LocBaml.exe    and then press Enter .
     NOTE
     If the input file, HelloApp.resources.dll, is not in the same directory as LocBaml.exe move one of the files so that
     both files are in the same directory.
3. When you run LocBaml to parse files, the output consists of seven fields delimited by commas (.csv files)
   or tabs (.txt files). The following shows the parsed .csv file for the HelloApp.resources.dll:
PA RSED . C SV F IL E
     HelloApp.g.en-US.resources:window1.baml,Stack1:System.Windows.Controls.StackPanel.$Content,Ignore,FALSE,
     FALSE,,#Text1;#Text2;
     HelloApp.g.en-US.resources:window1.baml,Text1:System.Windows.Controls.TextBlock.$Content,None,TRUE, TRUE,,Hello
     World
     HelloApp.g.en-US.resources:window1.baml,Text2:System.Windows.Controls.TextBlock.$Content,None,TRUE,
     TRUE,,Goodbye World
   Notice that all the values for the Comments field contain no values; if a field doesn't have a value, it is
   empty. Also notice that the item in the first row is neither readable nor modifiable, and has "Ignore" as its
   Categor y value, all of which indicates that the value is not localizable.
4. To facilitate discovery of localizable items in parsed files, particularly in large files, you can sort or filter
   the items by Categor y , Readability , and Modifiability . For example, you can filter out unreadable and
   unmodifiable values.
     NOTE
     If the input file, Hello.csv, is not in the same directory as the executable, LocBaml.exe, move one of the files so that
     both files are in the same directory.
5. In the same assembly as the main application assembly, create a new culture-specific folder to house the
   new satellite assembly. For French-Canadian, the folder would be fr-CA.
6. Copy the generated satellite assembly to the new folder.
7. To test the new satellite assembly, you need to change the culture under which your application will run.
   You can do this in one of two ways:
      Change your operating system's regional settings.
      In your application, add the following code to App.xaml.cs:
         <Application
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="SDKSample.App"
             x:Uid="Application_1"
             StartupUri="Window1.xaml">
         </Application>
         using System.Windows;
         using System.Globalization;
         using System.Threading;
         namespace SDKSample
         {
             public partial class App : Application
             {
                 public App()
                 {
                     // Change culture under which this application runs
                     CultureInfo ci = new CultureInfo("fr-CA");
                     Thread.CurrentThread.CurrentCulture = ci;
                     Thread.CurrentThread.CurrentUICulture = ci;
                 }
             }
         }
         Imports System.Windows
         Imports System.Globalization
         Imports System.Threading
         Namespace SDKSample
             Partial Public Class App
                 Inherits Application
                 Public Sub New()
                     ' Change culture under which this application runs
                     Dim ci As New CultureInfo("fr-CA")
                     Thread.CurrentThread.CurrentCulture = ci
                     Thread.CurrentThread.CurrentUICulture = ci
                 End Sub
             End Class
         End Namespace
This example describes how to use the automatic layout approach to create a button in a localizable application.
Localization of a UI was adapted for required adjustment. Now with the capabilities of Windows Presentation
Foundation (WPF) you can design elements that reduce the need for adjustment. The approach to writing
applications that can be more easily resized and repositioned is called automatic layout .
Example
The following two Extensible Application Markup Language (XAML) examples create applications that instantiate
a button; one with English text and one with Spanish text. Notice that the code is the same except for the text; the
button adjusts to fit the text.
   <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       x:Class="ButtonLoc.Pane1"
       Name="myWindow"
       SizeToContent="WidthAndHeight"
       >
   <DockPanel>
       <Button FontSize="28" Height="50">My name is Hope.</Button>
   </DockPanel>
   </Window>
   <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       x:Class="ButtonLoc.Pane1"
       Name="myWindow"
       SizeToContent="WidthAndHeight"
       >
    <DockPanel>
       <Button FontSize="28" Height="50">Me llamo Esperanza.</Button>
     </DockPanel>
   </Window>
The following graphic shows the output of the code samples with auto-resizable buttons:
See also
   Use Automatic Layout Overview
Use a Grid for Automatic Layout
       How to: Use a Grid for Automatic Layout
       11/21/2022 • 2 minutes to read • Edit Online
This example describes how to use a grid in the automatic layout approach to creating a localizable application.
Localization of a UI was adapted for required adjustment. Now with the capabilities of Windows Presentation
Foundation (WPF) you can design elements that reduce the need for adjustment. The approach to writing
applications that can be more easily re-sized and repositioned is called auto layout .
The following Extensible Application Markup Language (XAML) example demonstrates using a grid to position
some buttons and text. Notice that the height and width of the cells are set to Auto ; therefore the cell that
contains the button with an image adjusts to fit the image. Because the Grid element can adjust to its content it
can be useful when taking the automatic layout approach to designing applications that can be localized.
Example
The following example shows how to use a grid.
Grid
See also
   Use Automatic Layout Overview
   Use Automatic Layout to Create a Button
       How to: Use a ResourceDictionary to Manage
       Localizable String Resources
      11/21/2022 • 2 minutes to read • Edit Online
This example shows how to use a ResourceDictionary to package localizable string resources for Windows
Presentation Foundation (WPF) applications.
To use a ResourceDictionary to manage localizable string resources
1. Create a ResourceDictionary that contains the strings you would like to localize. The following code
   shows an example.
      <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:system="clr-namespace:System;assembly=mscorlib">
</ResourceDictionary>
   This code defines a string resource,   localizedMessage   , of type String, from the System namespace in
   mscorlib.dll.
2. Add the ResourceDictionary to your application, using the following code.
      <Application.Resources>
        <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="StringResources.xaml" />
          </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
      </Application.Resources>
3. Use the string resource from markup, using Extensible Application Markup Language (XAML) like the
   following.
      <!-- Declarative use of string resource from StringResources.xaml resource dictionary -->
      <TextBox DockPanel.Dock="Top" Text="{StaticResource localizedMessage}" />
4. Use the string resource from code-behind, using code like the following.
Localization means to adapt a user interface to different cultures. To do this, text such as titles, captions, and list
box items must be translated. To make translation easier, the items to be translated are collected into resource
files. See Localize an app for information on how to create a resource file for localization. To make a WPF
application localizable, developers need to build all the localizable resources into a resource assembly. The
resource assembly is localized into different languages, and the code-behind uses resource management API to
load.
Example
One of the files required for a WPF application is a project file (.proj). All resources that you use in your
application should be included in the project file. The following XAML example shows this.
   <Resource Include="data\picture1.jpg"/>
   <EmbeddedResource Include="data\stringtable.en-US.restext"/>
To use a resource in your application, instantiate ResourceManager and load the resource you want to use. The
following C# code demonstrates how to do this.
See also
   Localize an app
       Layout
       11/21/2022 • 9 minutes to read • Edit Online
This topic describes the Windows Presentation Foundation (WPF) layout system. Understanding how and when
layout calculations occur is essential for creating user interfaces in WPF.
This topic contains the following sections:
   Element Bounding Boxes
   The Layout System
   Measuring and Arranging Children
   Panel Elements and Custom Layout Behaviors
   Layout Performance Considerations
   Sub-pixel Rendering and Layout Rounding
   What's Next
A single TextBlock element is hosted within a Grid. While the text fills only the upper-left corner of the first
column, the allocated space for the TextBlock is actually much larger. The bounding box of any
FrameworkElement can be retrieved by using the GetLayoutSlot method. The following illustration shows the
bounding box for the TextBlock element.
As shown by the yellow rectangle, the allocated space for the TextBlock element is actually much larger than it
appears. As additional elements are added to the Grid, this allocation could shrink or expand, depending on the
type and size of elements that are added.
The layout slot of the TextBlock is translated into a Path by using the GetLayoutSlot method. This technique can
be useful for displaying the bounding box of an element.
  NOTE
  There is a difference between the properties of Height and Width and ActualHeight and ActualWidth. For example, the
  ActualHeight property is a calculated value based on other height inputs and the layout system. The value is set by the
  layout system itself, based on an actual rendering pass, and may therefore lag slightly behind the set value of properties,
  such as Height, that are the basis of the input change.
  Because ActualHeight is a calculated value, you should be aware that there could be multiple or incremental reported
  changes to it as a result of various operations by the layout system. The layout system may be calculating required
  measure space for child elements, constraints by the parent element, and so on.
The ultimate goal of the measure pass is for the child to determine its DesiredSize, which occurs during the
MeasureCore call. The DesiredSize value is stored by Measure for use during the content arrange pass.
The arrange pass begins with a call to the Arrange method. During the arrange pass, the parent Panel element
generates a rectangle that represents the bounds of the child. This value is passed to the ArrangeCore method
for processing.
The ArrangeCore method evaluates the DesiredSize of the child and evaluates any additional margins that may
affect the rendered size of the element. ArrangeCore generates an arrangeSize , which is passed to the
ArrangeOverride method of the Panel as a parameter. ArrangeOverride generates the finalSize of the child.
Finally, the ArrangeCore method does a final evaluation of offset properties, such as margin and alignment, and
puts the child within its layout slot. The child does not have to (and frequently does not) fill the entire allocated
space. Control is then returned to the parent Panel and the layout process is complete.
PA N EL N A M E DESC RIP T IO N
  Canvas                                                            Defines an area within which you can explicitly position child
                                                                    elements by coordinates relative to the Canvas area.
  DockPanel                                                         Defines an area within which you can arrange child elements
                                                                    either horizontally or vertically, relative to each other.
For applications that require a layout that is not possible by using any of the predefined Panel elements, custom
layout behaviors can be achieved by inheriting from Panel and overriding the MeasureOverride and
ArrangeOverride methods.
What's Next
Understanding how elements are measured and arranged is the first step in understanding layout. For more
information about the available Panel elements, see Panels Overview. To better understand the various
positioning properties that can affect layout, see Alignment, Margins, and Padding Overview. When you are
ready to put it all together in a lightweight application, see Walkthrough: My first WPF desktop application.
See also
   FrameworkElement
   UIElement
   Panels Overview
   Alignment, Margins, and Padding Overview
   Layout and Design
         Migration and Interoperability
         11/21/2022 • 2 minutes to read • Edit Online
This page contains links to documents that discuss how to implement interoperation between Windows
Presentation Foundation (WPF) applications and other types of Microsoft Windows applications.
In This Section
Types migrated from WPF to System.Xaml
WPF and Windows Forms Interoperation
WPF and Win32 Interoperation
WPF and Direct3D9 Interoperation
Reference
 T ERM                                                  DEF IN IT IO N
Related Sections
       Types migrated from WPF to System.Xaml
       11/21/2022 • 5 minutes to read • Edit Online
In .NET Framework 3.5 and .NET Framework 3.0, both Windows Presentation Foundation (WPF) and Windows
Workflow Foundation included a XAML language implementation. Many of the public types that provided
extensibility for the WPF XAML implementation existed in the WindowsBase, PresentationCore, and
PresentationFramework assemblies. Likewise, public types that provided extensibility for Windows Workflow
Foundation XAML existed in the System.Workflow.ComponentModel assembly. In the .NET Framework 4, some
of the XAML-related types were migrated to the System.Xaml assembly. A common .NET Framework
implementation of XAML language services enables many XAML extensibility scenarios that were originally
defined by a specific framework's XAML implementation but are now part of overall .NET Framework 4 XAML
language support. This article lists the types that were migrated and discusses issues related to the migration.
MarkupExtension
In the .NET Framework 3.5 and .NET Framework 3.0, the MarkupExtension class for WPF was in the
WindowsBase assembly. A parallel class for Windows Workflow Foundation, MarkupExtension, existed in the
System.Workflow.ComponentModel assembly. In the .NET Framework 4, the MarkupExtension class is migrated
to the System.Xaml assembly. In the .NET Framework 4, MarkupExtension is intended for any XAML extensibility
scenario that uses .NET XAML Services, not just for those that build on specific frameworks. When possible,
specific frameworks or user code in the framework should also build on the MarkupExtension class for XAML
extension.
  NOTE
  Another service from .NET Framework 3.5 that is related to markup extensions is the IReceiveMarkupExtension interface.
  IReceiveMarkupExtension was not migrated and is marked [Obsolete] for .NET Framework 4. Scenarios that previously
  used IReceiveMarkupExtension should instead use XamlSetMarkupExtensionAttribute attributed callbacks.
  AcceptedMarkupExtensionExpressionTypeAttribute is also marked [Obsolete] .
NullExtension {x:Null}
Although System.Xaml may not have specific support classes, the general logic for processing language features
for the XAML language now resides in System.Xaml and its implemented XAML readers and XAML writers. For
example, x:TypeArguments is an attribute that is processed by XAML readers and XAML writers from
System.Xaml implementations; it can be noted in the XAML node stream, has handling in the default (CLR-
based) XAML schema context, has a XAML type-system representation, and so on. For more information about
the reference documentation for XAML, see XAML Services.
XAML-Related Attributes
WPF XAML included several attributes that can be applied to CLR types to indicate something about their XAML
behavior. The following is a list of the attributes that existed in WPF assemblies in .NET Framework 3.5 and .NET
Framework 3.0. These attributes are migrated to System.Xaml in .NET Framework 4.
   AmbientAttribute
   ContentPropertyAttribute
   ContentWrapperAttribute
   DependsOnAttribute
   MarkupExtensionReturnTypeAttribute
   NameScopePropertyAttribute
   RootNamespaceAttribute
   RuntimeNamePropertyAttribute
   TrimSurroundingWhitespaceAttribute
   ValueSerializerAttribute
   WhitespaceSignificantCollectionAttribute
   XmlLangPropertyAttribute
   XmlnsCompatibleWithAttribute
   XmlnsDefinitionAttribute
   XmlnsPrefixAttribute
Miscellaneous Classes
The IComponentConnector interface existed in WindowsBase in .NET Framework 3.5 and .NET Framework 3.0,
but exists in System.Xaml in .NET Framework 4. IComponentConnector is primarily intended for tooling support
and XAML markup compilers.
The INameScope interface existed in WindowsBase in .NET Framework 3.5 and .NET Framework 3.0, but exists in
System.Xaml in .NET Framework 4. INameScope defines basic operations for a XAML namescope.
XamlWriter
XamlParseException
WPF and Windows Forms present two different architectures for creating application interfaces. The
System.Windows.Forms.Integration namespace provides classes that enable common interoperation scenarios.
The two key classes that implement interoperation capabilities are WindowsFormsHost and ElementHost. This
topic describes which interoperation scenarios are supported and which scenarios are not supported.
  NOTE
  Special consideration is given to the hybrid control scenario. A hybrid control has a control from one technology nested in
  a control from the other technology. This is also called a nested interoperation. A multilevel hybrid control has more than
  one level of hybrid control nesting. An example of a multilevel nested interoperation is a Windows Forms control that
  contains a WPF control, which contains another Windows Forms control. Multilevel hybrid controls are not supported.
  Transparency                          Windows Forms control rendering        Some Windows Forms controls do not
                                        supports transparency. The             support transparency. For example, the
                                        background of the parent WPF control   TextBox and ComboBox controls will
                                        can become the background of hosted    not be transparent when hosted by
                                        Windows Forms controls.                WPF.
B EH AVIO R   SUP P O RT ED                             N OT SUP P O RT ED
Navigation with arrow keys   - Navigation with arrow keys in the        Not applicable.
                             WindowsFormsHost control is the
                             same as in an ordinary Windows
                             Forms container control: The UP
                             ARROW and LEFT ARROW keys select
                             the previous control, and the DOWN
                             ARROW and RIGHT ARROW keys
                             select the next control.
                             - The UP ARROW and LEFT ARROW
                             keys from the first control that is
                             contained in the WindowsFormsHost
                             control perform the same action as the
                             SHIFT+TAB keyboard shortcut. If there
                             is a focusable WPF control, focus
                             moves outside the
                             WindowsFormsHost control. This
                             behavior differs from the standard
                             ContainerControl behavior in that no
                             wrapping to the last control occurs. If
                             no other focusable WPF control exists,
                             focus returns to the last Windows
                             Forms control in the tab order.
                             - The DOWN ARROW and RIGHT
                             ARROW keys from the last control that
                             is contained in the WindowsFormsHost
                             control perform the same action as the
                             TAB key. If there is a focusable WPF
                             control, focus moves outside the
                             WindowsFormsHost control. This
                             behavior differs from the standard
                             ContainerControl behavior in that no
                             wrapping to the first control occurs. If
                             no other focusable WPF control exists,
                             focus returns to the first Windows
                             Forms control in the tab order.
Shortcut keys                          Shortcut keys work as usual, except         - Windows Forms shortcut keys that
                                       where noted in the "Not supported"          are handled at the preprocessing stage
                                       column.                                     always take precedence over WPF
                                                                                   shortcut keys. For example, if you have
                                                                                   a ToolStrip control with CTRL+S
                                                                                   shortcut keys defined, and there is a
                                                                                   WPF command bound to CTRL+S, the
                                                                                   ToolStrip control handler is always
                                                                                   invoked first, regardless of focus.
                                                                                   - Windows Forms shortcut keys that
                                                                                   are handled by the KeyDown event are
                                                                                   processed last in WPF. You can prevent
                                                                                   this behavior by overriding the
                                                                                   Windows Forms control's IsInputKey
                                                                                   method or handling the
                                                                                   PreviewKeyDown event. Return true
                                                                                   from the IsInputKey method, or set
                                                                                   the value of the
                                                                                   PreviewKeyDownEventArgs.IsInputKey
                                                                                   property to true in your
                                                                                   PreviewKeyDown event handler.
AcceptsReturn, AcceptsTab, and other   Properties that change the default          Windows Forms controls that change
control-specific behavior              keyboard behavior work as usual,            default keyboard behavior by handling
                                       assuming that the Windows Forms             the KeyDown event are processed last
                                       control overrides the IsInputKey            in the host WPF control. Because these
                                       method to return true .                     controls are processed last, they can
                                                                                   produce unexpected behavior.
Enter and Leave Events                 When focus is not going to the              Enter and Leave events are not raised
                                       containing ElementHost control, the         when the following focus changes
                                       Enter and Leave events are raised as        occur:
                                       usual when focus changes in a single
                                       WindowsFormsHost control.                   - From inside to outside a
                                                                                   WindowsFormsHost control.
                                                                                   - From outside to inside a
                                                                                   WindowsFormsHost control.
                                                                                   - Outside a WindowsFormsHost
                                                                                   control.
                                                                                   - From a Windows Forms control
                                                                                   hosted in a WindowsFormsHost
                                                                                   control to an ElementHost control
                                                                                   hosted inside the same
                                                                                   WindowsFormsHost.
Multithreading                         All varieties of multithreading are         Both the Windows Forms and WPF
                                       supported.                                  technologies assume a single-threaded
                                                                                   concurrency model. During debugging,
                                                                                   calls to framework objects from other
                                                                                   threads will raise an exception to
                                                                                   enforce this requirement.
 Multithreading                    All varieties of multithreading are         Both the Windows Forms and WPF
                                   supported.                                  technologies assume a single-threaded
                                                                               concurrency model. During debugging,
                                                                               calls to framework objects from other
                                                                               threads will raise an exception to
                                                                               enforce this requirement.
See also
  ElementHost
  WindowsFormsHost
  Walkthrough: Hosting a Windows Forms Control in WPF
  Walkthrough: Hosting a Windows Forms Composite Control in WPF
  Walkthrough: Hosting a WPF Composite Control in Windows Forms
  Windows Forms and WPF Property Mapping
       Windows Forms and WPF Interoperability Input
       Architecture
       11/21/2022 • 4 minutes to read • Edit Online
Interoperation between the WPF and Windows Forms requires that both technologies have the appropriate
keyboard input processing. This topic describes how these technologies implement keyboard and message
processing to enable smooth interoperation in hybrid applications.
This topic contains the following subsections:
   Modeless Forms and Dialog Boxes
   WindowsFormsHost Keyboard and Message Processing
   ElementHost Keyboard and Message Processing
See also
   EnableWindowsFormsInterop
   EnableModelessKeyboardInterop
   ElementHost
   WindowsFormsHost
   Walkthrough: Hosting a Windows Forms Composite Control in WPF
   Walkthrough: Hosting a WPF Composite Control in Windows Forms
   WPF and Win32 Interoperation
        Layout Considerations for the WindowsFormsHost
        Element
        11/21/2022 • 6 minutes to read • Edit Online
This topic describes how the WindowsFormsHost element interacts with the WPF layout system.
WPF and Windows Forms support different, but similar, logic for sizing and positioning elements on a form or
page. When you create a hybrid user interface (UI) that hosts Windows Forms controls in WPF, the
WindowsFormsHost element integrates the two layout schemes.
  Anchoring and docking                                        Windows Forms controls support positioning and sizing
                                                               based on the parent container. For more information, see
                                                               Control.Anchor and Control.Dock.
Layout Limitations
In general, Windows Forms controls cannot be scaled and transformed to the extent possible in WPF. The
following list describes the known limitations when the WindowsFormsHost element attempts to integrate its
hosted Windows Forms control into the WPF layout system.
   In some cases, Windows Forms controls cannot be resized, or can be sized only to specific dimensions.
   For example, a Windows Forms ComboBox control supports only a single height, which is defined by the
   control's font size. In a WPF dynamic layout where elements can stretch vertically, a hosted ComboBox
   control will not stretch as expected.
   Windows Forms controls cannot be rotated or skewed. The WindowsFormsHost element raises the
   LayoutError event if you apply a skew or rotation transformation. If you do not handle the LayoutError
   event, an InvalidOperationException is raised.
   In most cases, Windows Forms controls do not support proportional scaling. Although the overall
   dimensions of the control will scale, child controls and component elements of the control may not resize
   as expected. This limitation depends on how well each Windows Forms control supports scaling. In
   addition, you cannot scale Windows Forms controls down to a size of 0 pixels.
   Windows Forms controls support autoscaling, in which the form will automatically resize itself and its
   controls based on the font size. In a WPF user interface, changing the font size does not resize the entire
   layout, although individual elements may dynamically resize.
Z-order
In a WPF user interface, you can change the z-order of elements to control overlapping behavior. A hosted
Windows Forms control is drawn in a separate HWND, so it is always drawn on top of WPF elements.
A hosted Windows Forms control is also drawn on top of any Adorner elements.
Layout Behavior
The following sections describe specific aspects of layout behavior when hosting Windows Forms controls in
WPF.
Scaling, Unit Conversion, and Device Independence
Whenever the WindowsFormsHost element performs operations involving WPF and Windows Forms
dimensions, two coordinate systems are involved: device-independent pixels for WPF and hardware pixels for
Windows Forms. Therefore, you must apply proper unit and scaling conversions to achieve a consistent layout.
Conversion between the coordinate systems depends on the current device resolution and any layout or
rendering transforms applied to the WindowsFormsHost element or to its ancestors.
If the output device is 96 dpi and no scaling has been applied to the WindowsFormsHost element, one device-
independent pixel is equal to one hardware pixel.
All other cases require coordinate system scaling. The hosted control is not resized. Instead, the
WindowsFormsHost element attempts to scale the hosted control and all of its child controls. Because Windows
Forms does not fully support scaling, the WindowsFormsHost element scales to the degree supported by
particular controls.
Override the ScaleChild method to provide custom scaling behavior for the hosted Windows Forms control.
In addition to scaling, the WindowsFormsHost element handles rounding and overflow cases as described in the
following table.
Layout-related Properties
Properties that control layout behavior in Windows Forms controls and WPF elements are mapped
appropriately by the WindowsFormsHost element. For more information, see Windows Forms and WPF
Property Mapping.
Layout Changes in the Hosted Control
Layout changes in the hosted Windows Forms control are propagated to WPF to trigger layout updates. The
InvalidateMeasure method on WindowsFormsHost ensures that layout changes in the hosted control cause the
WPF layout engine to run.
Continuously Sized Windows Forms Controls
Windows Forms controls that support continuous scaling fully interact with the WPF layout system. The
WindowsFormsHost element uses the MeasureOverride and ArrangeOverride methods as usual to size and
arrange the hosted Windows Forms control.
Sizing Algorithm
The WindowsFormsHost element uses the following procedure to size the hosted control:
1. The WindowsFormsHost element overrides the MeasureOverride and ArrangeOverride methods.
2. To determine the size of the hosted control, the MeasureOverride method calls the hosted control's
   GetPreferredSize method with a constraint translated from the constraint passed to the MeasureOverride
   method.
3. The ArrangeOverride method attempts to set the hosted control to the given size constraint.
4. If the hosted control's Size property matches the specified constraint, the hosted control is sized to the
   constraint.
If the Size property does not match the specified constraint, the hosted control does not support continuous
sizing. For example, the MonthCalendar control allows only discrete sizes. The permitted sizes for this control
consist of integers (representing the number of months) for both height and width. In cases such as this, the
WindowsFormsHost element behaves as follows:
   If the Size property returns a larger size than the specified constraint, the WindowsFormsHost element
   clips the hosted control. Height and width are handled separately, so the hosted control may be clipped in
   either direction.
   If the Size property returns a smaller size than the specified constraint, WindowsFormsHost accepts this
   size value and returns the value to the WPF layout system.
See also
   ElementHost
   WindowsFormsHost
   Walkthrough: Arranging Windows Forms Controls in WPF
   Arranging Windows Forms Controls in WPF Sample
   Windows Forms and WPF Property Mapping
   Migration and Interoperability
        Windows Forms Controls and Equivalent WPF
        Controls
        11/21/2022 • 2 minutes to read • Edit Online
Many Windows Forms controls have equivalent WPF controls, but some Windows Forms controls have no
equivalents in WPF. This topic compares control types provided by the two technologies.
You can always use interoperation to host Windows Forms controls that do not have equivalents in your WPF-
based applications.
The following table shows which Windows Forms controls and components have equivalent WPF control
functionality.
W IN DO W S F O RM S C O N T RO L W P F EQ UIVA L EN T C O N T RO L REM A RK S
BindingSource CollectionViewSource
Button Button
CheckBox CheckBox
ContextMenuStrip ContextMenu
DataGridView DataGrid
DateTimePicker DatePicker
GroupBox GroupBox
Label Label
LinkLabel                           No equivalent control.              You can use the Hyperlink class to host
                                                                        hyperlinks within flow content.
ListBox ListBox
MonthCalendar Calendar
Panel Canvas
PictureBox Image
PrintDialog PrintDialog
PrintPreviewControl DocumentViewer
ProgressBar                         ProgressBar
W IN DO W S F O RM S C O N T RO L   W P F EQ UIVA L EN T C O N T RO L   REM A RK S
RadioButton RadioButton
RichTextBox RichTextBox
ScrollableControl ScrollViewer
SoundPlayer MediaPlayer
SplitContainer GridSplitter
StatusStrip StatusBar
TabControl TabControl
TableLayoutPanel Grid
TextBox TextBox
Timer DispatcherTimer
ToolStrip ToolBar
ToolTip ToolTip
TrackBar Slider
TreeView TreeView
UserControl UserControl
See also
  ElementHost
  WindowsFormsHost
  WPF Designer for Windows Forms Developers
  Walkthrough: Hosting a Windows Forms Control in WPF
  Walkthrough: Hosting a WPF Composite Control in Windows Forms
  Migration and Interoperability
       Windows Forms and WPF Property Mapping
       11/21/2022 • 6 minutes to read • Edit Online
The Windows Forms and WPF technologies have two similar but different property models. Property mapping
supports interoperation between the two architectures and provides the following capabilities:
   Makes it easy to map relevant property changes in the host environment to the hosted control or
   element.
   Provides default handling for mapping the most commonly used properties.
   Allows easy removal, overriding, or extending of default properties.
   Ensures that property value changes on the host are automatically detected and translated to the hosted
   control or element.
  NOTE
  Property-change events are not propagated up the hosting control or element hierarchy. Property translation is not
  performed if the local value of a property does not change because of direct setting, styles, inheritance, data binding, or
  other mechanisms that change the value of the property.
Use the PropertyMap property on the WindowsFormsHost element and the PropertyMap property on
ElementHost control to access property mapping.
 W IN DO W S P RESEN TAT IO N
 F O UN DAT IO N H O ST IN G                  W IN DO W S F O RM S                         IN T ERO P ERAT IO N B EH AVIO R
W IN DO W S P RESEN TAT IO N
F O UN DAT IO N H O ST IN G      W IN DO W S F O RM S                 IN T ERO P ERAT IO N B EH AVIO R
                                                                      FlowDirection.RightToLeft maps to
                                                                      RightToLeft.Yes.
W IN DO W S P RESEN TAT IO N
F O UN DAT IO N H O ST IN G    W IN DO W S F O RM S            IN T ERO P ERAT IO N B EH AVIO R
FontStyle                      Style on the hosted control's   The set of WPF properties is translated
                               System.Drawing.Font             into a corresponding Font. When one
                                                               of these properties changes, a new
                                                               Font is created. For Normal: Italic is
                                                               disabled. For Italic or Oblique: Italic is
                                                               enabled.
FontWeight                     Style on the hosted control's   The set of WPF properties is translated
                               System.Drawing.Font             into a corresponding Font. When one
                                                               of these properties changes, a new
                                                               Font is created. For Black, Bold,
                                                               DemiBold, ExtraBold, Heavy, Medium,
                                                               SemiBold, or UltraBold: Bold is enabled.
                                                               For ExtraLight, Light, Normal, Regular,
                                                               Thin, or UltraLight: Bold is disabled.
Attached properties on container elements are fully supported by the WindowsFormsHost element.
For more information, see Walkthrough: Mapping Properties Using the WindowsFormsHost Element.
                                       W IN DO W S P RESEN TAT IO N
 W IN DO W S F O RM S H O ST IN G      F O UN DAT IO N                       IN T ERO P ERAT IO N B EH AVIO R
FontStretch
FontStyle
FontWeight
See also
ElementHost
WindowsFormsHost
WPF and Win32 Interoperation
WPF and Windows Forms Interoperation
Walkthrough: Mapping Properties Using the WindowsFormsHost Element
Walkthrough: Mapping Properties Using the ElementHost Control
       Troubleshooting Hybrid Applications
      11/21/2022 • 6 minutes to read • Edit Online
This topic lists some common problems that can occur when authoring hybrid applications, which use both WPF
and Windows Forms technologies.
Overlapping Controls
Controls may not overlap as you would expect. Windows Forms uses a separate HWND for each control. WPF
uses one HWND for all content on a page. This implementation difference causes unexpected overlapping
behaviors.
A Windows Forms control hosted in WPF always appears on top of the WPF content.
WPF content hosted in an ElementHost control appears at the z-order of the ElementHost control. It is possible
to overlap ElementHost controls, but the hosted WPF content does not combine or interact.
Child Property
The WindowsFormsHost and ElementHost classes can host only a single child control or element. To host more
than one control or element, you must use a container as the child content. For example, you could add
Windows Forms button and check box controls to a System.Windows.Forms.Panel control, and then assign the
panel to a WindowsFormsHost control's Child property. However, you cannot add the button and check box
controls separately to the same WindowsFormsHost control.
Scaling
WPF and Windows Forms have different scaling models. Some WPF scaling transformations are meaningful to
Windows Forms controls, but others are not. For example, scaling a Windows Forms control to 0 will work, but if
you try to scale the same control back to a non-zero value, the control's size remains 0. For more information,
see Layout Considerations for the WindowsFormsHost Element.
Adapter
There may be confusion when working the WindowsFormsHost and ElementHost classes, because they include
a hidden container. Both the WindowsFormsHost and ElementHost classes have a hidden container, called an
adapter, which they use to host content. For the WindowsFormsHost element, the adapter derives from the
System.Windows.Forms.ContainerControl class. For the ElementHost control, the adapter derives from the
DockPanel element. When you see references to the adapter in other interoperation topics, this container is what
is being discussed.
Nesting
Nesting a WindowsFormsHost element inside an ElementHost control is not supported. Nesting an ElementHost
control inside a WindowsFormsHost element is also not supported.
Focus
Focus works differently in WPF and Windows Forms, which means that focus issues may occur in a hybrid
application. For example, if you have focus inside a WindowsFormsHost element, and you either minimize and
restore the page or show a modal dialog box, focus inside the WindowsFormsHost element may be lost. The
WindowsFormsHost element still has focus, but the control inside it may not.
Data validation is also affected by focus. Validation works in a WindowsFormsHost element, but it does not work
as you tab out of the WindowsFormsHost element, or between two different WindowsFormsHost elements.
Property Mapping
Some property mappings require extensive interpretation to bridge dissimilar implementations between the
WPF and Windows Forms technologies. Property mappings enable your code to react to changes in fonts,
colors, and other properties. In general, property mappings work by listening for either PropertyChanged
events or OnPropertyChanged calls, and setting appropriate properties on either the child control or its adapter.
For more information, see Windows Forms and WPF Property Mapping.
H O ST C L A SS C O N T EN T P RO P ERT IES
ElementHost Height
Width
Margin
VerticalAlignment
HorizontalAlignment
WindowsFormsHost Margin
Dock
AutoSize
Location
MaximumSize
Do not set these properties directly on the hosted content. For more information, see Layout Considerations for
the WindowsFormsHost Element.
Navigation Applications
Navigation applications may not maintain user state. The WindowsFormsHost element recreates its controls
when it is used in a navigation application. Recreating child controls occurs when the user navigates away from
the page hosting the WindowsFormsHost element and then returns to it. Any content that has been typed in by
the user will be lost.
Dispose
Not disposing classes properly can leak resources. In your hybrid applications, make sure that the
WindowsFormsHost and ElementHost classes are disposed, or you could leak resources. Windows Forms
disposes ElementHost controls when its non-modal Form parent closes. WPF disposes WindowsFormsHost
elements when your application shuts down. It is possible to show a WindowsFormsHost element in a Window
in a Windows Forms message loop. In this case, your code may not receive notification that your application is
shutting down.
Licensed Controls
Licensed Windows Forms controls that display licensing information in a message box to the user might cause
unexpected behavior for a hybrid application. Some licensed controls show a dialog box in response to handle
creation. For example, a licensed control might inform the user that a license is required, or that the user has
three remaining trial uses of the control.
The WindowsFormsHost element derives from the HwndHost class, and the child control’s handle is created
inside the BuildWindowCore method. The HwndHost class does not allow messages to be processed in the
BuildWindowCore method, but displaying a dialog box causes messages to be sent. To enable this licensing
scenario, call the Control.CreateControl method on the control before assigning it as the WindowsFormsHost
element's child.
WPF Designer
You can design your WPF content by using the WPF Designer for Visual Studio. The following sections list some
common problems that can occur when authoring hybrid applications with the WPF Designer.
BackColorTransparent is ignored at design time
The BackColorTransparent property might not work as expected at design time.
If a WPF control is not on a visible parent, the WPF runtime ignores the BackColorTransparent value. The reason
that BackColorTransparent might be ignored is because ElementHost object is created in a separate AppDomain.
However, when you run the application, BackColorTransparent does work as expected.
Design-time Error List appears when the obj folder is deleted
If the obj folder is deleted, the Design-time Error List appears.
When you design using ElementHost, the Windows Forms Designer uses generated files in the Debug or
Release folder within your project's obj folder. If you delete these files, the Design-time Error List appears. To fix
this problem, rebuild your project. For more information, see Design-Time Errors in the Windows Forms
Designer.
See also
   ElementHost
   WindowsFormsHost
   Interoperability in the WPF Designer
   Windows Forms and WPF Interoperability Input Architecture
   How to: Enable Visual Styles in a Hybrid Application
   Layout Considerations for the WindowsFormsHost Element
   Windows Forms and WPF Property Mapping
   Design-Time Errors in the Windows Forms Designer
   Migration and Interoperability
      Walkthrough: Hosting a Windows Forms Control in
      WPF
      11/21/2022 • 2 minutes to read • Edit Online
WPF provides many controls with a rich feature set. However, you may sometimes want to use Windows Forms
controls on your WPF pages. For example, you may have a substantial investment in existing Windows Forms
controls, or you may have a Windows Forms control that provides unique functionality.
This walkthrough shows you how to host a Windows Forms System.Windows.Forms.MaskedTextBox control on
a WPF page by using code.
For a complete code listing of the tasks shown in this walkthrough, see Hosting a Windows Forms Control in
WPF Sample.
Prerequisites
You need Visual Studio to complete this walkthrough.
<Grid Name="grid1">
</Grid>
End Sub
9. At the top of the file, add the following Imports or using statement.
using System.Windows.Forms;
Imports System.Windows.Forms
 See also
    ElementHost
    WindowsFormsHost
    Design XAML in Visual Studio
    Walkthrough: Hosting a Windows Forms Control in WPF by Using XAML
    Walkthrough: Hosting a Windows Forms Composite Control in WPF
    Walkthrough: Hosting a WPF Composite Control in Windows Forms
    Windows Forms Controls and Equivalent WPF Controls
    Hosting a Windows Forms Control in WPF Sample
       Walkthrough: Hosting a Windows Forms Control in
       WPF by Using XAML
       11/21/2022 • 2 minutes to read • Edit Online
WPF provides many controls with a rich feature set. However, you may sometimes want to use Windows Forms
controls on your WPF pages. For example, you may have a substantial investment in existing Windows Forms
controls, or you may have a Windows Forms control that provides unique functionality.
This walkthrough shows you how to host a Windows Forms System.Windows.Forms.MaskedTextBox control on
a WPF page by using XAML.
For a complete code listing of the tasks shown in this walkthrough, see Hosting a Windows Forms Control in
WPF by Using XAML Sample.
Prerequisites
You need Visual Studio to complete this walkthrough.
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
<Grid>
           <WindowsFormsHost>
               <wf:MaskedTextBox x:Name="mtbDate" Mask="00/00/0000"/>
           </WindowsFormsHost>
</Grid>
See also
ElementHost
WindowsFormsHost
Design XAML in Visual Studio
Walkthrough: Hosting a Windows Forms Control in WPF
Walkthrough: Hosting a Windows Forms Composite Control in WPF
Walkthrough: Hosting a WPF Composite Control in Windows Forms
Windows Forms Controls and Equivalent WPF Controls
Hosting a Windows Forms Control in WPF by Using XAML Sample
       Walkthrough: Hosting a Windows Forms Composite
       Control in WPF
       11/21/2022 • 15 minutes to read • Edit Online
WPF application rather than to rewrite it from scratch. The most common scenario is when you have existing
Windows Forms controls. In some cases, you might not even have access to the source code for these controls.
WPF provides a straightforward procedure for hosting such controls in a WPF application. For example, you can
use WPF for most of your programming while hosting your specialized DataGridView controls.
This walkthrough steps you through an application that hosts a Windows Forms composite control to perform
data entry in a WPF application. The composite control is packaged in a DLL. This general procedure can be
extended to more complex applications and controls. This walkthrough is designed to be nearly identical in
appearance and functionality to Walkthrough: Hosting a WPF Composite Control in Windows Forms. The
primary difference is that the hosting scenario is reversed.
The walkthrough is divided into two sections. The first section briefly describes the implementation of the
Windows Forms composite control. The second section discusses in detail how to host the composite control in
a WPF application, receive events from the control, and access some of the control's properties.
Tasks illustrated in this walkthrough include:
   Implementing the Windows Forms composite control.
   Implementing the WPF host application.
For a complete code listing of the tasks illustrated in this walkthrough, see Hosting a Windows Forms
Composite Control in WPF Sample.
Prerequisites
You need Visual Studio to complete this walkthrough.
Add five Label controls and their corresponding TextBox controls, sized and arranged as they are in the
preceding illustration, on the form. In the example, the TextBox controls are named:
    txtName
txtAddress
txtCity
txtState
txtZip
Add two Button controls labeled OK and Cancel . In the example, the button names are       btnOK   and       btnCancel   ,
respectively.
Implementing the Supporting Code
Open the form in code view. The control returns the collected data to its host by raising the custom
 OnButtonClick event. The data is contained in the event argument object. The following code shows the event
and delegate declaration.
Add the following code to the      MyControl1    class.
    Public Sub New(ByVal result As Boolean, ByVal name As String, ByVal address As String, ByVal city As
String, ByVal state As String, ByVal zip As String)
        _IsOK = result
        _Name = name
        _StreetAddress = address
        _City = city
        _State = state
        _Zip = zip
End Sub
When the user clicks the OK or Cancel button, the Click event handlers create a MyControlEventArgs object that
contains the data and raises the OnButtonClick event. The only difference between the two handlers is the event
argument's IsOK property. This property enables the host to determine which button was clicked. It is set to
 true for the OK button, and false for the Cancel button. The following code shows the two button handlers.
End Sub
End Sub
Sn.exe -k MyControls.snk
4. To include the key file in your project, right-click the project name in Solution Explorer and then click
   Proper ties . In the Project Designer, click the Signing tab, select the Sign the assembly check box and
   then browse to your key file.
5. Build the solution. The build will produce a DLL named MyControls.dll.
   <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="WpfHost.MainWindow"
         xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
         Loaded="Init">
     <DockPanel>
       <DockPanel.Resources>
         <Style x:Key="inlineText" TargetType="{x:Type Inline}">
           <Setter Property="FontWeight" Value="Normal"/>
         </Style>
         <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
           <Setter Property="DockPanel.Dock" Value="Top"/>
           <Setter Property="FontWeight" Value="Bold"/>
           <Setter Property="Margin" Value="10,5,10,0"/>
         </Style>
       </DockPanel.Resources>
       <StackPanel Orientation="Vertical"
                   DockPanel.Dock="Left"
                   Background="Bisque"
                   Width="250">
         <TextBlock Margin="10,10,10,10"
                     FontWeight="Bold"
                     FontSize="12">Control Properties</TextBlock>
         <TextBlock Style="{StaticResource titleText}">Background Color</TextBlock>
         <StackPanel Margin="10,10,10,10">
           <RadioButton Name="rdbtnOriginalBackColor"
                       IsChecked="True"
                       Click="BackColorChanged">Original</RadioButton>
           <RadioButton Name="rdbtnBackGreen"
                       Click="BackColorChanged">LightGreen</RadioButton>
           <RadioButton Name="rdbtnBackSalmon"
                       Click="BackColorChanged">LightSalmon</RadioButton>
         </StackPanel>
  <TextBlock Style="{StaticResource titleText}">Foreground Color</TextBlock>
  <StackPanel Margin="10,10,10,10">
    <RadioButton Name="rdbtnOriginalForeColor"
                IsChecked="True"
                Click="ForeColorChanged">Original</RadioButton>
    <RadioButton Name="rdbtnForeRed"
                Click="ForeColorChanged">Red</RadioButton>
    <RadioButton Name="rdbtnForeYellow"
                Click="ForeColorChanged">Yellow</RadioButton>
  </StackPanel>
<WindowsFormsHost Name="wfh"
                 DockPanel.Dock="Top"
                 Height="300">
  <mcl:MyControl1 Name="mc"/>
</WindowsFormsHost>
<StackPanel Orientation="Vertical"
            Height="Auto"
            Background="LightBlue">
  <TextBlock Margin="10,10,10,10"
        FontWeight="Bold"
        FontSize="12">Data From Control</TextBlock>
  <TextBlock Style="{StaticResource titleText}">
    Name: <Span Name="txtName" Style="{StaticResource inlineText}"/>
           Name: <Span Name="txtName" Style="{StaticResource inlineText}"/>
         </TextBlock>
         <TextBlock Style="{StaticResource titleText}">
           Street Address: <Span Name="txtAddress" Style="{StaticResource inlineText}"/>
         </TextBlock>
         <TextBlock Style="{StaticResource titleText}">
           City: <Span Name="txtCity" Style="{StaticResource inlineText}"/>
         </TextBlock>
         <TextBlock Style="{StaticResource titleText}">
           State: <Span Name="txtState" Style="{StaticResource inlineText}"/>
         </TextBlock>
         <TextBlock Style="{StaticResource titleText}">
           Zip: <Span Name="txtZip" Style="{StaticResource inlineText}"/>
         </TextBlock>
       </StackPanel>
     </DockPanel>
   </Window>
The first StackPanel element contains several sets of RadioButton controls that enable you to modify various
default properties of the hosted control. That is followed by a WindowsFormsHost element, which hosts
 MyControl1 . The final StackPanel element contains several TextBlock elements that display the data that is
returned by the hosted control. The ordering of the elements and the Dock and Height attribute settings embed
the hosted control into the window with no gaps or distortion.
Hosting the Control
The following edited version of the previous XAML focuses on the elements that are needed to host          MyControl1   .
   <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="WpfHost.MainWindow"
         xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
         Loaded="Init">
   <WindowsFormsHost Name="wfh"
                    DockPanel.Dock="Top"
                    Height="300">
     <mcl:MyControl1 Name="mc"/>
   </WindowsFormsHost>
The xmlns namespace mapping attribute creates a reference to the MyControls namespace that contains the
hosted control. This mapping enables you to represent MyControl1 in XAML as <mcl:MyControl1> .
Two elements in the XAML handle the hosting:
    WindowsFormsHost  represents the WindowsFormsHost element that enables you to host a Windows
   Forms control in a WPF application.
    mcl:MyControl1   , which represents MyControl1 , is added to the WindowsFormsHost element's child
   collection. As a result, this Windows Forms control is rendered as part of the WPF window, and you can
   communicate with the control from the application.
Implementing the Code -Behind File
The code-behind file, MainWindow.xaml.vb or MainWindow.xaml.cs, contains the procedural code that
implements the functionality of the UI discussed in the preceding section. The primary tasks are:
   Attaching an event handler to   MyControl1   's   OnButtonClick   event.
   Modifying various properties of   MyControl1      , based on how the collection of option buttons are set.
   Displaying the data collected by the control.
Initializing the Application
The initialization code is contained in an event handler for the window's Loaded event and attaches an event
handler to the control's OnButtonClick event.
In MainWindow.xaml.vb or MainWindow.xaml.cs, add the following code to the      MainWindow   class.
End Sub
Because the XAML discussed previously added     MyControl1   to the WindowsFormsHost element's child element
collection, you can cast the WindowsFormsHost element's Child to get the reference to          MyControl1       . You can
then use that reference to attach an event handler to OnButtonClick .
In addition to providing a reference to the control itself, WindowsFormsHost exposes a number of the control's
properties, which you can manipulate from the application. The initialization code assigns those values to
private global variables for later use in the application.
So that you can easily access the types in the     MyControls   DLL, add the following   Imports   or   using    statement
to the top of the file.
Imports MyControls
using MyControls;
       if (args.IsOK)
       {
           txtName.Inlines.Add( " " + args.MyName );
           txtAddress.Inlines.Add( " " + args.MyStreetAddress );
           txtCity.Inlines.Add( " " + args.MyCity );
           txtState.Inlines.Add( " " + args.MyState );
           txtZip.Inlines.Add( " " + args.MyZip );
       }
   }
       If args.IsOK Then
           txtName.Inlines.Add(" " + args.MyName)
           txtAddress.Inlines.Add(" " + args.MyStreetAddress)
           txtCity.Inlines.Add(" " + args.MyCity)
           txtState.Inlines.Add(" " + args.MyState)
           txtZip.Inlines.Add(" " + args.MyZip)
       End If
End Sub
The data in the text boxes is packed into the MyControlEventArgs object. If the user clicks the OK button, the
event handler extracts the data and displays it in the panel below MyControl1 .
Modifying the Control’s Properties
The WindowsFormsHost element exposes several of the hosted control's default properties. As a result, you can
change the appearance of the control to match the style of your application more closely. The sets of option
buttons in the left panel enable the user to modify several color and font properties. Each set of buttons has a
handler for the Click event, which detects the user's option button selections and changes the corresponding
property on the control.
Add the following code to the        MainWindow   class.
       If sender.Equals(rdbtnBackGreen) Then
           wfh.Background = New SolidColorBrush(Colors.LightGreen)
       ElseIf sender.Equals(rdbtnBackSalmon) Then
           wfh.Background = New SolidColorBrush(Colors.LightSalmon)
       ElseIf UIIsReady = True Then
           wfh.Background = initBackBrush
       End If
End Sub
End Sub
End Sub
End Sub
End Sub
End Sub
Build and run the application. Add some text in the Windows Forms composite control and then click OK . The
text appears in the labels. Click the different radio buttons to see the effect on the control.
See also
 ElementHost
 WindowsFormsHost
 Design XAML in Visual Studio
 Walkthrough: Hosting a Windows Forms Control in WPF
 Walkthrough: Hosting a WPF Composite Control in Windows Forms
       Walkthrough: Hosting an ActiveX Control in WPF
       11/21/2022 • 3 minutes to read • Edit Online
To enable improved interaction with browsers, you can use Microsoft ActiveX controls in your WPF-based
application. This walkthrough demonstrates how you can host the Microsoft Windows Media Player as a control
on a WPF page.
Tasks illustrated in this walkthrough include:
   Creating the project.
   Creating the ActiveX control.
   Hosting the ActiveX control on a WPF Page.
When you have completed this walkthrough, you will understand how to use Microsoft ActiveX controls in your
WPF-based application.
Prerequisites
You need the following components to complete this walkthrough:
   Microsoft Windows Media Player installed on the computer where Visual Studio is installed.
   Visual Studio 2010.
<Grid Name="grid1">
</Grid>
End Sub
 See also
    ElementHost
    WindowsFormsHost
    Design XAML in Visual Studio
    Walkthrough: Hosting a Windows Forms Composite Control in WPF
    Walkthrough: Hosting a WPF Composite Control in Windows Forms
       How to: Enable Visual Styles in a Hybrid Application
       11/21/2022 • 2 minutes to read • Edit Online
This topic shows how to enable visual styles on a Windows Forms control hosted in a WPF-based application.
If your application calls the EnableVisualStyles method, most of your Windows Forms controls will automatically
use visual styles. For more information, see Rendering Controls with Visual Styles.
For a complete code listing of the tasks illustrated in this topic, see Enabling Visual Styles in a Hybrid Application
Sample.
           ' Assign the Windows Forms tab control as the hosted control.
           host.Child = tc
End Sub
See also
   EnableVisualStyles
   System.Windows.Forms.VisualStyles
   WindowsFormsHost
   Rendering Controls with Visual Styles
   Walkthrough: Hosting a Windows Forms Control in WPF
       Walkthrough: Arranging Windows Forms Controls in
       WPF
       11/21/2022 • 9 minutes to read • Edit Online
This walkthrough shows you how to use WPF layout features to arrange Windows Forms controls in a hybrid
application.
Tasks illustrated in this walkthrough include:
   Creating the project.
   Using default layout settings.
   Sizing to content.
   Using absolute positioning.
   Specifying size explicitly.
   Setting layout properties.
   Understanding z-order limitations.
   Docking.
   Setting visibility.
   Hosting a control that does not stretch.
   Scaling.
   Rotating.
   Setting padding and margins.
   Using dynamic layout containers.
For a complete code listing of the tasks illustrated in this walkthrough, see Arranging Windows Forms Controls
in WPF Sample.
When you are finished, you will have an understanding of Windows Forms layout features in WPF-based
applications.
Prerequisites
You need Visual Studio to complete this walkthrough.
5. In the Grid element set the ShowGridLines property to true and define five rows and three columns.
      <Grid ShowGridLines="true">
        <Grid.RowDefinitions>
          <RowDefinition/>
          <RowDefinition/>
          <RowDefinition/>
          <RowDefinition/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
2. Press F5 to build and run the application. The Windows Forms System.Windows.Forms.Button control
   appears in the Canvas. The hosted control is sized based on its content, and the WindowsFormsHost
   element is sized to accommodate the hosted control.
Sizing to Content
The WindowsFormsHost element ensures that the hosted control is sized to display its content properly.
To size to content, follow these steps:
1. Copy the following XAML into the Grid element:
2. Press F5 to build and run the application. The WindowsFormsHost element is placed 20 pixels from the
   top side of the grid cell and 20 pixels from the left.
2. Press F5 to build and run the application. The WindowsFormsHost element is set to a size of 50 pixels
   wide by 70 pixels high, which is smaller than the default layout settings. The content of the Windows
   Forms control is rearranged accordingly.
          b.Top = 20;
          b.Left = 20;
      }
          b.Top = 20
          b.Left = 20
End Sub
2. Press F5 to build and run the application. The WindowsFormsHost element is painted over the label
   element.
Docking
WindowsFormsHost element supports WPF docking. Set the Dock attached property to dock the hosted control
in a DockPanel element.
To dock a hosted control, follow these steps:
1. Copy the following XAML into the Grid element:
2. Press F5 to build and run the application. The WindowsFormsHost element is docked to the right side of
   the DockPanel element.
Setting Visibility
You can make your Windows Forms control invisible or collapse it by setting the Visibility property on the
WindowsFormsHost element. When a control is invisible, it is not displayed, but it occupies layout space. When a
control is collapsed, it is not displayed, nor does it occupy layout space.
To set the visibility of a hosted control, follow these steps:
1. Copy the following XAML into the Grid element:
2. In MainWindow.xaml.vb or MainWindow.xaml.cs, copy the following code into the class definition:
2. Press F5 to build and run the application. The WindowsFormsHost element is centered in the grid row,
   but it is not stretched to fill the available space. If the window is large enough, you may see two or more
   months displayed by the hosted MonthCalendar control, but these are centered in the row. The WPF
   layout engine centers elements that cannot be sized to fill the available space.
Scaling
Unlike WPF elements, most Windows Forms controls are not continuously scalable. To provide custom scaling,
you override the WindowsFormsHost.ScaleChild method.
To scale a hosted control by using the default behavior, follow these steps:
1. Copy the following XAML into the Grid element:
        <StackPanel.RenderTransform>
          <ScaleTransform CenterX="0" CenterY="0" ScaleX="0.5" ScaleY="0.5" />
        </StackPanel.RenderTransform>
        <WindowsFormsHost Background="Yellow">
          <wf:Button Text="Windows Forms control" FlatStyle="Flat"/>
        </WindowsFormsHost>
</StackPanel>
2. Press F5 to build and run the application. The hosted control and its surrounding elements are scaled by
   a factor of 0.5. However, the hosted control's font is not scaled.
Rotating
Unlike WPF elements, Windows Forms controls do not support rotation. The WindowsFormsHost element does
not rotate with other WPF elements when a rotation transformation is applied. Any rotation value other than
180 degrees raises the LayoutError event.
To see the effect of rotation in a hybrid application, follow these steps:
1. Copy the following XAML into the Grid element:
        <StackPanel.RenderTransform>
          <RotateTransform CenterX="200" CenterY="50" Angle="180" />
        </StackPanel.RenderTransform>
        <WindowsFormsHost Background="Yellow">
          <wf:Button Text="Windows Forms control" FlatStyle="Flat"/>
        </WindowsFormsHost>
</StackPanel>
2. Press F5 to build and run the application. The hosted control is not rotated, but its surrounding elements
   are rotated by an angle of 180 degrees. You may have to resize the window to see the elements.
2. Press F5 to build and run the application. The padding and margin settings are applied to the hosted
   Windows Forms controls in the same way they would be applied in Windows Forms.
2. In MainWindow.xaml.vb or MainWindow.xaml.cs, copy the following code into the class definition:
flp.WrapContents = true;
                flp.Controls.Add(b);
          }
      }
flp.WrapContents = True
          Dim i As Integer
          For i = 0 To numButtons
              Dim b As New System.Windows.Forms.Button()
              b.Text = "Button"
              b.BackColor = System.Drawing.Color.AliceBlue
              b.FlatStyle = System.Windows.Forms.FlatStyle.Flat
              flp.Controls.Add(b)
          Next i
End Sub
          this.InitializeFlowLayoutPanel();
      }
Me.InitializeFlowLayoutPanel()
End Sub
4. Press F5 to build and run the application. The WindowsFormsHost element fills the DockPanel, and
   FlowLayoutPanel arranges its child controls in the default FlowDirection.
See also
  ElementHost
  WindowsFormsHost
  Design XAML in Visual Studio
  Layout Considerations for the WindowsFormsHost Element
  Arranging Windows Forms Controls in WPF Sample
  Walkthrough: Hosting a Windows Forms Composite Control in WPF
  Walkthrough: Hosting a WPF Composite Control in Windows Forms
       Walkthrough: Binding to Data in Hybrid
       Applications
       11/21/2022 • 6 minutes to read • Edit Online
Binding a data source to a control is essential for providing users with access to underlying data, whether you
are using Windows Forms or WPF. This walkthrough shows how you can use data binding in hybrid applications
that include both Windows Forms and WPF controls.
Tasks illustrated in this walkthrough include:
   Creating the project.
   Defining the data template.
   Specifying the form layout.
   Specifying data bindings.
   Displaying data by using interoperation.
   Adding the data source to the project.
   Binding to the data source.
For a complete code listing of the tasks illustrated in this walkthrough, see Data Binding in Hybrid Applications
Sample.
When you are finished, you will have an understanding of data binding features in hybrid applications.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio.
   Access to the Northwind sample database running on Microsoft SQL Server.
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
5. Name the default Grid element     mainGrid    by assigning the Name property.
      <Grid x:Name="mainGrid">
      <Grid.Resources>
          <DataTemplate x:Key="ListItemsTemplate">
              <TextBlock Text="{Binding Path=ContactName}"/>
          </DataTemplate>
      </Grid.Resources>
      <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
          <ColumnDefinition Width="Auto"/>
          <ColumnDefinition Width="Auto"/>
          <ColumnDefinition Width="Auto"/>
      </Grid.ColumnDefinitions>
4. When you are prompted to choose your database objects, select the       Customers   and   Orders   tables, and
   name the generated data set NorthwindDataSet .
      public MainWindow()
      {
          InitializeComponent();
End Sub
4. Open MainWindow.xaml.
5. In Design view or XAML view, select the Window element.
6. In the Properties window, click the Events tab.
7. Double-click the Loaded event.
8. Copy the following code into the Loaded event handler.
  This code assigns the BindingSource component as the data context and populates the   Customers   and
   Orders adapter objects.
          BindingListCollectionView cv = CollectionViewSource.GetDefaultView(
              this.nwBindingSource) as BindingListCollectionView;
           Dim cv As BindingListCollectionView = _
               CollectionViewSource.GetDefaultView(Me.nwBindingSource)
End Sub
 See also
    ElementHost
WindowsFormsHost
Design XAML in Visual Studio
Data Binding in Hybrid Applications Sample
Walkthrough: Hosting a Windows Forms Composite Control in WPF
Walkthrough: Hosting a WPF Composite Control in Windows Forms
       Walkthrough: Host a 3D WPF Composite Control in
       Windows Forms
       11/21/2022 • 4 minutes to read • Edit Online
This walkthrough demonstrates how you can create a WPF composite control and host it in Windows Forms
controls and forms by using the ElementHost control.
In this walkthrough, you will implement a WPF UserControl that contains two child controls. The UserControl
displays a three-dimensional (3D) cone. Rendering 3D objects is much easier with the WPF than with Windows
Forms. Therefore, it makes sense to host a WPF UserControl class to create 3D graphics in Windows Forms.
Tasks illustrated in this walkthrough include:
   Creating the WPF UserControl.
   Creating the Windows Forms host project.
   Hosting the WPF UserControl.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio 2017
      <UserControl x:Class="HostingWpfUserControlInWf.UserControl1"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          >
<Grid>
          <ModelVisual3D>
            <ModelVisual3D.Content>
              <Model3DGroup >
                <Model3DGroup.Children>
                    <GeometryModel3D.Geometry>
                      <MeshGeometry3D
    Positions="0.293893 -0.5 0.404509 0.475528 -0.5 0.154509 0 0.5 0 0.475528 -0.5 0.154509 0 0.5
0 0 0.5 0 0.475528 -0.5 0.154509 0.475528 -0.5 -0.154509 0 0.5 0 0.475528 -0.5 -0.154509 0 0.5
0 0 0.5 0 0.475528 -0.5 -0.154509 0.293893 -0.5 -0.404509 0 0.5 0 0.293893 -0.5 -0.404509 0 0.5
0 0 0.5 0 0.293893 -0.5 -0.404509 0 -0.5 -0.5 0 0.5 0 0 -0.5 -0.5 0 0.5 0 0 0.5 0 0 -0.5 -0.5
-0.293893 -0.5 -0.404509 0 0.5 0 -0.293893 -0.5 -0.404509 0 0.5 0 0 0.5 0 -0.293893 -0.5 -
0.404509 -0.475528 -0.5 -0.154509 0 0.5 0 -0.475528 -0.5 -0.154509 0 0.5 0 0 0.5 0 -0.475528 -
0.5 -0.154509 -0.475528 -0.5 0.154509 0 0.5 0 -0.475528 -0.5 0.154509 0 0.5 0 0 0.5 0 -0.475528
-0.5 0.154509 -0.293892 -0.5 0.404509 0 0.5 0 -0.293892 -0.5 0.404509 0 0.5 0 0 0.5 0 -0.293892
-0.5 0.404509 0 -0.5 0.5 0 0.5 0 0 -0.5 0.5 0 0.5 0 0 0.5 0 0 -0.5 0.5 0.293893 -0.5 0.404509
0 0.5 0 0.293893 -0.5 0.404509 0 0.5 0 0 0.5 0 "
    Normals="0.7236065,0.4472139,0.5257313 0.2763934,0.4472138,0.8506507
0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 0,0.4294458,0.9030925
0.5308242,0.4294462,0.7306172 0.2763934,0.4472138,0.8506507 -0.2763934,0.4472138,0.8506507
0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.5308242,0.4294462,0.7306172
0,0.4294458,0.9030925 -0.2763934,0.4472138,0.8506507 -0.7236065,0.4472139,0.5257313 -
0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.858892,0.429446,0.279071 -
0.5308242,0.4294462,0.7306172 -0.7236065,0.4472139,0.5257313 -0.8944269,0.4472139,0 -
0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.858892,0.429446,-0.279071 -
0.858892,0.429446,0.279071 -0.8944269,0.4472139,0 -0.7236065,0.4472139,-0.5257313 -
0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.5308242,0.4294462,-0.7306172 -
0.858892,0.429446,-0.279071 -0.7236065,0.4472139,-0.5257313 -0.2763934,0.4472138,-0.8506507 -
0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0,0.4294458,-0.9030925 -
0.5308242,0.4294462,-0.7306172 -0.2763934,0.4472138,-0.8506507 0.2763934,0.4472138,-0.8506507
0,0.4294458,-0.9030925 0.2763934,0.4472138,-0.8506507 0.5308249,0.4294459,-0.7306169 0,0.4294458,-
0.9030925 0.2763934,0.4472138,-0.8506507 0.7236068,0.4472141,-0.5257306 0.5308249,0.4294459,-
0.7306169 0.7236068,0.4472141,-0.5257306 0.8588922,0.4294461,-0.27907 0.5308249,0.4294459,-
0.7306169 0.7236068,0.4472141,-0.5257306 0.8944269,0.4472139,0 0.8588922,0.4294461,-0.27907
0.8944269,0.4472139,0 0.858892,0.429446,0.279071 0.8588922,0.4294461,-0.27907
0.8944269,0.4472139,0 0.7236065,0.4472139,0.5257313 0.858892,0.429446,0.279071
0.7236065,0.4472139,0.5257313 0.5308242,0.4294462,0.7306172 0.858892,0.429446,0.279071 "
TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 " />
                    </GeometryModel3D.Geometry>
                       <GeometryModel3D.Material>
                         <DiffuseMaterial>
                           <DiffuseMaterial.Brush>
                             <SolidColorBrush
                               Color="Red"
                               Opacity="1.0"/>
                           </DiffuseMaterial.Brush>
                         </DiffuseMaterial>
                       </GeometryModel3D.Material>
                     </GeometryModel3D>
                         </Model3DGroup.Children>
                       </Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
            </Viewport3D>
          </Grid>
</UserControl>
   This code defines a System.Windows.Controls.UserControl that contains two child controls. The first child
   control is a System.Windows.Controls.Label control; the second is a Viewport3D control that displays a
   3D cone.
using System.Windows.Forms.Integration;
namespace WpfUserControlHost
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
Imports System.Windows.Forms.Integration
End Class
See also
   ElementHost
   WindowsFormsHost
   Design XAML in Visual Studio
   Walkthrough: Hosting a WPF Composite Control in Windows Forms
   Walkthrough: Hosting a Windows Forms Composite Control in WPF
   Hosting a WPF Composite Control in Windows Forms Sample
       Walkthrough: Hosting a WPF Composite Control in
       Windows Forms
       11/21/2022 • 16 minutes to read • Edit Online
WPF rather than to rewrite it from scratch. A common scenario is when you want to embed one or more
controls implemented with WPF within your Windows Forms application. For more information about
customizing WPF controls, see Control Customization.
This walkthrough steps you through an application that hosts a WPF composite control to perform data-entry in
a Windows Forms application. The composite control is packaged in a DLL. This general procedure can be
extended to more complex applications and controls. This walkthrough is designed to be nearly identical in
appearance and functionality to Walkthrough: Hosting a Windows Forms Composite Control in WPF. The
primary difference is that the hosting scenario is reversed.
The walkthrough is divided into two sections. The first section briefly describes the implementation of the WPF
composite control. The second section discusses in detail how to host the composite control in a Windows
Forms application, receive events from the control, and access some of the control's properties.
Tasks illustrated in this walkthrough include:
   Implementing the WPF composite control.
   Implementing the Windows Forms host application.
For a complete code listing of the tasks illustrated in this walkthrough, see Hosting a WPF Composite Control in
Windows Forms Sample.
Prerequisites
You need Visual Studio to complete this walkthrough.
     <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"    />
       <RowDefinition Height="Auto"    />
       <RowDefinition Height="Auto"    />
       <RowDefinition Height="Auto"    />
     </Grid.RowDefinitions>
</Grid>
     <TextBlock Grid.Column="0"
           Grid.Row="1"
           Style="{StaticResource inlineText}"
           Name="nameLabel">Name</TextBlock>
     <TextBox Grid.Column="1"
           Grid.Row="1"
           Grid.ColumnSpan="3"
           Name="txtName"/>
     <TextBlock Grid.Column="0"
           Grid.Row="2"
           Style="{StaticResource inlineText}"
           Name="addressLabel">Street Address</TextBlock>
     <TextBox Grid.Column="1"
           Grid.Row="2"
           Grid.ColumnSpan="3"
           Name="txtAddress"/>
     <TextBlock Grid.Column="0"
           Grid.Row="3"
           Style="{StaticResource inlineText}"
           Name="cityLabel">City</TextBlock>
     <TextBox Grid.Column="1"
           Grid.Row="3"
           Width="100"
           Name="txtCity"/>
     <TextBlock Grid.Column="2"
           Grid.Row="3"
           Style="{StaticResource inlineText}"
           Name="stateLabel">State</TextBlock>
     <TextBox Grid.Column="3"
           Grid.Row="3"
           Width="50"
           Name="txtState"/>
     <TextBlock Grid.Column="0"
           Grid.Row="4"
           Style="{StaticResource inlineText}"
           Name="zipLabel">Zip</TextBlock>
     <TextBox Grid.Column="1"
           Grid.Row="4"
           Width="100"
           Name="txtZip"/>
   <Grid.Resources>
     <Style x:Key="inlineText" TargetType="{x:Type TextBlock}">
       <Setter Property="Margin" Value="10,5,10,0"/>
       <Setter Property="FontWeight" Value="Normal"/>
       <Setter Property="FontSize" Value="12"/>
     </Style>
     <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
       <Setter Property="DockPanel.Dock" Value="Top"/>
       <Setter Property="FontWeight" Value="Bold"/>
       <Setter Property="FontSize" Value="14"/>
       <Setter Property="Margin" Value="10,5,10,0"/>
     </Style>
     <Style TargetType="{x:Type Button}">
       <Setter Property="Margin" Value="10,5,10,0"/>
       <Setter Property="Width" Value="60"/>
     </Style>
     <Style TargetType="{x:Type TextBox}">
       <Setter Property="Margin" Value="10,5,10,0"/>
     </Style>
   </Grid.Resources>
   <Button Grid.Row="5"
           Grid.Column="0"
           Name="btnOK"
           Click="ButtonClicked">OK</Button>
   <Button Grid.Row="5"
           Grid.Column="1"
           Name="btnCancel"
           Click="ButtonClicked">Cancel</Button>
   namespace MyControls
   {
     public partial class MyControl1 : Grid
     {
       //...
     }
     public class MyControlEventArgs : EventArgs
     {
       //...
     }
   }
The first class, MyControl1 , is a partial class containing the code that implements the functionality of the UI
defined in MyControl1.xaml. When MyControl1.xaml is parsed, the XAML is converted to the same partial class,
and the two partial classes are merged to form the compiled control. For this reason, the class name in the code-
behind file must match the class name assigned to MyControl1.xaml, and it must inherit from the root element
of the control. The second class, MyControlEventArgs , is an event arguments class that is used to send the data
back to the host.
Open MyControl1.xaml.cs. Change the existing class declaration so that it has the following name and inherits
from Grid.
Delete the existing constructor and add the following code to your         MyControl1   class.
   public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
   public event MyControlEventHandler OnButtonClick;
   private FontWeight _fontWeight;
   private double _fontSize;
   private FontFamily _fontFamily;
   private FontStyle _fontStyle;
   private SolidColorBrush _foreground;
   private SolidColorBrush _background;
Creating Properties
The remainder of the class simply exposes properties that correspond to the global variables discussed
previously. When a property changes, the set accessor modifies the appearance of the control by changing the
corresponding element properties and updating the underlying global variables.
Add the following code to your       MyControl1   class.
Build the solution. The build will produce a DLL named MyControls.dll.
NAME T EXT
groupBox3 radioSizeTen 10
groupBox3 radioSizeTwelve 12
   using System.Windows;
   using System.Windows.Forms.Integration;
   using System.Windows.Media;
Replace the contents of the existing   Form1   class with the following code.
   private ElementHost ctrlHost;
   private MyControls.MyControl1 wpfAddressCtrl;
   System.Windows.FontWeight initFontWeight;
   double initFontSize;
   System.Windows.FontStyle initFontStyle;
   System.Windows.Media.SolidColorBrush initBackBrush;
   System.Windows.Media.SolidColorBrush initForeBrush;
   System.Windows.Media.FontFamily initFontFamily;
   public Form1()
   {
       InitializeComponent();
   }
         wpfAddressCtrl.OnButtonClick +=
             new MyControls.MyControl1.MyControlEventHandler(
             avAddressCtrl_OnButtonClick);
         wpfAddressCtrl.Loaded += new RoutedEventHandler(
             avAddressCtrl_Loaded);
   }
The    Form1_Load   method in the preceding code shows the general procedure for hosting a WPF control:
1. Create a new ElementHost object.
2. Set the control's Dock property to DockStyle.Fill.
3. Add the ElementHost control to the Panel control's Controls collection.
4. Create an instance of the WPF control.
5. Host the composite control on the form by assigning the control to the ElementHost control's Child
   property.
The remaining two lines in the    Form1_Load   method attach handlers to two control events:
                 is a custom event that is fired by the composite control when the user clicks the OK or
      OnButtonClick
   Cancel button. You handle the event to get the user's response and to collect any data that the user
   specified.
   Loaded is a standard event that is raised by a WPF control when it is fully loaded. The event is used here
   because the example needs to initialize several global variables using properties from the control. At the
   time of the form's Load event, the control is not fully loaded and those values are still set to null . You
   need to wait until the control's Loaded event occurs before you can access those properties.
The Loaded event handler is shown in the preceding code. The       OnButtonClick   handler is discussed in the next
section.
Handling OnButtonClick
The OnButtonClick event occurs when the user clicks the OK or Cancel button.
The event handler checks the event argument's IsOK field to determine which button was clicked. The lbl data
variables correspond to the Label controls that were discussed earlier. If the user clicks the OK button, the data
from the control's TextBox controls is assigned to the corresponding Label control. If the user clicks Cancel , the
Text values are set to the default strings.
Add the following button click event handler code to the   Form1   class.
   void avAddressCtrl_OnButtonClick(
       object sender,
       MyControls.MyControl1.MyControlEventArgs args)
   {
       if (args.IsOK)
       {
            lblAddress.Text = "Street Address: " + args.MyStreetAddress;
            lblCity.Text = "City: " + args.MyCity;
            lblName.Text = "Name: " + args.MyName;
            lblState.Text = "State: " + args.MyState;
            lblZip.Text = "Zip: " + args.MyZip;
       }
       else
       {
            lblAddress.Text = "Street Address: ";
            lblCity.Text = "City: ";
            lblName.Text = "Name: ";
            lblState.Text = "State: ";
            lblZip.Text = "Zip: ";
       }
   }
Build and run the application. Add some text in the WPF composite control and then click OK . The text appears
in the labels. At this point, code has not been added to handle the radio buttons.
Modifying the Appearance of the Control
The RadioButton controls on the form will enable the user to change the WPF composite control's foreground
and background colors as well as several font properties. The background color is exposed by the ElementHost
object. The remaining properties are exposed as custom properties of the control.
Double-click each RadioButton control on the form to create CheckedChanged event handlers. Replace the
CheckedChanged event handlers with the following code.
Build and run the application. Click the different radio buttons to see the effect on the WPF composite control.
See also
 ElementHost
 WindowsFormsHost
 Design XAML in Visual Studio
 Walkthrough: Hosting a Windows Forms Composite Control in WPF
 Walkthrough: Hosting a 3D WPF Composite Control in Windows Forms
       Walkthrough: Mapping Properties Using the
       ElementHost Control
       11/21/2022 • 7 minutes to read • Edit Online
This walkthrough shows you how to use the PropertyMap property to map Windows Forms properties to
corresponding properties on a hosted WPF element.
Tasks illustrated in this walkthrough include:
   Creating the project.
   Defining a new property mapping.
   Removing a default property mapping.
   Extending a default property mapping.
When you are finished, you will be able to map Windows Forms properties to corresponding WPF properties on
a hosted element.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio 2017
      using   System.Windows;
      using   System.Windows.Media;
      using   System.Windows.Media.Imaging;
      using   System.Windows.Forms.Integration;
      Imports   System.Windows
      Imports   System.Windows.Media
      Imports   System.Windows.Media.Imaging
      Imports   System.Windows.Forms.Integration
4. Open     Form1   in the Windows Forms Designer. Double-click the form to add an event handler for the Load
   event.
5. Return to the Windows Forms Designer and add an event handler for the form's Resize event. For more
   information, see How to: Create Event Handlers Using the Designer.
6. Declare an ElementHost field in the    Form1   class.
            wpfButton.Margin = t;
      }
      ' The AddMarginMapping method adds a new property mapping
      ' for the Margin property.
      Private Sub AddMarginMapping()
           elemHost.PropertyMap.Add( _
               "Margin", _
               New PropertyTranslator(AddressOf OnMarginChange))
End Sub
wpfButton.Margin = t
End Sub
   The   AddMarginMapping   method adds a new mapping for the Margin property.
   The   OnMarginChange   method translates the Margin property to the WPF Margin property.
2. Copy the following code into the definition for the   Form1   class.
// The AddRegionMapping method assigns a custom
// mapping for the Region property.
private void AddRegionMapping()
{
    elemHost.PropertyMap.Add(
        "Region",
        new PropertyTranslator(OnRegionChange));
}
           elemHost.PropertyMap.Add( _
               "Region", _
               New PropertyTranslator(AddressOf OnRegionChange))
End Sub
End Sub
End Sub
   The   AddRegionMapping   method adds a new mapping for the Region property.
   The   OnRegionChange   method translates the Region property to the WPF Clip property.
   The Form1_Resize method handles the form's Resize event and sizes the clipping region to fit the hosted
   element.
The RemoveCursorMapping method deletes the default mapping for the Cursor property.
               elemHost.PropertyMap("BackColor") = PropertyTranslator.Combine( _
                   elemHost.PropertyMap("BackColor"), _
                   PropertyTranslator.CreateDelegate( _
                   GetType(PropertyTranslator), _
                   Me, _
                   "OnBackColorChange"))
           End If
End Sub
End Sub
   The ExtendBackColorMapping method adds a custom property translator to the existing BackColor
   property mapping.
   The   OnBackColorChangemethod assigns a specific image to the hosted control's Background property. The
   OnBackColorChange   method is called after the default property mapping is applied.
End Sub
   The   Form1_Load   method handles the Load event and performs the following initialization.
      Creates a WPF Button element.
      Calls the methods you defined earlier in the walkthrough to set up the property mappings.
      Assigns initial values to the mapped properties.
2. Press F5 to build and run the application.
See also
   ElementHost.PropertyMap
   WindowsFormsHost.PropertyMap
   WindowsFormsHost
   Windows Forms and WPF Property Mapping
   Design XAML in Visual Studio
   Walkthrough: Hosting a WPF Composite Control in Windows Forms
       Walkthrough: Mapping Properties Using the
       WindowsFormsHost Element
       11/21/2022 • 9 minutes to read • Edit Online
This walkthrough shows you how to use the PropertyMap property to map WPF properties to corresponding
properties on a hosted Windows Forms control.
Tasks illustrated in this walkthrough include:
   Creating the project.
   Defining the application layout.
   Defining a new property mapping.
   Removing a default property mapping.
   Replacing a default property mapping.
   Extending a default property mapping.
When you are finished, you will be able to map WPF properties to corresponding properties on a hosted
Windows Forms control.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio 2017
      using   System.Drawing;
      using   System.Drawing.Drawing2D;
      using   System.Windows.Forms;
      using   System.Windows.Forms.Integration;
      Imports   System.Drawing
      Imports   System.Drawing.Drawing2D
      Imports   System.Windows.Forms
      Imports   System.Windows.Forms.Integration
    if (cb != null)
    {
        cb.Region = this.CreateClipRegion();
    }
}
path.StartFigure();
    path.AddEllipse(new System.Drawing.Rectangle(
        0,
        0,
        (int)wfHost.ActualWidth,
        (int)wfHost.ActualHeight ) );
path.CloseFigure();
         wfHost.PropertyMap.Add( _
             "Clip", _
             New PropertyTranslator(AddressOf OnClipChange))
End Sub
End Sub
End Sub
path.StartFigure()
         path.AddEllipse(New System.Drawing.Rectangle( _
             0, _
             0, _
             wfHost.ActualWidth, _
             wfHost.ActualHeight))
path.CloseFigure()
End Function
 The   AddClipMapping   method adds a new mapping for the Clip property.
 The   OnClipChange   method translates the Clip property to the Windows FormsRegion property.
 The Window1_SizeChanged method handles the window's SizeChanged event and sizes the clipping region
 to fit the application window.
The RemoveCursorMapping method deletes the default mapping for the Cursor property.
    wfHost.PropertyMap.Add(
        "FlowDirection",
        new PropertyTranslator(OnFlowDirectionChange));
}
wfHost.PropertyMap.Remove("FlowDirection")
          wfHost.PropertyMap.Add( _
              "FlowDirection", _
              New PropertyTranslator(AddressOf OnFlowDirectionChange))
      End Sub
           Dim fd As System.Windows.FlowDirection = _
               CType(value, System.Windows.FlowDirection)
End Sub
End Sub
   The   ReplaceFlowDirectionMapping   method replaces the default mapping for the FlowDirection property.
   The OnFlowDirectionChange method translates the FlowDirection property to the Windows
   FormsRightToLeft property.
   The cb_CheckedChanged method handles the CheckedChanged event on the CheckBox control. It assigns
   the FlowDirection property based on the value of the CheckState property
       if (b != null)
       {
           cb.BackgroundImage = new System.Drawing.Bitmap(@"C:\WINDOWS\Santa Fe Stucco.bmp");
       }
   }
           wfHost.PropertyMap("Background") = PropertyTranslator.Combine( _
           wfHost.PropertyMap("Background"), _
           PropertyTranslator.CreateDelegate( _
               GetType(PropertyTranslator), _
               Me, _
               "OnBackgroundChange"))
       End If
End Sub
End Sub
The ExtendBackgroundMapping method adds a custom property translator to the existing Background
property mapping.
The OnBackgroundChange method assigns a specific image to the hosted control's BackgroundImage
property. The OnBackgroundChange method is called after the default property mapping is applied.
Initializing Your Property Mappings
Set up your property mappings by calling the previously described methods in the Loaded event handler.
To initialize your property mappings
1. Copy the following code into the definition for the   Window1   class.
System.Windows.Forms.Application.EnableVisualStyles()
End Sub
   The   WindowLoaded   method handles the Loaded event and performs the following initialization.
      Creates a Windows FormsCheckBox control.
      Calls the methods you defined earlier in the walkthrough to set up the property mappings.
      Assigns initial values to the mapped properties.
2. Press F5 to build and run the application. Click the check box to see the effect of the FlowDirection
   mapping. When you click the check box, the layout reverses its left-right orientation.
See also
   WindowsFormsHost.PropertyMap
   ElementHost.PropertyMap
   WindowsFormsHost
   Windows Forms and WPF Property Mapping
   Design XAML in Visual Studio
Walkthrough: Hosting a Windows Forms Control in WPF
       Walkthrough: Localizing a Hybrid Application
       11/21/2022 • 4 minutes to read • Edit Online
This walkthrough shows you how to localize WPF elements in a Windows Forms-based hybrid application.
Tasks illustrated in this walkthrough include:
   Creating the Windows Forms host project.
   Adding localizable content.
   Enabling localization.
   Assigning resource identifiers.
   Using the LocBaml tool to produce a satellite assembly.
For a complete code listing of the tasks illustrated in this walkthrough, see Localizing a Hybrid Application
Sample.
When you are finished, you will have a localized hybrid application.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio 2017
         <Canvas>
           <Button Content="Hello"/>
         </Canvas>
       </UserControl>
 Enabling Localization
 The Windows Forms Designer provides settings for enabling localization in a satellite assembly.
 To enable localization
 1. In Solution Explorer , double-click Form1.cs to open it in the Windows Forms Designer.
 2. In the Proper ties window, set the value of the form's Localizable property to           true   .
 3. In the Proper ties window, set the value of the Language property to Spanish (Spain) .
 4. In the Windows Forms Designer, select the label control.
 5. In the Proper ties window, set the value of the Text property to       "Hola"   .
    A new resource file named Form1.es-ES.resx is added to the project.
 6. In Solution Explorer , right-click Form1.cs and click View Code to open it in the Code Editor.
 7. Copy the following code into the    Form1    constructor, preceding the call to     InitializeComponent   .
       public Form1()
       {
           System.Threading.Thread.CurrentThread.CurrentUICulture = new
       System.Globalization.CultureInfo("es-ES");
            InitializeComponent();
       }
       <UICulture>en-US</UICulture>
11. Save the project file and close it.
12. In Solution Explorer , right-click LocalizingWpfInWf and click Reload Project .
 3. In Solution Explorer , double-click SimpleControl.xaml to open it in the Code Editor. You will see that
    the msbuild command has added the Uid attribute to all the elements. This facilitates localization
    through the assignment of resource identifiers.
          <Canvas x:Uid="Canvas_1">
            <Button x:Uid="Button_1" Content="Hello"/>
          </Canvas>
        </UserControl>
 3. Open the temp.csv file with Visual Studio or another text editor. Replace the string   "Hello"   with its
    Spanish translation, "Hola" .
 4. Save the temp.csv file.
 5. Use the following command to generate the localized resource file.
See also
   ElementHost
   WindowsFormsHost
   Localize an Application
   Walkthrough: Localizing Windows Forms
   Design XAML in Visual Studio
       WPF and Win32 Interoperation
       11/21/2022 • 10 minutes to read • Edit Online
This topic provides an overview of how to interoperate WPF and Win32 code. Windows Presentation
Foundation (WPF) provides a rich environment for creating applications. However, when you have a substantial
investment in Win32 code, it might be more effective to reuse some of that code.
  NOTE
  If you have not used C++/CLI before, you might notice some "new" keywords such as gcnew and nullptr in the
  interoperation code examples. These keywords supersede the older double-underscore syntax ( __gc ) and provide a
  more natural syntax for managed code in C++. To learn more about the C++/CLI managed features, see Component
  Extensions for Runtime Platforms.
How WPF Uses Hwnds
To make the most of WPF "HWND interop", you need to understand how WPF uses HWNDs. For any HWND,
you cannot mix WPF rendering with DirectX rendering or GDI / GDI+ rendering. This has a number of
implications. Primarily, in order to mix these rendering models at all, you must create an interoperation solution,
and use designated segments of interoperation for each rendering model that you choose to use. Also, the
rendering behavior creates an "airspace" restriction for what your interoperation solution can accomplish. The
"airspace" concept is explained in greater detail in the topic Technology Regions Overview.
All WPF elements on the screen are ultimately backed by a HWND. When you create a WPF Window, WPF
creates a top-level HWND, and uses an HwndSource to put the Window and its WPF content inside the HWND.
The rest of your WPF content in the application shares that singular HWND. An exception is menus, combo box
drop downs, and other pop-ups. These elements create their own top-level window, which is why a WPF menu
can potentially go past the edge of the window HWND that contains it. When you use HwndHost to put an
HWND inside WPF, WPF informs Win32 how to position the new child HWND relative to the WPF Window
HWND.
A related concept to HWND is transparency within and between each HWND. This is also discussed in the topic
Technology Regions Overview.
  NOTE
  You can do some or all of the WPF content class definition for Step One in XAML using the default partial class of the
  content class, if you produce a separate assembly and then reference it. Although you typically include an Application
  object as part of compiling the XAML into an assembly, you do not end up using that Application as part of the
  interoperation, you just use one or more of the root classes for XAML files referred to by the application and reference
  their partial classes. The remainder of the procedure is essentially similar to that outlined above.
  Each of these steps is illustrated through code in the topic Walkthrough: Hosting WPF Content in Win32.
See also
   HwndHost
   HwndSource
   System.Windows.Interop
   Walkthrough: Hosting a Win32 Control in WPF
   Walkthrough: Hosting WPF Content in Win32
       Technology Regions Overview
       11/21/2022 • 3 minutes to read • Edit Online
If multiple presentation technologies are used in an application, such as WPF, Win32, or DirectX, they must share
the rendering areas within a common top-level window. This topic describes issues that might influence the
presentation and input for your WPF interoperation application.
Regions
Within a top-level window, you can conceptualize that each HWND that comprises one of the technologies of an
interoperation application has its own region (also called "airspace"). Each pixel within the window belongs to
exactly one HWND, which constitutes the region of that HWND. (Strictly speaking, there is more than one WPF
region if there is more than one WPF HWND, but for purposes of this discussion, you can assume there is only
one). The region implies that all layers or other windows that attempt to render above that pixel during
application lifetime must be part of the same render-level technology. Attempting to render WPF pixels over
Win32 leads to undesirable results, and is disallowed as much as possible through the interoperation APIs.
Region Examples
The following illustration shows an application that mixes Win32, DirectX, and WPF. Each technology uses its
own separate, non-overlapping set of pixels, and there are no region issues.
Suppose that this application uses the mouse pointer position to create an animation that attempts to render
over any of these three regions. No matter which technology was responsible for the animation itself, that
technology would violate the region of the other two. The following illustration shows an attempt to render a
WPF circle over a Win32 region.
Another violation is if you try to use transparency/alpha blending between different technologies. In the
following illustration, the WPF box violates the Win32 and DirectX regions. Because pixels in that WPF box are
semi-transparent, they would have to be owned jointly by both DirectX and WPF, which is not possible. So this is
another violation and cannot be built.
The previous three examples used rectangular regions, but different shapes are possible. For example, a region
can have a hole. The following illustration shows a Win32 region with a rectangular hole this is the size of the
WPF and DirectX regions combined.
Regions can also be completely nonrectangular, or any shape describable by a Win32 HRGN (region).
See also
   WPF and Win32 Interoperation
   Walkthrough: Hosting a WPF Clock in Win32
   Hosting Win32 Content in WPF
      Sharing Message Loops Between Win32 and WPF
      11/21/2022 • 4 minutes to read • Edit Online
This topic describes how to implement a message loop for interoperation with Windows Presentation
Foundation (WPF), either by using existing message loop exposure in Dispatcher or by creating a separate
message loop on the Win32 side of your interoperation code.
See also
   ComponentDispatcher
   IKeyboardInputSink
   WPF and Win32 Interoperation
   Threading Model
   Input Overview
       Hosting Win32 Content in WPF
       11/21/2022 • 8 minutes to read • Edit Online
Prerequisites
See WPF and Win32 Interoperation.
But suppose the Win32 code is not quite so self-contained? If so, you can create a Win32 dialog box and embed
its contents into a larger WPF application. The sample shows this in Visual Studio and C++, although it is also
possible to do this in a different language or at the command line.
Start with a simple dialog, which is compiled into a C++ DLL project.
Next, introduce the dialog into the larger WPF application:
   Compile the DLL as managed ( /clr )
   Turn the dialog into a control
   Define the derived class of HwndHost with     BuildWindowCore   and   DestroyWindowCore   methods
   Override   TranslateAccelerator   method to handle dialog keys
   Override   TabInto   method to support tabbing
   Override   OnMnemonic   method to support mnemonics
   Instantiate the HwndHost subclass and put it under the right WPF element
Turn the Dialog into a Control
You can turn a dialog box into a child HWND using the WS_CHILD and DS_CONTROL styles. Go into the
resource file (.rc) where the dialog is defined, and find the beginning of the definition of the dialog:
This action does not fully package it into a self-contained control; you still need to call IsDialogMessage() so
Win32 can process certain messages, but the control change does provide a straightforward way of putting
those controls inside another HWND.
Subclass HwndHost
Import the following namespaces:
   namespace   ManagedCpp
   {
       using   namespace    System;
       using   namespace    System::Windows;
       using   namespace    System::Windows::Interop;
       using   namespace    System::Windows::Input;
       using   namespace    System::Windows::Media;
       using   namespace    System::Runtime::InteropServices;
Then create a derived class of HwndHost and override the BuildWindowCore and DestroyWindowCore methods:
       protected:
           virtual HandleRef BuildWindowCore(HandleRef hwndParent) override {
               InitializeGlobals();
               dialog = CreateDialog(hInstance,
                   MAKEINTRESOURCE(IDD_DIALOG1),
                   (HWND) hwndParent.Handle.ToPointer(),
                   (DLGPROC) About);
               return HandleRef(this, IntPtr(dialog));
           }
Here you use the CreateDialog to create the dialog box that is really a control. Since this is one of the first
methods called inside the DLL, you should also do some standard Win32 initialization by calling a function you
will define later, called InitializeGlobals() :
   bool initialized = false;
       void InitializeGlobals() {
           if (initialized) return;
           initialized = true;
               // Win32's IsDialogMessage() will handle most of our tabbing, but doesn't know
               // what to do when it reaches the last tab stop
               if (m.message == WM_KEYDOWN && m.wParam == VK_TAB) {
                   HWND firstTabStop = GetDlgItem(dialog, IDC_EDIT1);
                   HWND lastTabStop = GetDlgItem(dialog, IDCANCEL);
                   TraversalRequest^ request = nullptr;
                   if (request != nullptr)
                       return ((IKeyboardInputSink^) this)->KeyboardInputSite->OnNoMoreTabStops(request);
This is a lot of code in one piece, so it could use some more detailed explanations. First, the code using C++ and
C++ macros; you need to be aware that there is already a macro named TranslateAccelerator , which is defined
in winuser.h:
Both MSGs have the same data, but sometimes it is easier to work with the unmanaged definition, so in this
sample you can define the obvious conversion routine:
m.time = msg.time;
       POINT pt;
       pt.x = msg.pt_x;
       pt.y = msg.pt_y;
       m.pt = pt;
       return m;
   }
Back to TranslateAccelerator . The basic principle is to call the Win32 function IsDialogMessage to do as much
work as possible, but IsDialogMessage does not have access to anything outside the dialog. As a user tab
around the dialog, when tabbing runs past the last control in our dialog, you need to set focus to the WPF
portion by calling IKeyboardInputSite::OnNoMoreStops .
   // Win32's IsDialogMessage() will handle most of the tabbing, but doesn't know
   // what to do when it reaches the last tab stop
   if (m.message == WM_KEYDOWN && m.wParam == VK_TAB) {
       HWND firstTabStop = GetDlgItem(dialog, IDC_EDIT1);
       HWND lastTabStop = GetDlgItem(dialog, IDCANCEL);
       TraversalRequest^ request = nullptr;
       if (request != nullptr)
           return ((IKeyboardInputSink^) this)->KeyboardInputSite->OnNoMoreTabStops(request);
   }
Finally, call IsDialogMessage . But one of the responsibilities of a TranslateAccelerator method is telling WPF
whether you handled the keystroke or not. If you did not handle it, the input event can tunnel and bubble
through the rest of the application. Here, you will expose a quirk of keyboard messange handling and the nature
of the input architecture in Win32. Unfortunately, IsDialogMessage does not return in any way whether it
handles a particular keystroke. Even worse, it will call DispatchMessage() on keystrokes it should not handle! So
you will have to reverse-engineer IsDialogMessage , and only call it for the keys you know it will handle:
   // Only call IsDialogMessage for keys it will do something with.
   if (msg.message == WM_SYSKEYDOWN || msg.message == WM_KEYDOWN) {
       switch (m.wParam) {
           case VK_TAB:
           case VK_LEFT:
           case VK_UP:
           case VK_RIGHT:
           case VK_DOWN:
           case VK_EXECUTE:
           case VK_RETURN:
           case VK_ESCAPE:
           case VK_CANCEL:
               IsDialogMessage(dialog, &m);
               // IsDialogMessage should be called ProcessDialogMessage --
               // it processes messages without ever really telling you
               // if it handled a specific message or not
               return true;
       }
   public:
       virtual bool TabInto(TraversalRequest^ request) override {
           if (request->FocusNavigationDirection == FocusNavigationDirection::Last) {
               HWND lastTabStop = GetDlgItem(dialog, IDCANCEL);
               SetFocus(lastTabStop);
           }
           else {
               HWND firstTabStop = GetDlgItem(dialog, IDC_EDIT1);
               SetFocus(firstTabStop);
           }
           return true;
       }
The   TraversalRequest   parameter tells you whether the tab action is a tab or shift tab.
Override OnMnemonic Method to Support Mnemonics
Keyboard handling is almost complete, but there is one thing missing – mnemonics do not work. If a user
presses alt-F, focus doe not jump to the "First name:" edit box. So, you override the OnMnemonic method:
   virtual bool OnMnemonic(System::Windows::Interop::MSG% msg, ModifierKeys modifiers) override {
       ::MSG m = ConvertMessage(msg);
Why not call IsDialogMessage here? You have the same issue as before--you need to be able to inform WPF
code whether your code handled the keystroke or not, and IsDialogMessage cannot do that. There is also a
second issue, because IsDialogMessage refuses to process the mnemonic if the focused HWND is not inside the
dialog box.
Instantiate the HwndHost Derived Class
Finally, now that all the key and tab support is in place, you can put your HwndHost into the larger WPF
application. If the main application is written in XAML, the easiest way to put it in the right place is to leave an
empty Border element where you want to put the HwndHost. Here you create a Border named
 insertHwndHostHere :
   <Window x:Class="WPFApplication1.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="Windows Presentation Framework Application"
       Loaded="Window1_Loaded"
       >
       <StackPanel>
           <Button Content="WPF button"/>
           <Border Name="insertHwndHostHere" Height="200" Width="500"/>
           <Button Content="WPF button"/>
       </StackPanel>
   </Window>
Then all that remains is to find a good place in code sequence to instantiate the HwndHost and connect it to the
Border. In this example, you will put it inside the constructor for the Window derived class:
  public partial class Window1 : Window {
      public Window1() {
      }
See also
  WPF and Win32 Interoperation
       Walkthrough: Host a Win32 Control in WPF
       11/21/2022 • 16 minutes to read • Edit Online
Windows Presentation Foundation (WPF) provides a rich environment for creating applications. However, when
you have a substantial investment in Win32 code, it may be more effective to reuse at least some of that code in
your WPF application rather than rewrite it completely. WPF provides a straightforward mechanism for hosting
a Win32 window, on a WPF page.
This topic walks you through an application, Hosting a Win32 ListBox Control in WPF Sample, that hosts a
Win32 list box control. This general procedure can be extended to hosting any Win32 window.
Requirements
This topic assumes a basic familiarity with both WPF and Windows API programming. For a basic introduction
to WPF programming, see Getting Started. For an introduction to Windows API programming, see any of the
numerous books on the subject, in particular Programming Windows by Charles Petzold.
Because the sample that accompanies this topic is implemented in C#, it makes use of Platform Invocation
Services (PInvoke) to access the Windows API. Some familiarity with PInvoke is helpful but not essential.
  NOTE
  This topic includes a number of code examples from the associated sample. However, for readability, it does not include
  the complete sample code. You can obtain or view complete code from Hosting a Win32 ListBox Control in WPF Sample.
   <DockPanel Background="LightGreen">
     <Border Name="ControlHostElement"
     Width="200"
     Height="200"
     HorizontalAlignment="Right"
     VerticalAlignment="Top"
     BorderBrush="LightGray"
     BorderThickness="3"
     DockPanel.Dock="Right"/>
     <StackPanel>
       <Label HorizontalAlignment="Center"
         Margin="0,10,0,0"
         FontSize="14"
         FontWeight="Bold">Control the Control</Label>
       <TextBlock Margin="10,10,10,10" >Selected Text: <TextBlock Name="selectedText"/></TextBlock>
       <TextBlock Margin="10,10,10,10" >Number of Items: <TextBlock Name="numItems"/></TextBlock>
       <Label HorizontalAlignment="Center"
         Margin="10,10,10,10">Append an Item to the List</Label>
       <StackPanel Orientation="Horizontal">
         <Label HorizontalAlignment="Left"
           Margin="10,10,10,10">Item Text</Label>
         <TextBox HorizontalAlignment="Left"
           Name="txtAppend"
           Width="200"
           Margin="10,10,10,10"></TextBox>
       </StackPanel>
       <Button HorizontalAlignment="Left"
         Click="AppendText"
         Width="75"
         Margin="10,10,10,10">Append</Button>
       <Label HorizontalAlignment="Center"
         Margin="10,10,10,10">Delete the Selected Item</Label>
       <Button Click="DeleteText"
         Width="125"
         Margin="10,10,10,10"
         HorizontalAlignment="Left">Delete</Button>
     </StackPanel>
   </DockPanel>
 </Window>
There is also a set of constants. These constants are largely taken from Winuser.h, and allow you to use
conventional names when calling Win32 functions.
   Friend Const WS_CHILD As Integer = &H40000000, WS_VISIBLE As Integer = &H10000000, LBS_NOTIFY As Integer =
   &H00000001, HOST_ID As Integer = &H00000002, LISTBOX_ID As Integer = &H00000001, WS_VSCROLL As Integer =
   &H00200000, WS_BORDER As Integer = &H00800000
The ListBox control is created as a child of the host window. The height and width of both windows are set to the
values passed to the constructor, discussed above. This ensures that the size of the host window and control is
identical to the reserved area on the page. After the windows are created, the sample returns a HandleRef object
that contains the HWND of the host window.
   //PInvoke declarations
   [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
   internal static extern IntPtr CreateWindowEx(int dwExStyle,
                                                 string lpszClassName,
                                                 string lpszWindowName,
                                                 int style,
                                                 int x, int y,
                                                 int width, int height,
                                                 IntPtr hwndParent,
                                                 IntPtr hMenu,
                                                 IntPtr hInst,
                                                 [MarshalAs(UnmanagedType.AsAny)] object pvParam);
   'PInvoke declarations
   <DllImport("user32.dll", EntryPoint := "CreateWindowEx", CharSet := CharSet.Unicode)>
   Friend Shared Function CreateWindowEx(ByVal dwExStyle As Integer, ByVal lpszClassName As String, ByVal
   lpszWindowName As String, ByVal style As Integer, ByVal x As Integer, ByVal y As Integer, ByVal width As
   Integer, ByVal height As Integer, ByVal hwndParent As IntPtr, ByVal hMenu As IntPtr, ByVal hInst As IntPtr,
   <MarshalAs(UnmanagedType.AsAny)> ByVal pvParam As Object) As IntPtr
   End Function
   protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
   {
     handled = false;
     return IntPtr.Zero;
   }
  NOTE
  Notice that there are two PInvoke declarations for SendMessage. This is necessary because one uses the wParam
  parameter to pass a string and the other uses it to pass an integer. You need a separate declaration for each signature to
  ensure that the data is marshaled correctly.
public partial class HostWindow : Window
{
int selectedItem;
IntPtr hwndListBox;
ControlHost listControl;
Application app;
Window myWindow;
int itemCount;
  handled = false;
  if (msg == WM_COMMAND)
  {
    switch ((uint)wParam.ToInt32() >> 16 & 0xFFFF) //extract the HIWORD
    {
      case LBN_SELCHANGE : //Get the item text and display it
        selectedItem = SendMessage(listControl.hwndListBox, LB_GETCURSEL, IntPtr.Zero, IntPtr.Zero);
        textLength = SendMessage(listControl.hwndListBox, LB_GETTEXTLEN, IntPtr.Zero, IntPtr.Zero);
        StringBuilder itemText = new StringBuilder();
        SendMessage(hwndListBox, LB_GETTEXT, selectedItem, itemText);
        selectedText.Text = itemText.ToString();
        handled = true;
        break;
    }
  }
  return IntPtr.Zero;
}
internal const int
  LBN_SELCHANGE = 0x00000001,
  WM_COMMAND = 0x00000111,
  LB_GETCURSEL = 0x00000188,
  LB_GETTEXTLEN = 0x0000018A,
  LB_ADDSTRING = 0x00000180,
  LB_GETTEXT = 0x00000189,
  LB_DELETESTRING = 0x00000182,
  LB_GETCOUNT = 0x0000018B;
       handled = False
       If msg = WM_COMMAND Then
           Select Case CUInt(wParam.ToInt32()) >> 16 And &HFFFF 'extract the HIWORD
                Case LBN_SELCHANGE 'Get the item text and display it
                    selectedItem = SendMessage(listControl.hwndListBox, LB_GETCURSEL, IntPtr.Zero, IntPtr.Zero)
                    textLength = SendMessage(listControl.hwndListBox, LB_GETTEXTLEN, IntPtr.Zero, IntPtr.Zero)
                    Dim itemText As New StringBuilder()
                    SendMessage(hwndListBox, LB_GETTEXT, selectedItem, itemText)
                    selectedText.Text = itemText.ToString()
                    handled = True
           End Select
       End If
       Return IntPtr.Zero
   End Function
   Friend Const LBN_SELCHANGE As Integer = &H1, WM_COMMAND As Integer = &H111, LB_GETCURSEL As Integer = &H188,
   LB_GETTEXTLEN As Integer = &H18A, LB_ADDSTRING As Integer = &H180, LB_GETTEXT As Integer = &H189,
   LB_DELETESTRING As Integer = &H182, LB_GETCOUNT As Integer = &H18B
When the user selects an item or changes their selection, the control notifies the host window by sending it a
 WM_COMMAND message, which raises the MessageHook event for the page. The handler receives the same
information as the main window procedure of the host window. It also passes a reference to a Boolean value,
 handled . You set handled to true to indicate that you have handled the message and no further processing is
needed.
 WM_COMMAND is sent for a variety of reasons, so you must examine the notification ID to determine whether it is
an event that you wish to handle. The ID is contained in the high word of the wParam parameter. The sample
uses bitwise operators to extract the ID. If the user has made or changed their selection, the ID will be
 LBN_SELCHANGE .
When    LBN_SELCHANGE  is received, the sample gets the index of the selected item by sending the control a
 LB_GETCURSEL message. To get the text, you first create a StringBuilder. You then send the control an LB_GETTEXT
message. Pass the empty StringBuilder object as the wParam parameter. When SendMessage returns, the
StringBuilder will contain the text of the selected item. This use of SendMessage requires yet another PInvoke
declaration.
Finally, set   handled   to   true   to indicate that the message has been handled.
See also
   HwndHost
   WPF and Win32 Interoperation
Walkthrough: My first WPF desktop application
       Walkthrough: Hosting WPF Content in Win32
       11/21/2022 • 15 minutes to read • Edit Online
WPF functionality to your application rather than rewriting your original code. WPF provides a straightforward
mechanism for hosting WPF content in a Win32 window.
This tutorial describes how to write a sample application, Hosting WPF Content in a Win32 Window Sample, that
hosts WPF content in a Win32 window. You can extend this sample to host any Win32 window. Because it
involves mixing managed and unmanaged code, the application is written in C++/CLI.
Requirements
This tutorial assumes a basic familiarity with both WPF and Win32 programming. For a basic introduction to
WPF programming, see Getting Started. For an introduction to Win32 programming, you should reference any
of the numerous books on the subject, in particular Programming Windows by Charles Petzold.
Because the sample that accompanies this tutorial is implemented in C++/CLI, this tutorial assumes familiarity
with the use of C++ to program the Windows API plus an understanding of managed code programming.
Familiarity with C++/CLI is helpful but not essential.
  NOTE
  This tutorial includes a number of code examples from the associated sample. However, for readability, it does not include
  the complete sample code. For the complete sample code, see Hosting WPF Content in a Win32 Window Sample.
  NOTE
  You can also use WPF content. However, you will have to compile it separately as a dynamic-link library (DLL) and
  reference that DLL from your Win32 application. The remainder of the procedure is similar to that outlined above.
  NOTE
  This compiler flag allows you to use managed code in your application, but your unmanaged code will still compile as
  before.
WPF uses the single-threaded apartment (STA) threading model. In order to work properly with the WPF content
code, you must set the application's threading model to STA by applying an attribute to the entry point.
   case WM_CREATE :
     GetClientRect(hWnd, &rect);
     wpfHwnd = GetHwnd(hWnd, rect.right-375, 0, 375, 250);
     CreateDataDisplay(hWnd, 275, rect.right-375, 375);
     CreateRadioButtons(hWnd);
   break;
The GetHwnd method takes size and position information plus the parent window handle and returns the
window handle of the hosted WPF content.
  NOTE
  You cannot use a #using directive for the System::Windows::Interop namespace. Doing so creates a name collision
  between the MSG structure in that namespace and the MSG structure declared in winuser.h. You must instead use fully-
  qualified names to access the contents of that namespace.
   HWND GetHwnd(HWND parent, int x, int y, int width, int height)
   {
       System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew
   System::Windows::Interop::HwndSourceParameters(
       "hi" // NAME
       );
       sourceParams->PositionX = x;
       sourceParams->PositionY = y;
       sourceParams->Height = height;
       sourceParams->Width = width;
       sourceParams->ParentWindow = IntPtr(parent);
       sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD; // style
       System::Windows::Interop::HwndSource^ source = gcnew
   System::Windows::Interop::HwndSource(*sourceParams);
       WPFPage ^myPage = gcnew WPFPage(width, height);
       //Assign a reference to the WPF page and a set of UI properties to a set of static properties in a class
       //that is designed for that purpose.
       WPFPageHost::hostedPage = myPage;
       WPFPageHost::initBackBrush = myPage->Background;
       WPFPageHost::initFontFamily = myPage->DefaultFontFamily;
       WPFPageHost::initFontSize = myPage->DefaultFontSize;
       WPFPageHost::initFontStyle = myPage->DefaultFontStyle;
       WPFPageHost::initFontWeight = myPage->DefaultFontWeight;
       WPFPageHost::initForeBrush = myPage->DefaultForeBrush;
       myPage->OnButtonClicked += gcnew WPFPage::ButtonClickHandler(WPFButtonClicked);
       source->RootVisual = myPage;
       return (HWND) source->Handle.ToPointer();
   }
You cannot host the WPF content directly in your application window. Instead, you first create an HwndSource
object to wrap the WPF content. This object is basically a window that is designed to host a WPF content. You
host the HwndSource object in the parent window by creating it as a child of a Win32 window that is part of
your application. The HwndSource constructor parameters contain much the same information that you would
pass to CreateWindow when you create a Win32 child window.
You next create an instance of the WPF content object. In this case, the WPF content is implemented as a
separate class, WPFPage , using C++/CLI. You could also implement the WPF content with WPF content as a DLL.
You can add a reference to that DLL to your project, and use that reference to create an instance of the WPF
content.
You display the WPF content in your child window by assigning a reference to the WPF content to the RootVisual
property of the HwndSource.
The next line of code attaches an event handler, WPFButtonClicked , to the WPF content OnButtonClicked event.
This handler is called when the user clicks the OK or Cancel button. See communicating_with_the_WPF content
for further discussion of this event handler.
The final line of code shown returns the window handle (HWND) that is associated with the HwndSource object.
You can use this handle from your Win32 code to send messages to the hosted window, although the sample
does not do so. The HwndSource object raises an event every time it receives a message. To process the
messages, call the AddHook method to attach a message handler and then process the messages in that handler.
The latter part of the GetHwnd function assigns values to those fields for later use while myPage is still in scope.
The handler receives a custom event argument object from the WPF content, MyPageEventArgs . The object's
 IsOK property is set to true if the OK button was clicked, and false if the Cancel button was clicked.
If the OK button was clicked, the handler gets a reference to the WPF content from the container class. It then
collects the user information that is held by the associated WPF content properties and uses the static controls
to display the information on the parent window. Because the WPF content data is in the form of a managed
string, it has to be marshaled for use by a Win32 control. If the Cancel button was clicked, the handler clears the
data from the static controls.
The application UI provides a set of radio buttons that allow the user to modify the background color of the WPF
content, and several font-related properties. The following example is an excerpt from the application's window
procedure (WndProc) and its message handling that sets various properties on different messages, including
the background color. The others are similar, and are not shown. See the complete sample for details and
context.
   case WM_COMMAND:
     wmId    = LOWORD(wParam);
     wmEvent = HIWORD(wParam);
     switch (wmId)
     {
     //Menu selections
       case IDM_ABOUT:
         DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
       break;
       case IDM_EXIT:
         DestroyWindow(hWnd);
       break;
       //RadioButtons
       case IDC_ORIGINALBACKGROUND :
         WPFPageHost::hostedPage->Background = WPFPageHost::initBackBrush;
       break;
       case IDC_LIGHTGREENBACKGROUND :
         WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightGreen);
       break;
       case IDC_LIGHTSALMONBACKGROUND :
         WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightSalmon);
       break;
To set the background color, get a reference to the WPF content ( hostedPage ) from WPFPageHost and set the
background color property to the appropriate color. The sample uses three color options: the original color, light
green, or light salmon. The original background color is stored as a static field in the WPFPageHost class. To set
the other two, you create a new SolidColorBrush object and pass the constructor a static colors value from the
Colors object.
Layout
The UI elements in the WPF content consist of five TextBox controls, with associated Label controls: Name,
Address, City, State, and Zip. There are also two Button controls, OK and Cancel
The WPF content is implemented in the WPFPage class. Layout is handled with a Grid layout element. The class
inherits from Grid, which effectively makes it the WPF content root element.
The WPF content constructor takes the required width and height, and sizes the Grid accordingly. It then defines
the basic layout by creating a set of ColumnDefinition and RowDefinition objects and adding them to the Grid
object base ColumnDefinitions and RowDefinitions collections, respectively. This defines a grid of five rows and
seven columns, with the dimensions determined by the contents of the cells.
   WPFPage::WPFPage(int allottedWidth, int allotedHeight)
   {
     array<ColumnDefinition ^> ^ columnDef = gcnew array<ColumnDefinition ^> (4);
     array<RowDefinition ^> ^ rowDef = gcnew array<RowDefinition ^> (6);
     this->Height = allotedHeight;
     this->Width = allottedWidth;
     this->Background = gcnew SolidColorBrush(Colors::LightGray);
Next, the constructor adds the UI elements to the Grid. The first element is the title text, which is a Label control
that is centered in the first row of the grid.
The next row contains the Name Label control and its associated TextBox control. Because the same code is used
for each label/textbox pair, it is placed in a pair of private methods and used for all five label/textbox pairs. The
methods create the appropriate control, and call the Grid class static SetColumn and SetRow methods to place
the controls in the appropriate cell. After the control is created, the sample calls the Add method on the Children
property of the Grid to add the control to the grid. The code to add the remaining label/textbox pairs is similar.
See the sample code for details.
Finally, the sample adds the OK and Cancel buttons and attaches an event handler to their Click events.
   public:
     delegate void ButtonClickHandler(Object ^, MyPageEventArgs ^);
     WPFPage();
     WPFPage(int height, int width);
     event ButtonClickHandler ^OnButtonClicked;
From WPFPage.cpp:
See also
   HwndSource
   WPF and Win32 Interoperation
       Walkthrough: Host a WPF Clock in Win32
       11/21/2022 • 8 minutes to read • Edit Online
To put WPF inside Win32 applications, use HwndSource, which provides the HWND that contains your WPF
content. First you create the HwndSource, giving it parameters similar to CreateWindow. Then you tell the
HwndSource about the WPF content you want inside it. Finally, you get the HWND out of the HwndSource. This
walkthrough illustrates how to create a mixed WPF inside Win32 application that reimplements the operating
system Date and Time Proper ties dialog.
Prerequisites
See WPF and Win32 Interoperation.
You can recreate this dialog by creating a C++ Win32 project in Visual Studio, and using the dialog editor to
create the following:
(You do not need to use Visual Studio to use HwndSource, and you do not need to use C++ to write Win32
programs, but this is a fairly typical way to do it, and lends itself well to a stepwise tutorial explanation).
You need to accomplish five particular substeps in order to put a WPF clock into the dialog:
1. Enable your Win32 project to call managed code (/clr ) by changing project settings in Visual Studio.
2. Create a WPFPage in a separate DLL.
3. Put that WPFPage inside an HwndSource.
4. Get an HWND for that Page using the Handle property.
5. Use Win32 to decide where to place the HWND within the larger Win32 application
/clr
The first step is to turn this unmanaged Win32 project into one that can call managed code. You use the /clr
compiler option, which will link to the necessary DLLs you want to use, and adjust the Main method for use with
WPF.
To enable the use of managed code inside the C++ project: Right-click on win32clock project and select
Proper ties . On the General property page (the default), change Common Language Runtime support to               /clr
.
Next, add references to DLLs necessary for WPF: PresentationCore.dll, PresentationFramework.dll, System.dll,
WindowsBase.dll, UIAutomationProvider.dll, and UIAutomationTypes.dll. (Following instructions assume the
operating system is installed on C: drive.)
1. Right-click win32clock project and select References..., and inside that dialog:
2. Right-click win32clock project and select References....
3. Click Add New Reference , click Browse tab, enter C:\Program Files\Reference
   Assemblies\Microsoft\Framework\v3.0\PresentationCore.dll, and click OK.
4. Repeat for PresentationFramework.dll: C:\Program Files\Reference
   Assemblies\Microsoft\Framework\v3.0\PresentationFramework.dll.
5. Repeat for WindowsBase.dll: C:\Program Files\Reference
   Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll.
6. Repeat for UIAutomationTypes.dll: C:\Program Files\Reference
   Assemblies\Microsoft\Framework\v3.0\UIAutomationTypes.dll.
7. Repeat for UIAutomationProvider.dll: C:\Program Files\Reference
   Assemblies\Microsoft\Framework\v3.0\UIAutomationProvider.dll.
8. Click Add New Reference , select System.dll, and click OK .
9. Click OK to exit the win32clock Property Pages for adding references.
Finally, add the   STAThreadAttribute   to the   _tWinMain   method for use with WPF:
   [System::STAThreadAttribute]
   int APIENTRY _tWinMain(HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        LPTSTR    lpCmdLine,
                        int       nCmdShow)
This attribute tells the common language runtime (CLR) that when it initializes Component Object Model (COM),
it should use a single threaded apartment model (STA), which is necessary for WPF (and Windows Forms).
HwndSource
Next, you use HwndSource to make the WPFPage look like an HWND. You add this block of code to a C++ file:
   namespace   ManagedCode
   {
       using   namespace   System;
       using   namespace   System::Windows;
       using   namespace   System::Windows::Interop;
       using   namespace   System::Windows::Media;
This is a long piece of code that could use some explanation. The first part is various clauses so that you do not
need to fully qualify all the calls:
   namespace   ManagedCode
   {
       using   namespace   System;
       using   namespace   System::Windows;
       using   namespace   System::Windows::Interop;
       using   namespace   System::Windows::Media;
Then you define a function that creates the WPF content, puts an HwndSource around it, and returns the HWND:
Then you create the WPF content class by calling its constructor:
   source->RootVisual = page;
And in the final line, return the HWND for the HwndSource:
You then calculate the size and position of that placeholder STATIC, so you can put the WPF clock in that place:
RECT rectangle;
   GetWindowRect(placeholder, &rectangle);
   int width = rectangle.right - rectangle.left;
   int height = rectangle.bottom - rectangle.top;
   POINT point;
   point.x = rectangle.left;
   point.y = rectangle.top;
   result = MapWindowPoints(NULL, hDlg, &point, 1);
ShowWindow(placeholder, SW_HIDE);
To make the tutorial interesting, and to produce a real WPF clock, you will need to create a WPF clock control at
this point. You can do so mostly in markup, with just a few event handlers in code-behind. Since this tutorial is
about interoperation and not about control design, complete code for the WPF clock is provided here as a code
block, without discrete instructions for building it up or what each part means. Feel free to experiment with this
code to change the look and feel or functionality of the control.
Here is the markup:
   <Page x:Class="WPFClock.Clock"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       >
       <Grid>
           <Grid.Background>
               <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                 <GradientStop Color="#fcfcfe" Offset="0" />
                 <GradientStop Color="#f6f4f0" Offset="1.0" />
               </LinearGradientBrush>
           </Grid.Background>
        <Grid Name="PodClock" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Grid.Resources>
                <Storyboard x:Key="sb">
                    <DoubleAnimation From="0" To="360" Duration="12:00:00" RepeatBehavior="Forever"
                        Storyboard.TargetName="HourHand"
                        Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)"
                        />
                    <DoubleAnimation From="0" To="360" Duration="01:00:00" RepeatBehavior="Forever"
                        Storyboard.TargetName="MinuteHand"
                        Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)"
                        />
                    <DoubleAnimation From="0" To="360" Duration="0:1:00" RepeatBehavior="Forever"
                        Storyboard.TargetName="SecondHand"
                        Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)"
                        />
                </Storyboard>
            </Grid.Resources>
   namespace WPFClock
   {
       /// <summary>
       /// Interaction logic for Clock.xaml
       /// </summary>
       public partial class Clock : Page
       {
           private DispatcherTimer _dayTimer;
              public Clock()
              {
                  InitializeComponent();
                  this.Loaded += new RoutedEventHandler(Clock_Loaded);
              }
                  // then set up a timer to fire at the start of tomorrow, so that we can update
                  // the datacontext
                  _dayTimer = new DispatcherTimer();
                  _dayTimer.Interval = new TimeSpan(1, 0, 0, 0) - now.TimeOfDay;
                  _dayTimer.Tick += new EventHandler(OnDayChange);
                  _dayTimer.Start();
                  // finally, seek the timeline, which assumes a beginning at midnight, to the appropriate
                  // offset
                  Storyboard sb = (Storyboard)PodClock.FindResource("sb");
                  sb.Begin(PodClock, HandoffBehavior.SnapshotAndReplace, true);
                  sb.Seek(PodClock, now.TimeOfDay, TimeSeekOrigin.BeginTime);
              }
See also
   HwndSource
   WPF and Win32 Interoperation
   Win32 Clock Interoperation Sample
       WPF and Direct3D9 Interoperation
       11/21/2022 • 10 minutes to read • Edit Online
You can include Direct3D9 content in a Windows Presentation Foundation (WPF) application. This topic
describes how to create Direct3D9 content so that it efficiently interoperates with WPF.
  NOTE
  When using Direct3D9 content in WPF, you also need to think about performance. For more information about how to
  optimize for performance, see Performance Considerations for Direct3D9 and WPF Interoperability.
Display Buffers
The D3DImage class manages two display buffers, which are called the back buffer and the front buffer. The
back buffer is your Direct3D9 surface. Changes to the back buffer are copied forward to the front buffer when
you call the Unlock method.
The following illustration shows the relationship between the back buffer and the front buffer.
On Windows Vista or later operating system, use the Direct3DCreate9Ex method with a display that is
configured to use the Windows Display Driver Model (WDDM). Use the Direct3DCreate9 method on any other
platform.
Availability of the Direct3DCreate9Ex method
The d3d9.dll has the Direct3DCreate9Ex method only on Windows Vista or later operating system. If you directly
link the function on Windows XP, your application fails to load. To determine whether the Direct3DCreate9Ex
method is supported, load the DLL and look for the proc address. The following code shows how to test for the
  Direct3DCreate9Ex method. For a full code example, see Walkthrough: Creating Direct3D9 Content for Hosting
in WPF.
   HRESULT
   CRendererManager::EnsureD3DObjects()
   {
       HRESULT hr = S_OK;
           m_cAdapters = m_pD3D->GetAdapterCount();
       }
   Cleanup:
       if (hD3D)
       {
            FreeLibrary(hD3D);
       }
       return hr;
   }
HWND Creation
Creating a device requires an HWND. In general, you create a dummy HWND for Direct3D9 to use. The
following code example shows how to create a dummy HWND.
   HRESULT
   CRendererManager::EnsureHWND()
   {
       HRESULT hr = S_OK;
       if (!m_hwnd)
       {
           WNDCLASS wndclass;
           if (!RegisterClass(&wndclass))
           {
               IFC(E_FAIL);
           }
           m_hwnd = CreateWindow(szAppName,
                               TEXT("D3DImageSample"),
                               WS_OVERLAPPEDWINDOW,
                               0,                   //    Initial X
                               0,                   //    Initial Y
                               0,                   //    Width
                               0,                   //    Height
                               NULL,
                               NULL,
                               NULL,
                               NULL);
       }
   Cleanup:
       return hr;
   }
Present Parameters
Creating a device also requires a D3DPRESENT_PARAMETERS struct, but only a few parameters are important. These
parameters are chosen to minimize the memory footprint.
Set the BackBufferHeight and    BackBufferWidth   fields to 1. Setting them to 0 causes them to be set to the
dimensions of the HWND.
Always set the D3DCREATE_MULTITHREADED and D3DCREATE_FPU_PRESERVE flags to prevent corrupting memory used
by Direct3D9 and to prevent Direct3D9 from changing FPU settings.
The following code shows how to initialize the    D3DPRESENT_PARAMETERS   struct.
   HRESULT
   CRenderer::Init(IDirect3D9 *pD3D, IDirect3D9Ex *pD3DEx, HWND hwnd, UINT uAdapter)
   {
       HRESULT hr = S_OK;
       D3DPRESENT_PARAMETERS d3dpp;
       ZeroMemory(&d3dpp, sizeof(d3dpp));
       d3dpp.Windowed = TRUE;
       d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
       d3dpp.BackBufferHeight = 1;
       d3dpp.BackBufferWidth = 1;
       d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
       D3DCAPS9 caps;
       DWORD dwVertexProcessing;
       IFC(pD3D->GetDeviceCaps(uAdapter, D3DDEVTYPE_HAL, &caps));
       if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == D3DDEVCAPS_HWTRANSFORMANDLIGHT)
       {
            dwVertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
       }
       else
       {
            dwVertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
       }
       if (pD3DEx)
       {
           IDirect3DDevice9Ex *pd3dDevice = NULL;
           IFC(pD3DEx->CreateDeviceEx(
               uAdapter,
               D3DDEVTYPE_HAL,
               hwnd,
               dwVertexProcessing | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
               &d3dpp,
               NULL,
               &m_pd3dDeviceEx
               ));
            IFC(m_pd3dDeviceEx->QueryInterface(__uuidof(IDirect3DDevice9), reinterpret_cast<void**>
   (&m_pd3dDevice)));
       }
       else
       {
            assert(pD3D);
           IFC(pD3D->CreateDevice(
               uAdapter,
               D3DDEVTYPE_HAL,
               hwnd,
               dwVertexProcessing | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
               &d3dpp,
               &m_pd3dDevice
               ));
       }
   Cleanup:
       return hr;
   }
       //
       //   We test all adapters because because we potentially use all adapters.
       //   But even if this sample only rendered to the default adapter, you
       //   should check all adapters because WPF may move your surface to
       //   another adapter for you!
       //
                    if (FAILED(m_pD3D->CheckDeviceMultiSampleType(
                        i,
                        D3DDEVTYPE_HAL,
                        fmt,
                        TRUE,
                        static_cast<D3DMULTISAMPLE_TYPE>(m_uNumSamples),
                        NULL
                        )))
                    {
                        m_uNumSamples = 0;
                    }
             }
             else
             {
                    m_uNumSamples = 0;
             }
       }
   Cleanup:
       return hr;
   }
   HRESULT
   CRenderer::CreateSurface(UINT uWidth, UINT uHeight, bool fUseAlpha, UINT m_uNumSamples)
   {
       HRESULT hr = S_OK;
SAFE_RELEASE(m_pd3dRTS);
       IFC(m_pd3dDevice->CreateRenderTarget(
           uWidth,
           uHeight,
           fUseAlpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8,
           static_cast<D3DMULTISAMPLE_TYPE>(m_uNumSamples),
           0,
           m_pd3dDeviceEx ? FALSE : TRUE, // Lockable RT required for good XP perf
           &m_pd3dRTS,
           NULL
           ));
IFC(m_pd3dDevice->SetRenderTarget(0, m_pd3dRTS));
   Cleanup:
       return hr;
   }
WDDM
On Windows Vista and later operating systems, which are configured to use the WDDM, you can create a render
target texture and pass the level 0 surface to the SetBackBuffer method. This approach is not recommended on
Windows XP, because you cannot create a lockable render target texture and performance will be reduced.
Handling Resizing
If a D3DImage is displayed at a resolution other than its native size, it is scaled according to the current
BitmapScalingMode, except that Bilinear is substituted for Fant.
If you require higher fidelity, you must create a new surface when the container of the D3DImage changes size.
There are three possible approaches to handle resizing.
   Participate in the layout system and create a new surface when the size changes. Do not create too many
   surfaces, because you may exhaust or fragment video memory.
   Wait until a resize event has not occurred for a fixed period of time to create the new surface.
   Create a DispatcherTimer that checks the container dimensions several times per second.
Multi-monitor Optimization
Significantly reduced performance can result when the rendering system moves a D3DImage to another
monitor.
On WDDM, as long as the monitors are on the same video card and you use Direct3DCreate9Ex , there is no
reduction in performance. If the monitors are on separate video cards, performance is reduced. On Windows XP,
performance is always reduced.
When the D3DImage moves to another monitor, you can create a new surface on the corresponding adapter to
restore good performance.
To avoid the performance penalty, write code specifically for the multi-monitor case. The following list shows
one way to write multi-monitor code.
1. Find a point of the D3DImage in screen space with the       Visual.ProjectToScreen    method.
2. Use the   MonitorFromPoint   GDI method to find the monitor that is displaying the point.
3. Use the   IDirect3D9::GetAdapterMonitor    method to find which Direct3D9 adapter the monitor is on.
4. If the adapter is not the same as the adapter with the back buffer, create a new back buffer on the new
   monitor and assign it to the D3DImage back buffer.
  NOTE
  If the D3DImage straddles monitors, performance will be slow, except in the case of WDDM and   IDirect3D9Ex   on the
  same adapter. There is no way to improve performance in this situation.
The following code example shows how to find the current monitor.
   void
   CRendererManager::SetAdapter(POINT screenSpacePoint)
   {
        CleanupInvalidDevices();
       //
       // After CleanupInvalidDevices, we may not have any D3D objects. Rather than
       // recreate them here, ignore the adapter update and wait for render to recreate.
       //
Update the monitor when the D3DImage container's size or position changes, or update the monitor by using a
 DispatcherTimer that updates a few times per second.
  NOTE
  If WPF is rendering completely in software, D3DImage is not shown because WPF does not have a front buffer.
See also
   D3DImage
   Performance Considerations for Direct3D9 and WPF Interoperability
   Walkthrough: Creating Direct3D9 Content for Hosting in WPF
   Walkthrough: Hosting Direct3D9 Content in WPF
       Performance Considerations for Direct3D9 and WPF
       Interoperability
       11/21/2022 • 4 minutes to read • Edit Online
You can host Direct3D9 content by using the D3DImage class. Hosting Direct3D9 content can affect the
performance of your application. This topic describes best practices to optimize performance when hosting
Direct3D9 content in a Windows Presentation Foundation (WPF) application. These best practices include how to
use D3DImage and best practices when you are using Windows Vista, Windows XP, and multi-monitor displays.
  NOTE
  For code examples that demonstrate these best practices, see WPF and Direct3D9 Interoperation.
  NOTE
  If Windows Vista has a display that is configured to use the Windows XP Display Driver Model (XDDM), the surface is
  always copied through software, regardless of settings. With the proper settings and video card, you will see better
  performance on Windows Vista when you use the WDDM because surface copies are performed in hardware.
  NOTE
  XDDM is available on both Windows XP and Windows Vista; however, WDDM is available only on Windows Vista.
Performance Summary
The following table shows performance of the front buffer update as a function of operating system, pixel
format, and surface lockability. The front buffer and back buffer are assumed to be on the same adapter.
Depending on the adapter configuration, hardware updates are generally much faster than software updates.
                                                  OT H ER W IN DO W S
  SURFA C E P IXEL        W IN DO W S VISTA ,     VISTA                   W IN DO W S XP SP 3 O R
  F O RM AT               W DDM A N D 9EX         C O N F IGURAT IO N S   SP 2 W / H OT F IX        W IN DO W S XP SP 2
This walkthrough shows how to create Direct3D9 content that is suitable for hosting in a Windows Presentation
Foundation (WPF) application. For more information on hosting Direct3D9 content in WPF applications, see
WPF and Direct3D9 Interoperation.
In this walkthrough, you perform the following tasks:
   Create a Direct3D9 project.
   Configure the Direct3D9 project for hosting in a WPF application.
When you are finished, you will have a DLL that contains Direct3D9 content for use in a WPF application.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio 2010.
   DirectX SDK 9 or later.
CTriangleRenderer
 2. Open Renderer.h in the Code Editor and replace the automatically generated code with the following
    code.
#pragma once
        class CRenderer
        {
        public:
            virtual ~CRenderer();
             HRESULT CheckDeviceState();
             HRESULT CreateSurface(UINT uWidth, UINT uHeight, bool fUseAlpha, UINT m_uNumSamples);
        protected:
            CRenderer();
virtual HRESULT Init(IDirect3D9 *pD3D, IDirect3D9Ex *pD3DEx, HWND hwnd, UINT uAdapter);
             IDirect3DDevice9 *m_pd3dDevice;
             IDirect3DDevice9Ex *m_pd3dDeviceEx;
IDirect3DSurface9 *m_pd3dRTS;
};
 3. Open Renderer.cpp in the Code Editor and replace the automatically generated code with the following
    code.
        //+-----------------------------------------------------------------------------
        //
        // CRenderer
        //
        //      An abstract base class that creates a device and a target render
        //      surface. Derive from this class and override Init() and Render()
        //      to do your own rendering. See CTriangleRenderer for an example.
//------------------------------------------------------------------------------
#include "StdAfx.h"
//+-----------------------------------------------------------------------------
//
// Member:
//      CRenderer ctor
//
//------------------------------------------------------------------------------
CRenderer::CRenderer() : m_pd3dDevice(NULL), m_pd3dDeviceEx(NULL), m_pd3dRTS(NULL)
{
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRenderer dtor
//
//------------------------------------------------------------------------------
CRenderer::~CRenderer()
{
    SAFE_RELEASE(m_pd3dDevice);
    SAFE_RELEASE(m_pd3dDeviceEx);
    SAFE_RELEASE(m_pd3dRTS);
}
//+-----------------------------------------------------------------------------
//
// Member:
//       CRenderer::CheckDeviceState
//
// Synopsis:
//       Returns the status of the device. 9Ex devices are a special case because
//       TestCooperativeLevel() has been deprecated in 9Ex.
//
//------------------------------------------------------------------------------
HRESULT
CRenderer::CheckDeviceState()
{
    if (m_pd3dDeviceEx)
    {
         return m_pd3dDeviceEx->CheckDeviceState(NULL);
    }
    else if (m_pd3dDevice)
    {
         return m_pd3dDevice->TestCooperativeLevel();
    }
    else
    {
         return D3DERR_DEVICELOST;
    }
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRenderer::CreateSurface
//
// Synopsis:
//      Creates and sets the render target
//
//------------------------------------------------------------------------------
HRESULT
CRenderer::CreateSurface(UINT uWidth, UINT uHeight, bool fUseAlpha, UINT m_uNumSamples)
{
    HRESULT hr = S_OK;
    SAFE_RELEASE(m_pd3dRTS);
    SAFE_RELEASE(m_pd3dRTS);
    IFC(m_pd3dDevice->CreateRenderTarget(
        uWidth,
        uHeight,
        fUseAlpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8,
        static_cast<D3DMULTISAMPLE_TYPE>(m_uNumSamples),
        0,
        m_pd3dDeviceEx ? FALSE : TRUE, // Lockable RT required for good XP perf
        &m_pd3dRTS,
        NULL
        ));
IFC(m_pd3dDevice->SetRenderTarget(0, m_pd3dRTS));
Cleanup:
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRenderer::Init
//
// Synopsis:
//      Creates the device
//
//------------------------------------------------------------------------------
HRESULT
CRenderer::Init(IDirect3D9 *pD3D, IDirect3D9Ex *pD3DEx, HWND hwnd, UINT uAdapter)
{
    HRESULT hr = S_OK;
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.BackBufferHeight = 1;
    d3dpp.BackBufferWidth = 1;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    D3DCAPS9 caps;
    DWORD dwVertexProcessing;
    IFC(pD3D->GetDeviceCaps(uAdapter, D3DDEVTYPE_HAL, &caps));
    if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == D3DDEVCAPS_HWTRANSFORMANDLIGHT)
    {
         dwVertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    }
    else
    {
         dwVertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }
    if (pD3DEx)
    {
        IDirect3DDevice9Ex *pd3dDevice = NULL;
        IFC(pD3DEx->CreateDeviceEx(
            uAdapter,
            D3DDEVTYPE_HAL,
            hwnd,
            dwVertexProcessing | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
            &d3dpp,
            NULL,
            &m_pd3dDeviceEx
            ));
         IFC(m_pd3dDeviceEx->QueryInterface(__uuidof(IDirect3DDevice9), reinterpret_cast<void**>
(&m_pd3dDevice)));
    }
    else
         else
         {
                assert(pD3D);
                IFC(pD3D->CreateDevice(
                    uAdapter,
                    D3DDEVTYPE_HAL,
                    hwnd,
                    dwVertexProcessing | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
                    &d3dpp,
                    &m_pd3dDevice
                    ));
         }
     Cleanup:
         return hr;
     }
4. Open RendererManager.h in the Code Editor and replace the automatically generated code with the
   following code.
     #pragma once
class CRenderer;
     class CRendererManager
     {
     public:
         static HRESULT Create(CRendererManager **ppManager);
         ~CRendererManager();
HRESULT EnsureDevices();
HRESULT Render();
     private:
         CRendererManager();
          void CleanupInvalidDevices();
          HRESULT EnsureRenderers();
          HRESULT EnsureHWND();
          HRESULT EnsureD3DObjects();
          HRESULT TestSurfaceSettings();
          void DestroyResources();
          IDirect3D9   *m_pD3D;
          IDirect3D9Ex *m_pD3DEx;
          UINT m_cAdapters;
          CRenderer **m_rgRenderers;
          CRenderer *m_pCurrentRenderer;
HWND m_hwnd;
          UINT   m_uWidth;
          UINT   m_uHeight;
          UINT   m_uNumSamples;
          bool   m_fUseAlpha;
          bool   m_fSurfaceSettingsChanged;
     };
5. Open RendererManager.cpp in the Code Editor and replace the automatically generated code with the
   following code.
     //+-----------------------------------------------------------------------------
     //
     // CRendererManager
     //
     //      Manages the list of CRenderers. Managed code pinvokes into this class
     //      and this class forwards to the appropriate CRenderer.
     //
     //------------------------------------------------------------------------------
#include "StdAfx.h"
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager dtor
//
//------------------------------------------------------------------------------
CRendererManager::~CRendererManager()
{
    DestroyResources();
    if (m_hwnd)
    {
        DestroyWindow(m_hwnd);
        UnregisterClass(szAppName, NULL);
    }
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::Create
//
// Synopsis:
//      Creates the manager
//
//------------------------------------------------------------------------------
HRESULT
CRendererManager::Create(CRendererManager **ppManager)
{
    HRESULT hr = S_OK;
Cleanup:
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::EnsureRenderers
//
// Synopsis:
//      Makes sure the CRenderer objects exist
//
//
//------------------------------------------------------------------------------
HRESULT
CRendererManager::EnsureRenderers()
{
    HRESULT hr = S_OK;
    if (!m_rgRenderers)
    {
        IFC(EnsureHWND());
        assert(m_cAdapters);
        m_rgRenderers = new CRenderer*[m_cAdapters];
        IFCOOM(m_rgRenderers);
        ZeroMemory(m_rgRenderers, m_cAdapters * sizeof(m_rgRenderers[0]));
Cleanup:
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::EnsureHWND
//
// Synopsis:
//      Makes sure an HWND exists if we need it
//
//------------------------------------------------------------------------------
HRESULT
CRendererManager::EnsureHWND()
{
    HRESULT hr = S_OK;
    if (!m_hwnd)
    {
        WNDCLASS wndclass;
        if (!RegisterClass(&wndclass))
        {
            IFC(E_FAIL);
        }
        m_hwnd = CreateWindow(szAppName,
                            TEXT("D3DImageSample"),
                            WS_OVERLAPPEDWINDOW,
                            0,                   //   Initial X
                            0,                   //   Initial Y
                            0,                   //   Width
                            0,                   //   Height
                              0,                   // Height
                              NULL,
                              NULL,
                              NULL,
                              NULL);
    }
Cleanup:
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::EnsureD3DObjects
//
// Synopsis:
//      Makes sure the D3D objects exist
//
//------------------------------------------------------------------------------
HRESULT
CRendererManager::EnsureD3DObjects()
{
    HRESULT hr = S_OK;
        m_cAdapters = m_pD3D->GetAdapterCount();
    }
Cleanup:
    if (hD3D)
    {
         FreeLibrary(hD3D);
    }
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::CleanupInvalidDevices
//
// Synopsis:
//      Checks to see if any devices are bad and if so, deletes all resources
//
//      We could delete resources and wait for D3DERR_DEVICENOTRESET and reset
//      the devices, but if the device is lost because of an adapter order
//      change then our existing D3D objects would have stale adapter
//      information. We'll delete everything to be safe rather than sorry.
//
//
//------------------------------------------------------------------------------
void
CRendererManager::CleanupInvalidDevices()
{
     for (UINT i = 0; i < m_cAdapters; ++i)
     {
         if (FAILED(m_rgRenderers[i]->CheckDeviceState()))
         {
             DestroyResources();
             break;
         }
     }
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::GetBackBufferNoRef
//
// Synopsis:
//      Returns the surface of the current renderer without adding a reference
//
//      This can return NULL if we're in a bad device state.
//
//------------------------------------------------------------------------------
HRESULT
CRendererManager::GetBackBufferNoRef(IDirect3DSurface9 **ppSurface)
{
    HRESULT hr = S_OK;
CleanupInvalidDevices();
IFC(EnsureD3DObjects());
    //
    //   Even if we never render to another adapter, this sample creates devices
    //   and resources on each one. This is a potential waste of video memory,
    //   but it guarantees that we won't have any problems (e.g. out of video
    //   memory) when switching to render on another adapter. In your own code
    //   you may choose to delay creation but you'll need to handle the issues
    //   that come with it.
    //
IFC(EnsureRenderers());
    if (m_fSurfaceSettingsChanged)
    {
        if (FAILED(TestSurfaceSettings()))
        {
            IFC(E_FAIL);
        }
          m_fSurfaceSettingsChanged = false;
    }
    if (m_pCurrentRenderer)
    {
        *ppSurface = m_pCurrentRenderer->GetSurfaceNoRef();
    }
Cleanup:
    // If we failed because of a bad device, ignore the failure for now and
    // we'll clean up and try again next time.
    if (hr == D3DERR_DEVICELOST)
    {
         hr = S_OK;
    }
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::TestSurfaceSettings
//
// Synopsis:
//      Checks to see if our current surface settings are allowed on all
//      adapters.
//
//------------------------------------------------------------------------------
HRESULT
CRendererManager::TestSurfaceSettings()
{
    HRESULT hr = S_OK;
    //
    //   We test all adapters because because we potentially use all adapters.
    //   But even if this sample only rendered to the default adapter, you
    //   should check all adapters because WPF may move your surface to
    //   another adapter for you!
    //
              if (FAILED(m_pD3D->CheckDeviceMultiSampleType(
                  i,
                  D3DDEVTYPE_HAL,
                  fmt,
                  TRUE,
                  static_cast<D3DMULTISAMPLE_TYPE>(m_uNumSamples),
                  NULL
                   )))
               {
                   m_uNumSamples = 0;
               }
        }
        else
        {
               m_uNumSamples = 0;
        }
    }
Cleanup:
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//       CRendererManager::DestroyResources
//
// Synopsis:
//       Delete all D3D resources
//
//------------------------------------------------------------------------------
void
CRendererManager::DestroyResources()
{
     SAFE_RELEASE(m_pD3D);
     SAFE_RELEASE(m_pD3DEx);
    m_pCurrentRenderer = NULL;
    m_cAdapters = 0;
    m_fSurfaceSettingsChanged = true;
}
//+-----------------------------------------------------------------------------
//
// Member:
//       CRendererManager::SetSize
//
// Synopsis:
//       Update the size of the surface. Next render will create a new surface.
//
//------------------------------------------------------------------------------
void
CRendererManager::SetSize(UINT uWidth, UINT uHeight)
{
     if (uWidth != m_uWidth || uHeight != m_uHeight)
     {
         m_uWidth = uWidth;
         m_uHeight = uHeight;
         m_fSurfaceSettingsChanged = true;
     }
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CRendererManager::SetAlpha
//
// Synopsis:
// Synopsis:
//       Update the format of the surface. Next render will create a new surface.
//
//------------------------------------------------------------------------------
void
CRendererManager::SetAlpha(bool fUseAlpha)
{
     if (fUseAlpha != m_fUseAlpha)
     {
         m_fUseAlpha = fUseAlpha;
         m_fSurfaceSettingsChanged = true;
     }
}
//+-----------------------------------------------------------------------------
//
// Member:
//       CRendererManager::SetNumDesiredSamples
//
// Synopsis:
//       Update the MSAA settings of the surface. Next render will create a
//       new surface.
//
//------------------------------------------------------------------------------
void
CRendererManager::SetNumDesiredSamples(UINT uNumSamples)
{
     if (m_uNumSamples != uNumSamples)
     {
         m_uNumSamples = uNumSamples;
         m_fSurfaceSettingsChanged = true;
     }
}
//+-----------------------------------------------------------------------------
//
// Member:
//       CRendererManager::SetAdapter
//
// Synopsis:
//       Update the current renderer. Next render will use the new renderer.
//
//------------------------------------------------------------------------------
void
CRendererManager::SetAdapter(POINT screenSpacePoint)
{
     CleanupInvalidDevices();
    //
    // After CleanupInvalidDevices, we may not have any D3D objects. Rather than
    // recreate them here, ignore the adapter update and wait for render to recreate.
    //
//+-----------------------------------------------------------------------------
//
      //
      // Member:
      //      CRendererManager::Render
      //
      // Synopsis:
      //      Forward to the current renderer
      //
      //------------------------------------------------------------------------------
      HRESULT
      CRendererManager::Render()
      {
          return m_pCurrentRenderer ? m_pCurrentRenderer->Render() : S_OK;
      }
6. Open TriangleRenderer.h in the Code Editor and replace the automatically generated code with the
   following code.
#pragma once
HRESULT Render();
      protected:
          HRESULT Init(IDirect3D9 *pD3D, IDirect3D9Ex *pD3DEx, HWND hwnd, UINT uAdapter);
      private:
          CTriangleRenderer();
           IDirect3DVertexBuffer9 *m_pd3dVB;
      };
7. Open TriangleRenderer.cpp in the Code Editor and replace the automatically generated code with the
   following code.
      //+-----------------------------------------------------------------------------
      //
      // CTriangleRenderer
      //
      //      Subclass of CRenderer that renders a single, spinning triangle
      //
      //------------------------------------------------------------------------------
#include "StdAfx.h"
      struct CUSTOMVERTEX
      {
          FLOAT x, y, z;
          DWORD color;
      };
      //+-----------------------------------------------------------------------------
      //
      // Member:
      //      CTriangleRenderer ctor
      //
      //------------------------------------------------------------------------------
      CTriangleRenderer::CTriangleRenderer() : CRenderer(), m_pd3dVB(NULL)
CTriangleRenderer::CTriangleRenderer() : CRenderer(), m_pd3dVB(NULL)
{
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CTriangleRenderer dtor
//
//------------------------------------------------------------------------------
CTriangleRenderer::~CTriangleRenderer()
{
    SAFE_RELEASE(m_pd3dVB);
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CTriangleRenderer::Create
//
// Synopsis:
//      Creates the renderer
//
//------------------------------------------------------------------------------
HRESULT
CTriangleRenderer::Create(IDirect3D9 *pD3D, IDirect3D9Ex *pD3DEx, HWND hwnd, UINT uAdapter, CRenderer
**ppRenderer)
{
    HRESULT hr = S_OK;
    *ppRenderer = pRenderer;
    pRenderer = NULL;
Cleanup:
    delete pRenderer;
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CTriangleRenderer::Init
//
// Synopsis:
//      Override of CRenderer::Init that calls base to create the device and
//      then creates the CTriangleRenderer-specific resources
//
//------------------------------------------------------------------------------
HRESULT
CTriangleRenderer::Init(IDirect3D9 *pD3D, IDirect3D9Ex *pD3DEx, HWND hwnd, UINT uAdapter)
{
    HRESULT hr = S_OK;
    D3DXMATRIXA16 matView, matProj;
    D3DXVECTOR3 vEyePt(0.0f, 0.0f,-5.0f);
    D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
    // Set up the VB
    CUSTOMVERTEX vertices[] =
    {
         { -1.0f, -1.0f, 0.0f, 0xffff0000, }, // x, y, z, color
         { 1.0f, -1.0f, 0.0f, 0xff00ff00, },
         { 0.0f, 1.0f, 0.0f, 0xff00ffff, },
    };
    void *pVertices;
    IFC(m_pd3dVB->Lock(0, sizeof(vertices), &pVertices, 0));
    memcpy(pVertices, vertices, sizeof(vertices));
    m_pd3dVB->Unlock();
Cleanup:
    return hr;
}
//+-----------------------------------------------------------------------------
//
// Member:
//      CTriangleRenderer::Render
//
// Synopsis:
//      Renders the rotating triangle
//
//------------------------------------------------------------------------------
HRESULT
CTriangleRenderer::Render()
{
    HRESULT hr = S_OK;
    D3DXMATRIXA16 matWorld;
    IFC(m_pd3dDevice->BeginScene());
    IFC(m_pd3dDevice->Clear(
        0,
        NULL,
        D3DCLEAR_TARGET,
        D3DCOLOR_ARGB(128, 0, 0, 128), // NOTE: Premultiplied alpha!
        1.0f,
        0
        ));
IFC(m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1));
IFC(m_pd3dDevice->EndScene());
Cleanup:
    return hr;
}
8. Open stdafx.h in the Code Editor and replace the automatically generated code with the following code.
#pragma once
      #include <d3d9.h>
      #include <d3dx9.h>
#include <assert.h>
      #include "RendererManager.h"
      #include "Renderer.h"
      #include "TriangleRenderer.h"
9. Open dllmain.cpp in the Code Editor and replace the automatically generated code with the following
   code.
IFC(EnsureRendererManager());
pManager->SetSize(uWidth, uHeight);
      Cleanup:
          return hr;
           return hr;
       }
IFC(EnsureRendererManager());
pManager->SetAlpha(!!fUseAlpha);
       Cleanup:
           return hr;
       }
IFC(EnsureRendererManager());
pManager->SetNumDesiredSamples(uNumSamples);
       Cleanup:
           return hr;
       }
IFC(EnsureRendererManager());
pManager->SetAdapter(screenSpacePoint);
       Cleanup:
           return hr;
       }
IFC(EnsureRendererManager());
IFC(pManager->GetBackBufferNoRef(ppSurface));
       Cleanup:
           return hr;
       }
           return pManager->Render();
       }
EXPORTS
       SetSize
       SetAlpha
       SetNumDesiredSamples
       SetAdapter
       GetBackBufferNoRef
       Render
       Destroy
 Next Steps
    Host the Direct3D9 content in a WPF application. For more information, see Walkthrough: Hosting Direct3D9
    Content in WPF.
 See also
    D3DImage
    Performance Considerations for Direct3D9 and WPF Interoperability
    Walkthrough: Hosting Direct3D9 Content in WPF
       Walkthrough: Hosting Direct3D9 Content in WPF
       11/21/2022 • 5 minutes to read • Edit Online
This walkthrough shows how to host Direct3D9 content in a Windows Presentation Foundation (WPF)
application.
In this walkthrough, you perform the following tasks:
   Create a WPF project to host the Direct3D9 content.
   Import the Direct3D9 content.
   Display the Direct3D9 content by using the D3DImage class.
When you are finished, you will know how to host Direct3D9 content in a WPF application.
Prerequisites
You need the following components to complete this walkthrough:
   Visual Studio.
   DirectX SDK 9 or later.
   A DLL that contains Direct3D9 content in a WPF-compatible format. For more information, see WPF and
   Direct3D9 Interoperation and Walkthrough: Creating Direct3D9 Content for Hosting in WPF.
      using   System;
      using   System.Collections.Generic;
      using   System.Linq;
      using   System.Text;
      using   System.Windows;
      using   System.Windows.Controls;
      using   System.Windows.Data;
      using   System.Windows.Documents;
      using   System.Windows.Input;
      using   System.Windows.Interop;
      using   System.Windows.Media;
using   System.Windows.Media;
using   System.Windows.Media.Imaging;
using   System.Windows.Navigation;
using   System.Windows.Shapes;
using   System.Windows.Threading;
using   System.Runtime.InteropServices;
using   System.Security.Permissions;
namespace D3DHost
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
              //
              //   Optional: Subscribing to the IsFrontBufferAvailableChanged event.
              //
              //   If you don't render every frame (e.g. you only render in
              //   reaction to a button click), you should subscribe to the
              //   IsFrontBufferAvailableChanged event to be notified when rendered content
              //   is no longer being displayed. This event also notifies you when
              //   the D3DImage is capable of being displayed again.
              // For example, in the button click case, if you don't render again when
              // the IsFrontBufferAvailable property is set to true, your
              // D3DImage won't display anything until the next button click.
              //
              // Because this application renders every frame, there is no need to
              // handle the IsFrontBufferAvailableChanged event.
              //
              CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
              //
              // Optional: Multi-adapter optimization
              //
              // The surface is created initially on a particular adapter.
              // If the WPF window is dragged to another adapter, WPF
              // ensures that the D3DImage still shows up on the new
              // adapter.
              //
              // This process is slow on Windows XP.
              //
              // Performance is better on Vista with a 9Ex device. It's only
              // slow when the D3DImage crosses a video-card boundary.
              //
              // To work around this issue, you can move your surface when
              // the D3DImage is displayed on another adapter. To
              // determine when that is the case, transform a point on the
              // D3DImage into screen space and find out which adapter
              // contains that screen space point.
              //
              // When your D3DImage straddles two adapters, nothing
              // can be done, because one will be updating slowly.
              //
              _adapterTimer = new DispatcherTimer();
              _adapterTimer.Tick += new EventHandler(AdapterTimer_Tick);
              _adapterTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
              _adapterTimer.Start();
              //
              // Optional: Surface resizing
              //
    // The D3DImage is scaled when WPF renders it at a size
    // different from the natural size of the surface. If the
    // D3DImage is scaled up significantly, image quality
    // degrades.
    //
    // To avoid this, you can either create a very large
    // texture initially, or you can create new surfaces as
    // the size changes. Below is a very simple example of
    // how to do the latter.
    //
    // By creating a timer at Render priority, you are guaranteed
    // that new surfaces are created while the element
    // is still being arranged. A 200 ms interval gives
    // a good balance between image quality and performance.
    // You must be careful not to create new surfaces too
    // frequently. Frequently allocating a new surface may
    // fragment or exhaust video memory. This issue is more
    // significant on XDDM than it is on WDDM, because WDDM
    // can page out video memory.
    //
    // Another approach is deriving from the Image class,
    // participating in layout by overriding the ArrangeOverride method, and
    // updating size in the overriden method. Performance will degrade
    // if you resize too frequently.
    //
    // Blurry D3DImages can still occur due to subpixel
    // alignments.
    //
    _sizeTimer = new DispatcherTimer(DispatcherPriority.Render);
    _sizeTimer.Tick += new EventHandler(SizeTimer_Tick);
    _sizeTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
    _sizeTimer.Start();
}
~MainWindow()
{
    Destroy();
}
    HRESULT.Check(SetAdapter(p));
}
    // Given that the D3DImage is at 96.0 DPI, its Width and Height
    // properties will always be integers. ActualWidth/Height
    // may not be integers, so they are cast to integers.
    uint actualWidth = (uint)imgelt.ActualWidth;
    uint actualHeight = (uint)imgelt.ActualHeight;
    if ((actualWidth > 0 && actualHeight > 0) &&
        (actualWidth != (uint)d3dimg.Width || actualHeight != (uint)d3dimg.Height))
    {
        HRESULT.Check(SetSize(actualWidth, actualHeight));
    }
}
    // It's possible for Rendering to call back twice in the same frame
            // so only render when we haven't already rendered in this frame.
            if (d3dimg.IsFrontBufferAvailable && _lastRender != args.RenderingTime)
            {
                IntPtr pSurface = IntPtr.Zero;
                HRESULT.Check(GetBackBufferNoRef(out pSurface));
                if (pSurface != IntPtr.Zero)
                {
                    d3dimg.Lock();
                    // Repeatedly calling SetBackBuffer with the same IntPtr is
                    // a no-op. There is no performance penalty.
                    d3dimg.SetBackBuffer(D3DResourceType.IDirect3DSurface9, pSurface);
                    HRESULT.Check(Render());
                    d3dimg.AddDirtyRect(new Int32Rect(0, 0, d3dimg.PixelWidth, d3dimg.PixelHeight));
                    d3dimg.Unlock();
                    _lastRender = args.RenderingTime;
                }
            }
        }
        DispatcherTimer _sizeTimer;
        DispatcherTimer _adapterTimer;
        TimeSpan _lastRender;
        [DllImport("D3DCode.dll")]
        static extern int GetBackBufferNoRef(out IntPtr pSurface);
        [DllImport("D3DCode.dll")]
        static extern int SetSize(uint width, uint height);
        [DllImport("D3DCode.dll")]
        static extern int SetAlpha(bool useAlpha);
        [DllImport("D3DCode.dll")]
        static extern int SetNumDesiredSamples(uint numSamples);
        [StructLayout(LayoutKind.Sequential)]
        struct POINT
        {
            public POINT(Point p)
            {
                x = (int)p.X;
                y = (int)p.Y;
            }
            public int x;
            public int y;
        }
        [DllImport("D3DCode.dll")]
        static extern int SetAdapter(POINT screenSpacePoint);
        [DllImport("D3DCode.dll")]
        static extern int Render();
        [DllImport("D3DCode.dll")]
        static extern void Destroy();
    }
          <Window x:Class="D3DHost.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:i="clr-namespace:System.Windows.Interop;assembly=PresentationCore"
          Title="MainWindow" Height="300" Width="300" Background="PaleGoldenrod">
          <Grid>
              <Image x:Name="imgelt">
                  <Image.Source>
                       <i:D3DImage x:Name="d3dimg" />
                  </Image.Source>
              </Image>
          </Grid>
      </Window>
See also
   D3DImage
   Performance Considerations for Direct3D9 and WPF Interoperability
       Performance
       11/21/2022 • 2 minutes to read • Edit Online
Achieving optimal application performance requires forethought in application design and an understanding of
best practices for WPF applications.
In This Section
Graphics Rendering Tiers
Optimizing WPF Application Performance
Walkthrough: Caching Application Data in a WPF Application
Reference
RenderCapability
Tier
PresentationTraceSources
See also
   Layout
   Animation Tips and Tricks
       Graphics Rendering Tiers
       11/21/2022 • 6 minutes to read • Edit Online
A rendering tier defines a level of graphics hardware capability and performance for a device that runs a WPF
application.
Graphics Hardware
The features of the graphics hardware that most impact the rendering tier levels are:
   Video RAM The amount of video memory on the graphics hardware determines the size and number of
   buffers that can be used for compositing graphics.
   Pixel Shader A pixel shader is a graphics processing function that calculates effects on a per-pixel basis.
   Depending on the resolution of the displayed graphics, there could be several million pixels that need to
   be processed for each display frame.
   Ver tex Shader A vertex shader is a graphics processing function that performs mathematical operations
   on the vertex data of the object.
   Multitexture Suppor t Multitexture support refers to the ability to apply two or more distinct textures
   during a blending operation on a 3D graphics object. The degree of multitexture support is determined
   by the number of multitexture units on the graphics hardware.
A rendering tier value of 1 or 2 means that most of the graphics features of WPF will use hardware acceleration
if the necessary system resources are available and have not been exhausted. This corresponds to a DirectX
version that is greater than or equal to 9.0.
The following table shows the differences in graphics hardware requirements for rendering tier 1 and rendering
tier 2:
DirectX version Must be greater than or equal to 9.0. Must be greater than or equal to 9.0.
  Video RAM                                 Must be greater than or equal to 60         Must be greater than or equal to 120
                                            MB.                                         MB.
  Pixel shader                              Version level must greater than or          Version level must greater than or
                                            equal to 2.0.                               equal to 2.0.
The following features and capabilities are hardware accelerated for rendering tier 1 and rendering tier 2:
F EAT URE N OT ES
  3D lighting calculations                                        WPF performs per-vertex lighting, which means that a light
                                                                  intensity must be calculated at each vertex for each material
                                                                  applied to a mesh.
  Text rendering                                                  Subpixel font rendering uses available pixel shaders on the
                                                                  graphics hardware.
The following features and capabilities are hardware accelerated only for rendering tier 2:
F EAT URE N OT ES
F EAT URE N OT ES
  Printed content                                            All printed content is rendered using the WPF software
                                                             pipeline.
  Rasterized content that uses RenderTargetBitmap            Any content rendered by using the Render method of
                                                             RenderTargetBitmap.
  Tiled content that uses TileBrush                          Any tiled content in which the TileMode property of the
                                                             TileBrush is set to Tile.
  Surfaces that exceed the maximum texture size of the       For most graphics hardware, large surfaces are 2048x2048
  graphics hardware                                          or 4096x4096 pixels in size.
  Any operation whose video RAM requirement exceeds the      You can monitor application video RAM usage by using the
  memory of the graphics hardware                            Perforator tool that is included in the WPF Performance Suite
                                                             in the Windows SDK.
                                                             - WindowStyle = None
                                                             - AllowsTransparency = true
                                                             - Background = Transparent
Other Resources
The following resources can help you analyze the performance characteristics of your WPF application.
Graphics Rendering Registry Settings
WPF provides four registry settings for controlling WPF rendering:
Disable Hardware Acceleration Option Specifies whether hardware acceleration should be enabled.
  Required Video Driver Date Setting                         Specifies whether the system disables hardware acceleration
                                                             for drivers released before November 2004.
Use Reference Rasterizer Option Specifies whether WPF should use the reference rasterizer.
These settings can be accessed by any external configuration utility that knows how to reference the WPF
registry settings. These settings can also be created or modified by accessing the values directly by using the
Windows Registry Editor. For more information, see Graphics Rendering Registry Settings.
WPF Performance Profiling Tools
WPF provides a suite of performance profiling tools that allow you to analyze the run-time behavior of your
application and determine the types of performance optimizations you can apply. The following table lists the
performance profiling tools that are included in the Windows SDK tool, WPF Performance Suite:
TO O L DESC RIP T IO N
  Visual Profiler                                            Use for profiling the use of WPF services, such as layout and
                                                             event handling, by elements in the visual tree.
The WPF Performance Suite provides a rich, graphical view of performance data. For more information about
WPF performance tools, see WPF Performance Suite.
DirectX Diagnostic Tool
The DirectX Diagnostic Tool, Dxdiag.exe, is designed to help you troubleshoot DirectX-related issues. The default
installation folder for the DirectX Diagnostic Tool is:
~\Windows\System32
When you run the DirectX Diagnostic Tool, the main window contains a set of tabs that allow you to display and
diagnose DirectX-related information. For example, the System tab provides system information about your
computer and specifies the version of DirectX that is installed on your computer.
DirectX Diagnostic Tool main window
See also
   RenderCapability
   RenderOptions
   Optimizing WPF Application Performance
   WPF Performance Suite
   Graphics Rendering Registry Settings
   Animation Tips and Tricks
       Optimizing WPF Application Performance
       11/21/2022 • 2 minutes to read • Edit Online
This section is intended as a reference for WPF, you should first familiarize yourself with both platforms. This
section assumes working knowledge of both, and is written for programmers who already know enough to get
their applications up and running.
  NOTE
  The performance data provided in this section are based on WPF applications running on a 2.8 GHz PC with 512 RAM
  and an ATI Radeon 9700 graphics card.
In This Section
Planning for Application Performance
Taking Advantage of Hardware
Layout and Design
2D Graphics and Imaging
Object Behavior
Application Resources
Text
Data Binding
Controls
Other Performance Recommendations
Application Startup Time
See also
   RenderOptions
   RenderCapability
   Graphics Rendering Tiers
   WPF Graphics Rendering Overview
   Layout
   Trees in WPF
   Drawing Objects Overview
   Using DrawingVisual Objects
   Dependency Properties Overview
   Freezable Objects Overview
   XAML Resources
   Documents in WPF
   Drawing Formatted Text
Typography in WPF
Data Binding Overview
Navigation Overview
Animation Tips and Tricks
Walkthrough: Caching Application Data in a WPF Application
       Planning for Application Performance
       11/21/2022 • 2 minutes to read • Edit Online
The success of achieving your performance goals depends on how well you develop your performance strategy.
Planning is the first stage in developing any product. This topic describes a few very simple rules for developing
a good performance strategy.
Define Goals
Goals help you to determine whether an application is performing faster or slower. You should define goals for
all of your scenarios. All performance goals that you define should be based on your customers' expectations. It
may be difficult to set performance goals early on in the application development cycle, when there are still
many unresolved issues. However, it is better to set an initial goal and revise it later than not to have a goal at all.
See also
   Optimizing WPF Application Performance
   Taking Advantage of Hardware
   Layout and Design
   2D Graphics and Imaging
   Object Behavior
   Application Resources
   Text
   Data Binding
   Other Performance Recommendations
       Optimizing Performance: Taking Advantage of
       Hardware
       11/21/2022 • 3 minutes to read • Edit Online
The internal architecture of WPF has two rendering pipelines, hardware and software. This topic provides
information about these rendering pipelines to help you make decisions about performance optimizations of
your applications.
See also
   Optimizing WPF Application Performance
   Planning for Application Performance
   Layout and Design
   2D Graphics and Imaging
   Object Behavior
   Application Resources
   Text
   Data Binding
   Other Performance Recommendations
       Optimizing Performance: Layout and Design
       11/21/2022 • 3 minutes to read • Edit Online
The design of your WPF application can impact its performance by creating unnecessary overhead in calculating
layout and validating object references. The construction of objects, particularly at run time, can affect the
performance characteristics of your application.
This topic provides performance recommendations in these areas.
Layout
The term "layout pass" describes the process of measuring and arranging the members of a Panel-derived
object's collection of children, and then drawing them onscreen. The layout pass is a mathematically-intensive
process—the larger the number of children in the collection, the greater the number of calculations required.
For example, each time a child UIElement object in the collection changes its position, it has the potential to
trigger a new pass by the layout system. Because of the close relationship between object characteristics and
layout behavior, it's important to understand the type of events that can invoke the layout system. Your
application will perform better by reducing as much as possible any unnecessary invocations of the layout pass.
The layout system completes two passes for each child member in a collection: a measure pass, and an arrange
pass. Each child object provides its own overridden implementation of the Measure and Arrange methods in
order to provide its own specific layout behavior. At its simplest, layout is a recursive system that leads to an
element being sized, positioned, and drawn onscreen.
   A child UIElement object begins the layout process by first having its core properties measured.
   The object's FrameworkElement properties that are related to size, such as Width, Height, and Margin, are
   evaluated.
   Panel-specific logic is applied, such as the Dock property of the DockPanel, or the Orientation property of
   the StackPanel.
   Content is arranged, or positioned, after all child objects have been measured.
   The collection of child objects is drawn to the screen.
The layout pass process is invoked again if any of the following actions occur:
   A child object is added to the collection.
   A LayoutTransform is applied to the child object.
   The UpdateLayout method is called for the child object.
   When a change occurs to the value of a dependency property that is marked with metadata affecting the
   measure or arrange passes.
Use the Most Efficient Panel where Possible
The complexity of the layout process is directly based on the layout behavior of the Panel-derived elements you
use. For example, a Grid or StackPanel control provides much more functionality than a Canvas control. The
price for this greater increase in functionality is a greater increase in performance costs. However, if you do not
require the functionality that a Grid control provides, you should use the less costly alternatives, such as a
Canvas or a custom panel.
For more information, see Panels Overview.
Update Rather than Replace a RenderTransform
You may be able to update a Transform rather than replacing it as the value of a RenderTransform property. This
is particularly true in scenarios that involve animation. By updating an existing Transform, you avoid initiating an
unnecessary layout calculation.
Build Your Tree Top-Down
When a node is added or removed from the logical tree, property invalidations are raised on the node's parent
and all its children. As a result, a top-down construction pattern should always be followed to avoid the cost of
unnecessary invalidations on nodes that have already been validated. The following table shows the difference
in execution speed between building a tree top-down versus bottom-up, where the tree is 150 levels deep with a
single TextBlock and DockPanel at each level.
Top-down 11 96
The following code example demonstrates how to create a tree top down.
         myCanvas.Children.Add(parentPanel);
         myCanvas.Children.Add(textBlock);
       myCanvas.Children.Add(parentPanel)
       myCanvas.Children.Add(textBlock)
See also
   Optimizing WPF Application Performance
   Planning for Application Performance
   Taking Advantage of Hardware
   2D Graphics and Imaging
   Object Behavior
   Application Resources
   Text
   Data Binding
   Other Performance Recommendations
   Layout
       Optimizing Performance: 2D Graphics and Imaging
       11/21/2022 • 6 minutes to read • Edit Online
WPF provides a wide range of 2D graphics and imaging functionality that can be optimized for your application
requirements. This topic provides information about performance optimization in those areas.
StreamGeometry Objects
The StreamGeometry object is a lightweight alternative to PathGeometry for creating geometric shapes. Use a
StreamGeometry when you need to describe a complex geometry. StreamGeometry is optimized for handling
many PathGeometry objects and performs better when compared to using many individual PathGeometry
objects.
The following example uses attribute syntax to create a triangular StreamGeometry in XAML.
   <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <StackPanel>
     </StackPanel>
   </Page>
For more information on StreamGeometry objects, see Create a Shape Using a StreamGeometry.
DrawingVisual Objects
The DrawingVisual object is a lightweight drawing class that is used to render shapes, images, or text. This class
is considered lightweight because it does not provide layout or event handling, which improves its performance.
For this reason, drawings are ideal for backgrounds and clip art. For more information, see Using DrawingVisual
Objects.
Images
WPF imaging provides a significant improvement over the imaging capabilities in previous versions of
Windows. Imaging capabilities, such as displaying a bitmap or using an image on a common control, were
primarily handled by the Microsoft Windows Graphics Device Interface (GDI) or Microsoft Windows GDI+
application programming interface (API). These APIs provided baseline imaging functionality but lacked features
such as support for codec extensibility and high fidelity image support. WPF Imaging APIs have been
redesigned to overcome the shortcomings of GDI and GDI+ and provide a new set of APIs to display and use
images within your applications.
When using images, consider the following recommendations for gaining better performance:
   If your application requires you to display thumbnail images, consider creating a reduced-sized version of
   the image. By default, WPF loads your image and decodes it to its full size. If you only want a thumbnail
   version of the image, WPF unnecessary decodes the image to its full-size and then scales it down to a
   thumbnail size. To avoid this unnecessary overhead, you can either request WPF to decode the image to a
   thumbnail size, or request WPF to load a thumbnail size image.
   Always decode the image to desired size and not to the default size. As mentioned above, request WPF to
   decode your image to a desired size and not the default full size. You will reduce not only your
   application's working set, but execution speed as well.
   If possible, combine the images into a single image, such as a film strip composed of multiple images.
   For more information, see Imaging Overview.
BitmapScalingMode
When animating the scale of any bitmap, the default high-quality image resampling algorithm can sometimes
consume sufficient system resources to cause frame rate degradation, effectively causing animations to stutter.
By setting the BitmapScalingMode property of the RenderOptions object to LowQuality, you can create a
smoother animation when scaling a bitmap. LowQuality mode tells the WPF rendering engine to switch from a
quality-optimized algorithm to a speed-optimized algorithm when processing images.
The following example shows how to set the BitmapScalingMode for an image object.
   // Set the bitmap scaling mode for the image to render faster.
   RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality);
   ' Set the bitmap scaling mode for the image to render faster.
   RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality)
CachingHint
By default, WPF does not cache the rendered contents of TileBrush objects, such as DrawingBrush and
VisualBrush. In static scenarios where the contents or use of the TileBrush in the scene aren't changing, this
makes sense, since it conserves video memory. It does not make as much sense when a TileBrush with static
content is used in a non-static way—for example, when a static DrawingBrush or VisualBrush is mapped to the
surface of a rotating 3D object. The default behavior of WPF is to re-render the entire content of the
DrawingBrush or VisualBrush for every frame, even though the content is unchanging.
By setting the CachingHint property of the RenderOptions object to Cache, you can increase performance by
using cached versions of the tiled brush objects.
The CacheInvalidationThresholdMinimum and CacheInvalidationThresholdMaximum property values are
relative size values that determine when the TileBrush object should be regenerated due to changes in scale. For
example, by setting the CacheInvalidationThresholdMaximum property to 2.0, the cache for the TileBrush only
needs to be regenerated when its size exceeds twice the size of the current cache.
The following example shows how to use the caching hint option for a DrawingBrush.
   // Set the minimum and maximum relative sizes for regenerating the tiled brush.
   // The tiled brush will be regenerated and re-cached when its size is
   // 0.5x or 2x of the current cached size.
   RenderOptions.SetCacheInvalidationThresholdMinimum(drawingBrush, 0.5);
   RenderOptions.SetCacheInvalidationThresholdMaximum(drawingBrush, 2.0);
 Dim drawingBrush As New DrawingBrush()
 ' Set the minimum and maximum relative sizes for regenerating the tiled brush.
 ' The tiled brush will be regenerated and re-cached when its size is
 ' 0.5x or 2x of the current cached size.
 RenderOptions.SetCacheInvalidationThresholdMinimum(drawingBrush, 0.5)
 RenderOptions.SetCacheInvalidationThresholdMaximum(drawingBrush, 2.0)
See also
 Optimizing WPF Application Performance
 Planning for Application Performance
 Taking Advantage of Hardware
 Layout and Design
 Object Behavior
 Application Resources
 Text
 Data Binding
 Other Performance Recommendations
 Animation Tips and Tricks
       Optimizing Performance: Object Behavior
       11/21/2022 • 7 minutes to read • Edit Online
Understanding the intrinsic behavior of WPF objects will help you make the right tradeoffs between
functionality and performance.
Freezable Objects
A Freezable is a special type of object that has two states: unfrozen and frozen. Freezing objects whenever
possible improves the performance of your application and reduces its working set. For more information, see
Freezable Objects Overview.
Each Freezable has a Changed event that is raised whenever it changes. However, change notifications are costly
in terms of application performance.
Consider the following example in which each Rectangle uses the same Brush object:
   rectangle_1.Fill = myBrush;
   rectangle_2.Fill = myBrush;
   rectangle_3.Fill = myBrush;
   // ...
   rectangle_10.Fill = myBrush;
   rectangle_1.Fill = myBrush
   rectangle_2.Fill = myBrush
   rectangle_3.Fill = myBrush
   ' ...
   rectangle_10.Fill = myBrush
By default, WPF provides an event handler for the SolidColorBrush object's Changed event in order to invalidate
the Rectangle object's Fill property. In this case, each time the SolidColorBrush has to fire its Changed event it is
required to invoke the callback function for each Rectangle—the accumulation of these callback function
invocations impose a significant performance penalty. In addition, it is very performance intensive to add and
remove handlers at this point since the application would have to traverse the entire list to do so. If your
application scenario never changes the SolidColorBrush, you will be paying the cost of maintaining Changed
event handlers unnecessarily.
Freezing a Freezable can improve its performance, because it no longer needs to expend resources on
maintaining change notifications. The table below shows the size of a simple SolidColorBrush when its IsFrozen
property is set to true , compared to when it is not. This assumes applying one brush to the Fill property of ten
Rectangle objects.
STAT E SIZ E
   For i As Integer = 0 To 9
       ' Create a Rectangle using a non-frozed Brush.
       Dim rectangleNonFrozen As New Rectangle()
       rectangleNonFrozen.Fill = nonFrozenBrush
On the assignment of myBrush to myRectangle.Fill , a delegate pointing back to the Rectangle object will be
added to the SolidColorBrush object's Changed event. This means the following code does not actually make
 myRect eligible for garbage collection:
   myRectangle = null;
myRectangle = Nothing
In this case myBrush is still keeping myRectangle alive and will call back to it when it fires its Changed event.
Note that assigning myBrush to the Fill property of a new Rectangle will simply add another event handler to
 myBrush .
The recommended way to clean up these types of objects is to remove the Brush from the Fill property, which
will in turn remove the Changed event handler.
   myRectangle.Fill = null;
   myRectangle = null;
   myRectangle.Fill = Nothing
   myRectangle = Nothing
H O ST PA N EL REN DER T IM E ( M S)
StackPanel 3210
VirtualizingStackPanel 46
See also
   Optimizing WPF Application Performance
   Planning for Application Performance
   Taking Advantage of Hardware
   Layout and Design
   2D Graphics and Imaging
Application Resources
Text
Data Binding
Other Performance Recommendations
       Optimizing Performance: Application Resources
       11/21/2022 • 2 minutes to read • Edit Online
WPF allows you to share application resources so that you can support a consistent look or behavior across
similar-typed elements. This topic provides a few recommendations in this area that can help you improve the
performance of your applications.
For more information on resources, see XAML Resources.
Sharing resources
If your application uses custom controls and defines resources in a ResourceDictionary (or XAML Resources
node), it is recommended that you either define the resources at the Application or Window object level, or
define them in the default theme for the custom controls. Defining resources in a custom control's
ResourceDictionary imposes a performance impact for every instance of that control. For example, if you have
performance-intensive brush operations defined as part of the resource definition of a custom control and
many instances of the custom control, the application's working set will increase significantly.
To illustrate this point, consider the following. Let's say you are developing a card game using WPF. For most
card games, you need 52 cards with 52 different faces. You decide to implement a card custom control and you
define 52 brushes (each representing a card face) in the resources of your card custom control. In your main
application, you initially create 52 instances of this card custom control. Each instance of the card custom control
generates 52 instances of Brush objects, which gives you a total of 52 * 52 Brush objects in your application. By
moving the brushes out of the card custom control resources to the Application or Window object level, or
defining them in the default theme for the custom control, you reduce the working set of the application, since
you are now sharing the 52 brushes among 52 instances of the card control.
   <StackPanel.Resources>
     <SolidColorBrush x:Key="myBrush" Color="Teal"/>
   </StackPanel.Resources>
See also
   Optimizing WPF Application Performance
   Planning for Application Performance
   Taking Advantage of Hardware
   Layout and Design
2D Graphics and Imaging
Object Behavior
Text
Data Binding
Other Performance Recommendations
       Optimizing Performance: Text
       11/21/2022 • 9 minutes to read • Edit Online
WPF includes support for the presentation of text content through the use of feature-rich user interface (UI)
controls. In general you can divide text rendering in three layers:
1. Using the Glyphs and GlyphRun objects directly.
2. Using the FormattedText object.
3. Using high-level controls, such as the TextBlock and FlowDocument objects.
This topic provides text rendering performance recommendations.
  NOTE
  Glyphs and GlyphRun are designed for fixed-format document presentation and print scenarios. UI scenarios, see the
  Typography in WPF.
The following examples show how to define properties for a Glyphs object in XAML. The examples assume that
the Arial, Courier New, and Times New Roman fonts are installed in the C:\WINDOWS\Fonts folder on the
local computer.
   <!-- The example shows how to use a Glyphs object. -->
   <Page
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     >
<StackPanel Background="PowderBlue">
         <Glyphs
            FontUri               =   "C:\WINDOWS\Fonts\TIMES.TTF"
            FontRenderingEmSize   =   "100"
            StyleSimulations      =   "BoldSimulation"
            UnicodeString         =   "Hello World!"
            Fill                  =   "Black"
            OriginX               =   "100"
            OriginY               =   "200"
         />
      </StackPanel>
   </Page>
Using DrawGlyphRun
If you have custom control and you want to render glyphs, use the DrawGlyphRun method.
WPF also provides lower-level services for custom text formatting through the use of the FormattedText object.
The most efficient way of rendering text in Windows Presentation Foundation (WPF) is by generating text
content at the glyph level using Glyphs and GlyphRun. However, the cost of this efficiency is the loss of easy to
use rich text formatting, which are built-in features of Windows Presentation Foundation (WPF) controls, such as
TextBlock and FlowDocument.
FormattedText Object
The FormattedText object allows you to draw multi-line text, in which each character in the text can be
individually formatted. For more information, see Drawing Formatted Text.
To create formatted text, call the FormattedText constructor to create a FormattedText object. Once you have
created the initial formatted text string, you can apply a range of formatting styles. If your application wants to
implement its own layout, then the FormattedText object is better choice than using a control, such as TextBlock.
For more information on the FormattedText object, see Drawing Formatted Text .
The FormattedText object provides low-level text formatting capability. You can apply multiple formatting styles
to one or more characters. For example, you could call both the SetFontSize and SetForegroundBrush methods
to change the formatting of the first five characters in the text.
The following code example creates a FormattedText object and renders it.
protected override void OnRender(DrawingContext drawingContext)
{
    string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor";
    // Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
    formattedText.MaxTextWidth = 300;
    formattedText.MaxTextHeight = 240;
    // Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
    // The font size is calculated in terms of points -- not as device-independent pixels.
    formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
    // Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
    formattedText.SetFontWeight(FontWeights.Bold, 6, 11);
    // Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
    formattedText.SetForegroundBrush(
                            new LinearGradientBrush(
                            Colors.Orange,
                            Colors.Teal,
                            90.0),
                            6, 11);
    // Use an Italic font style beginning at the 28th character and continuing for 28 characters.
    formattedText.SetFontStyle(FontStyles.Italic, 28, 28);
       ' Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
       formattedText.MaxTextWidth = 300
       formattedText.MaxTextHeight = 240
       ' Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
       ' The font size is calculated in terms of points -- not as device-independent pixels.
       formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5)
       ' Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
       formattedText.SetFontWeight(FontWeights.Bold, 6, 11)
       ' Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
       formattedText.SetForegroundBrush(New LinearGradientBrush(Colors.Orange, Colors.Teal, 90.0), 6, 11)
       ' Use an Italic font style beginning at the 28th character and continuing for 28 characters.
       formattedText.SetFontStyle(FontStyles.Italic, 28, 28)
       ' Draw the formatted text string to the DrawingContext of the control.
       drawingContext.DrawText(formattedText, New Point(10, 0))
   End Sub
</FlowDocument>
   <!-- TextBlock is used to set text properties, which is more efficient. -->
   <TextBlock FontWeight="Bold">
     Hello, world
   </TextBlock>
The following table shows the cost of displaying 1000 TextBlock objects with and without an explicit Run.
Label.Content 835
  TextBlock.Text                                                      242
Hyperlink
The Hyperlink object is an inline-level flow content element that allows you to host hyperlinks within the flow
content.
Combine Hyperlinks in One TextBlock Object
You can optimize the use of multiple Hyperlink elements by grouping them together within the same TextBlock.
This helps to minimize the number of objects you create in your application. For example, you may want to
display multiple hyperlinks, such as the following:
MSN Home | My MSN
The following markup example shows multiple TextBlock elements used to display the hyperlinks:
   <TextBlock>
     <Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
   </TextBlock>
The following markup example shows a more efficient way of displaying the hyperlinks, this time, using a single
TextBlock:
The following markup sample shows a Hyperlink defined with and without an underline:
   <!-- Hyperlink with default underline. -->
   <Hyperlink NavigateUri="http://www.msn.com">
     MSN Home
   </Hyperlink>
The following table shows the performance cost of displaying 1000 Hyperlink elements with and without an
underline.
See also
   Optimizing WPF Application Performance
   Planning for Application Performance
Taking Advantage of Hardware
Layout and Design
2D Graphics and Imaging
Object Behavior
Application Resources
Data Binding
Other Performance Recommendations
        Optimizing Performance: Data Binding
        11/21/2022 • 5 minutes to read • Edit Online
Windows Presentation Foundation (WPF) data binding provides a simple and consistent way for applications to
present and interact with data. Elements can be bound to data from a variety of data sources in the form of CLR
objects and XML.
This topic provides data binding performance recommendations.
  To a DependencyProperty of a                90                                                  263
  DependencyObject.
Binding to an ItemsSource
Consider a scenario in which you have a CLR List<T> object that holds a list of employees that you want to
display in a ListBox. To create a correspondence between these two objects, you would bind your employee list
to the ItemsSource property of the ListBox. However, suppose you have a new employee joining your group. You
might think that in order to insert this new person into your bound ListBox values, you would simply add this
person to your employee list and expect this change to be recognized by the data binding engine automatically.
That assumption would prove false; in actuality, the change will not be reflected in the ListBox automatically. This
is because the CLR List<T> object does not automatically raise a collection changed event. In order to get the
ListBox to pick up the changes, you would have to recreate your list of employees and re-attach it to the
ItemsSource property of the ListBox. While this solution works, it introduces a huge performance impact. Each
time you reassign the ItemsSource of ListBox to a new object, the ListBox first throws away its previous items
and regenerates its entire list. The performance impact is magnified if your ListBox maps to a complex
DataTemplate.
A very efficient solution to this problem is to make your employee list an ObservableCollection<T>. An
ObservableCollection<T> object raises a change notification which the data binding engine can receive. The
event adds or removes an item from an ItemsControl without the need to regenerate the entire list.
The table below shows the time it takes to update the ListBox (with UI virtualization turned off) when one item is
added. The number in the first row represents the elapsed time when the CLR List<T> object is bound to ListBox
element's ItemsSource. The number in the second row represents the elapsed time when an
ObservableCollection<T> is bound to the ListBox element's ItemsSource. Note the significant time savings using
the ObservableCollection<T> data binding strategy.
To an ObservableCollection<T> 20
See also
   Optimizing WPF Application Performance
   Planning for Application Performance
   Taking Advantage of Hardware
   Layout and Design
   2D Graphics and Imaging
   Object Behavior
   Application Resources
   Text
   Other Performance Recommendations
   Data Binding Overview
   Walkthrough: Caching Application Data in a WPF Application
       Optimizing performance: Controls
       11/21/2022 • 4 minutes to read • Edit Online
Windows Presentation Foundation (WPF) includes many of the common user-interface (UI) components that are
used in most Windows applications. This topic contains techniques for improving the performance of your UI.
Container recycling
An optimization to UI virtualization added in the .NET Framework 3.5 SP1 for controls that inherit from
ItemsControl is container recycling, which can also improve scrolling performance. When an ItemsControl that
uses UI virtualization is populated, it creates an item container for each item that scrolls into view and destroys
the item container for each item that scrolls out of view. Container recycling enables the control to reuse the
existing item containers for different data items, so that item containers are not constantly created and
destroyed as the user scrolls the ItemsControl. You can choose to enable item recycling by setting the
VirtualizationMode attached property to Recycling.
Any ItemsControl that supports virtualization can use container recycling. For an example of how to enable
container recycling on a ListBox, see Improve the Scrolling Performance of a ListBox.
Optimizing templates
The visual tree contains all the visual elements in an application. In addition to the objects directly created, it also
contains objects due to template expansion. For example, when you create a Button, you also get
ClassicBorderDecorator and ContentPresenter objects in the visual tree. If you haven't optimized your control
templates, you may be creating a lot of extra unnecessary objects in the visual tree. For more information on the
visual tree, see WPF Graphics Rendering Overview.
Deferred scrolling
By default, when the user drags the thumb on a scrollbar, the content view continuously updates. If scrolling is
slow in your control, consider using deferred scrolling. In deferred scrolling, the content is updated only when
the user releases the thumb.
To implement deferred scrolling, set the IsDeferredScrollingEnabled property to true .
IsDeferredScrollingEnabled is an attached property and can be set on ScrollViewer and any control that has a
ScrollViewer in its control template.
See also
  Layout
  Layout and Design
  Data Binding
  Controls
  Styling and Templating
  Walkthrough: Caching Application Data in a WPF Application
       Optimizing Performance: Other Recommendations
       11/21/2022 • 3 minutes to read • Edit Online
This topic provides performance recommendations in addition to the ones covered by the topics in the
Optimizing WPF Application Performance section.
This topic contains the following sections:
   Opacity on Brushes Versus Opacity on Elements
   Navigation to Object
   Hit Testing on Large 3D Surfaces
   CompositionTarget.Rendering Event
   Avoid Using ScrollBarVisibility=Auto
   Configure Font Cache Service to Reduce Start-up Time
Navigation to Object
The NavigationWindow object derives from Window and extends it with content navigation support, primarily
by aggregating NavigationService and the journal. You can update the client area of NavigationWindow by
specifying either a uniform resource identifier (URI) or an object. The following sample shows both methods:
CompositionTarget.Rendering Event
The CompositionTarget.Rendering event causes WPF to continuously animate. If you use this event, detach it at
every opportunity.
See also
   Planning for Application Performance
   Taking Advantage of Hardware
   Layout and Design
   2D Graphics and Imaging
   Object Behavior
Application Resources
Text
Data Binding
Animation Tips and Tricks
       Application Startup Time
       11/21/2022 • 7 minutes to read • Edit Online
The amount of time that is required for a WPF application to start can vary greatly. This topic describes various
techniques for reducing the perceived and actual startup time for a Windows Presentation Foundation (WPF)
application.
Use Ngen.exe
Consider using the Native Image Generator (Ngen.exe) on your application. Using Ngen.exe means trading CPU
consumption for more disk access because the native image generated by Ngen.exe is likely to be larger than
the MSIL image.
To improve the warm startup time, you should always use Ngen.exe on your application, because this avoids the
CPU cost of JIT compilation of the application code.
In some cold startup scenarios, using Ngen.exe can also be helpful. This is because the JIT compiler (mscorjit.dll)
does not have to be loaded.
Having both Ngen and JIT modules can have the worst effect. This is because mscorjit.dll must be loaded, and
when the JIT compiler works on your code, many pages in the Ngen images must be accessed when the JIT
compiler reads the assemblies' metadata.
Ngen and ClickOnce
The way you plan to deploy your application can also make a difference in load time. ClickOnce application
deployment does not support Ngen. If you decide to use Ngen.exe for your application, you will have to use
another deployment mechanism, such as Windows Installer.
For more information, see Ngen.exe (Native Image Generator).
Rebasing and DLL Address Collisions
If you use Ngen.exe, be aware that rebasing can occur when the native images are loaded in memory. If a DLL is
not loaded at its preferred base address because that address range is already allocated, the Windows loader
will load it at another address, which can be a time-consuming operation.
You can use the Virtual Address Dump (Vadump.exe) tool to check if there are modules in which all the pages
are private. If this is the case, the module may have been rebased to a different address. Therefore, its pages
cannot be shared.
For more information about how to set the base address, see Ngen.exe (Native Image Generator).
Optimize Authenticode
Authenticode verification adds to the startup time. Authenticode-signed assemblies have to be verified with the
certification authority (CA). This verification can be time consuming, because it can require connecting to the
network several times to download current certificate revocation lists. It also makes sure that there is a full chain
of valid certificates on the path to a trusted root. This can translate to several seconds of delay while the
assembly is being loaded.
Consider installing the CA certificate on the client computer, or avoid using Authenticode when it is possible. If
you know that your application does not need the publisher evidence, you do not have to pay the cost of
signature verification.
Starting in .NET Framework 3.5, there is a configuration option that allows the Authenticode verification to be
bypassed. To do this, add the following setting to the app.exe.config file:
   <configuration>
       <runtime>
           <generatePublisherEvidence enabled="false"/>
       </runtime>
   </configuration>
See also
   SplashScreen
   AppDomain
   NeutralResourcesLanguageAttribute
   ResourceManager
   Add a Splash Screen to a WPF Application
   Ngen.exe (Native Image Generator)
   <generatePublisherEvidence> Element
       Walkthrough: Caching Application Data in a WPF
       Application
       11/21/2022 • 9 minutes to read • Edit Online
Caching enables you to store data in memory for rapid access. When the data is accessed again, applications can
get the data from the cache instead of retrieving it from the original source. This can improve performance and
scalability. In addition, caching makes data available when the data source is temporarily unavailable.
The .NET Framework provides classes that enable you to use caching in .NET Framework applications. These
classes are located in the System.Runtime.Caching namespace.
  NOTE
  The System.Runtime.Caching namespace is new in the .NET Framework 4. This namespace makes caching is available to all
  .NET Framework applications. In previous versions of the .NET Framework, caching was available only in the System.Web
  namespace and therefore required a dependency on ASP.NET classes.
This walkthrough shows you how to use the caching functionality that is available in the .NET Framework as part
of a Windows Presentation Foundation (WPF) application. In the walkthrough, you cache the contents of a text
file.
Tasks illustrated in this walkthrough include the following:
   Creating a WPF application project.
   Adding a reference to the .NET Framework 4.
   Initializing a cache.
   Adding a cache entry that contains the contents of a text file.
   Providing an eviction policy for the cache entry.
   Monitoring the path of the cached file and notifying the cache instance about changes to the monitored
   item.
Prerequisites
In order to complete this walkthrough, you will need:
   Visual Studio 2010.
   A text file that contains a small amount of text. (You will display the contents of the text file in a message
   box.) The code illustrated in the walkthrough assumes that you are working with the following file:
    c:\cache\cacheText.txt
However, you can use any text file and make small changes to the code in this walkthrough.
     NOTE
     If you do not see the WPF Application template, make sure that you are targeting a version of the .NET
     Framework that supports WPF. In the New Project dialog box, select .NET Framework 4 from the list.
5. In the Name text box, enter a name for your project. For example, you can enter WPFCaching .
6. Select the Create director y for solution check box.
7. Click OK .
   The WPF Designer opens in Design view and displays the MainWindow.xaml file. Visual Studio creates
   the My Project folder, the Application.xaml file, and the MainWindow.xaml file.
  NOTE
  The procedure for changing the .NET Framework target is different in a Visual Basic project and in a Visual C# project.
       using System.Runtime.Caching;
       using System.IO;
      Imports System.Runtime.Caching
      Imports System.IO
3. In the event handler, add the following code to instantiate the cache object:
   The ObjectCache class is a built-in class that provides an in-memory object cache.
4. Add the following code to read the contents of a cache entry named       filecontents   :
5. Add the following code to check whether the cache entry named filecontents exists:
End If
      if (fileContents == null)
      {
   If the specified cache entry does not exist, you must read the text file and add it as a cache entry to the
   cache.
6. In the if/then block, add the following code to create a new CacheItemPolicy object that specifies that
   the cache entry expires after 10 seconds.
      NOTE
      If the text file you want to use is not   c:\cache\cacheText.txt   , specify the path where the text file is that you
      want to use.
 8. Following the code that you added in the previous step, add the following code to add a new
    HostFileChangeMonitor object to the collection of change monitors for the cache entry:
policy.ChangeMonitors.Add(New HostFileChangeMonitor(filePaths))
policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
    The HostFileChangeMonitor object monitors the text file's path and notifies the cache if changes occur. In
    this example, the cache entry will expire if the content of the file changes.
 9. Following the code that you added in the previous step, add the following code to read the contents of
    the text file:
    The date and time timestamp is added so that you will be able to see when the cache entry expires.
10. Following the code that you added in the previous step, add the following code to insert the contents of
    the file into the cache object as a CacheItem instance:
    You specify information about how the cache entry should be evicted by passing the CacheItemPolicy
    object that you created earlier as a parameter.
11. After the   if/then   block, add the following code to display the cached file content in a message box:
MessageBox.Show(fileContents)
       MessageBox.Show(fileContents);
12. In the Build menu, click Build WPFCaching to build your project.
       NOTE
       You can increase the eviction time to 20 seconds or more to allow more time for you to make a change in the file.
 Code Example
 After you have completed this walkthrough, the code for the project you created will resemble the following
 example.
using   System;
using   System.Collections.Generic;
using   System.Linq;
using   System.Text;
using   System.Windows;
using   System.Windows.Controls;
using   System.Windows.Data;
using   System.Windows.Documents;
using   System.Windows.Input;
using   System.Windows.Media;
using   System.Windows.Media.Imaging;
using   System.Windows.Navigation;
using   System.Windows.Shapes;
using   System.Runtime.Caching;
using   System.IO;
namespace WPFCaching
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
              if (fileContents == null)
              {
                  CacheItemPolicy policy = new CacheItemPolicy();
                  policy.AbsoluteExpiration =
                      DateTimeOffset.Now.AddSeconds(10.0);
                  policy.ChangeMonitors.Add(new
                      HostFileChangeMonitor(filePaths));
Class MainWindow
See also
 MemoryCache
 ObjectCache
 System.Runtime.Caching
 Caching in .NET Framework Applications
       Threading Model
       11/21/2022 • 24 minutes to read • Edit Online
WPF developers won't have to write an interface that uses more than one thread. Because multithreaded
programs are complex and difficult to debug, they should be avoided when single-threaded solutions exist.
No matter how well architected, however, no UI framework will ever be able to provide a single-threaded
solution for every sort of problem. WPF comes close, but there are still situations where multiple threads
improve user interface (UI) responsiveness or application performance. After discussing some background
material, this paper explores some of these situations and then concludes with a discussion of some lower-level
details.
  NOTE
  This topic discusses threading by using the BeginInvoke method for asynchronous calls. You can also make asynchronous
  calls by calling the InvokeAsync method, which take an Action or Func<TResult> as a parameter. The InvokeAsync method
  returns a DispatcherOperation or DispatcherOperation<TResult>, which has a Task property. You can use the await
  keyword with either the DispatcherOperation or the associated Task. If you need to wait synchronously for the Task that is
  returned by a DispatcherOperation or DispatcherOperation<TResult>, call the DispatcherOperationWait extension
  method. Calling Task.Wait will result in a deadlock. For more information about using a Task to perform asynchronous
  operations, see Task-based asynchronous programming. The Invoke method also has overloads that take an Action or
  Func<TResult> as a parameter. You can use the Invoke method to make synchronous calls by passing in a delegate,
  Action or Func<TResult>.
This simple application counts upwards from three, searching for prime numbers. When the user clicks the
Star t button, the search begins. When the program finds a prime, it updates the user interface with its
discovery. At any point, the user can stop the search.
Although simple enough, the prime number search could go on forever, which presents some difficulties. If we
handled the entire search inside of the click event handler of the button, we would never give the UI thread a
chance to handle other events. The UI would be unable to respond to input or process messages. It would never
repaint and never respond to button clicks.
We could conduct the prime number search in a separate thread, but then we would need to deal with
synchronization issues. With a single-threaded approach, we can directly update the label that lists the largest
prime found.
If we break up the task of calculation into manageable chunks, we can periodically return to the Dispatcher and
process events. We can give WPF an opportunity to repaint and process input.
The best way to split processing time between calculation and event handling is to manage calculation from the
Dispatcher. By using the BeginInvoke method, we can schedule prime number checks in the same queue that UI
events are drawn from. In our example, we schedule only a single prime number check at a time. After the prime
number check is complete, we schedule the next check immediately. This check proceeds only after pending UI
events have been handled.
Microsoft Word accomplishes spell checking using this mechanism. Spell checking is done in the background
using the idle time of the UI thread. Let's take a look at the code.
The following example shows the XAML that creates the user interface.
   <Window x:Class="SDKSamples.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="Prime Numbers" Width="260" Height="75"
       >
     <StackPanel Orientation="Horizontal" VerticalAlignment="Center" >
       <Button Content="Start"
               Click="StartOrStop"
               Name="startStopButton"
               Margin="5,0,5,0"
               />
       <TextBlock Margin="10,5,0,0">Biggest Prime Found:</TextBlock>
       <TextBlock Name="bigPrime" Margin="4,5,0,0">3</TextBlock>
     </StackPanel>
   </Window>
   using   System;
   using   System.Windows;
   using   System.Windows.Controls;
   using   System.Windows.Threading;
   using   System.Threading;
   namespace SDKSamples
   {
       public partial class Window1 : Window
       {
           public delegate void NextPrimeDelegate();
            // If a prime number.
            if (!NotAPrime)
            {
                bigPrime.Text = num.ToString();
            }
            num += 2;
            if (continueCalculating)
            {
                startStopButton.Dispatcher.BeginInvoke(
                    System.Windows.Threading.DispatcherPriority.SystemIdle,
                    new NextPrimeDelegate(this.CheckNextNumber));
            }
        }
   Namespace SDKSamples
       Partial Public Class MainWindow
           Inherits Window
           Public Delegate Sub NextPrimeDelegate()
                 num += 2
                 If continueCalculating Then
   startStopButton.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.SystemIdle, New
   NextPrimeDelegate(AddressOf Me.CheckNextNumber))
               End If
           End Sub
The following example shows the event handler for the Button.
   private void StartOrStop(object sender, EventArgs e)
   {
       if (continueCalculating)
       {
            continueCalculating = false;
            startStopButton.Content = "Resume";
       }
       else
       {
            continueCalculating = true;
            startStopButton.Content = "Stop";
            startStopButton.Dispatcher.BeginInvoke(
                DispatcherPriority.Normal,
                new NextPrimeDelegate(CheckNextNumber));
       }
   }
Besides updating the text on the Button, this handler is responsible for scheduling the first prime number check
by adding a delegate to the Dispatcher queue. Sometime after this event handler has completed its work, the
Dispatcher will select this delegate for execution.
As we mentioned earlier, BeginInvoke is the Dispatcher member used to schedule a delegate for execution. In
this case, we choose the SystemIdle priority. The Dispatcher will execute this delegate only when there are no
important events to process. UI responsiveness is more important than number checking. We also pass a new
delegate representing the number-checking routine.
   public void CheckNextNumber()
   {
       // Reset flag.
       NotAPrime = false;
       // If a prime number.
       if (!NotAPrime)
       {
           bigPrime.Text = num.ToString();
       }
       num += 2;
       if (continueCalculating)
       {
           startStopButton.Dispatcher.BeginInvoke(
               System.Windows.Threading.DispatcherPriority.SystemIdle,
               new NextPrimeDelegate(this.CheckNextNumber));
       }
   }
       num += 2
       If continueCalculating Then
           startStopButton.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.SystemIdle, New
   NextPrimeDelegate(AddressOf Me.CheckNextNumber))
       End If
   End Sub
This method checks if the next odd number is prime. If it is prime, the method directly updates the bigPrime
TextBlock to reflect its discovery. We can do this because the calculation is occurring in the same thread that was
used to create the component. Had we chosen to use a separate thread for the calculation, we would have to use
a more complicated synchronization mechanism and execute the update in the UI thread. We’ll demonstrate this
situation next.
For the complete source code for this sample, see the Single-Threaded Application with Long-Running
Calculation Sample
   using   System;
   using   System.Windows;
   using   System.Windows.Controls;
   using   System.Windows.Media;
   using   System.Windows.Media.Animation;
   using   System.Windows.Media.Imaging;
   using   System.Windows.Shapes;
   using   System.Windows.Threading;
   using   System.Threading;
   namespace SDKSamples
   {
       public partial class Window1 : Window
       {
           // Delegates to be used in placking jobs onto the Dispatcher.
           private delegate void NoArgDelegate();
           private delegate void OneArgDelegate(String arg);
    fetcher.BeginInvoke(null, null);
}
    if (rand.Next(2) == 0)
    {
         weather = "rainy";
    }
    else
    {
         weather = "sunny";
    }
              //Update UI text
              fetchButton.IsEnabled = true;
              fetchButton.Content = "Fetch Forecast";
              weatherText.Text = weather;
          }
Imports   System.Windows
Imports   System.Windows.Controls
Imports   System.Windows.Media
Imports   System.Windows.Media.Animation
Imports   System.Windows.Media.Imaging
Imports   System.Windows.Shapes
Imports   System.Windows.Threading
Imports   System.Threading
Namespace SDKSamples
    Partial Public Class Window1
        Inherits Window
        ' Delegates to be used in placking jobs onto the Dispatcher.
        Private Delegate Sub NoArgDelegate()
        Private Delegate Sub OneArgDelegate(ByVal arg As String)
               fetcher.BeginInvoke(Nothing, Nothing)
           End Sub
               ' Tried and true method for weather forecasting - random numbers.
               Dim rand As New Random()
               Dim weather As String
               If rand.Next(2) = 0 Then
                    weather = "rainy"
               Else
                    weather = "sunny"
               End If
               'Update UI text
               fetchButton.IsEnabled = True
               fetchButton.Content = "Fetch Forecast"
               weatherText.Text = weather
           End Sub
          fetcher.BeginInvoke(null, null);
      }
          fetcher.BeginInvoke(Nothing, Nothing)
      End Sub
When the button is clicked, we display the clock drawing and start animating it. We disable the button. We
invoke the FetchWeatherFromServer method in a new thread, and then we return, allowing the Dispatcher to
process events while we wait to collect the weather forecast.
   Fetching the Weather
          if (rand.Next(2) == 0)
          {
               weather = "rainy";
          }
          else
          {
               weather = "sunny";
          }
          ' Tried and true method for weather forecasting - random numbers.
          Dim rand As New Random()
          Dim weather As String
          If rand.Next(2) = 0 Then
               weather = "rainy"
          Else
               weather = "sunny"
          End If
To keep things simple, we don’t actually have any networking code in this example. Instead, we simulate the
delay of network access by putting our new thread to sleep for four seconds. In this time, the original UI thread
is still running and responding to events. To show this, we’ve left an animation running, and the minimize and
maximize buttons also continue to work.
When the delay is finished, and we’ve randomly selected our weather forecast, it’s time to report back to the UI
thread. We do this by scheduling a call to UpdateUserInterface in the UI thread using that thread’s Dispatcher.
We pass a string describing the weather to this scheduled method call.
   Updating the UI
          //Update UI text
          fetchButton.IsEnabled = true;
          fetchButton.Content = "Fetch Forecast";
          weatherText.Text = weather;
      }
      Private Sub UpdateUserInterface(ByVal weather As String)
          'Set the weather image
          If weather = "sunny" Then
              weatherIndicatorImage.Source = CType(Me.Resources("SunnyImageSource"), ImageSource)
          ElseIf weather = "rainy" Then
              weatherIndicatorImage.Source = CType(Me.Resources("RainingImageSource"), ImageSource)
          End If
          'Update UI text
          fetchButton.IsEnabled = True
          fetchButton.Content = "Fetch Forecast"
          weatherText.Text = weather
      End Sub
When the Dispatcher in the UI thread has time, it executes the scheduled call to UpdateUserInterface . This
method stops the clock animation and chooses an image to describe the weather. It displays this image and
restores the "fetch forecast" button.
    <Frame Name="placeHolder"
            Width="800"
            Height="550"></Frame>
  </StackPanel>
</Window>
using   System;
using   System.Windows;
using   System.Windows.Controls;
using   System.Windows.Data;
using   System.Windows.Threading;
using   System.Threading;
namespace SDKSamples
{
    public partial class Window1 : Window
    {
   Namespace SDKSamples
       Partial Public Class Window1
           Inherits Window
The following threading segments of this code are the most interesting to us in this context:
This method is called when the "new window" button is clicked. It creates a new thread and starts it
asynchronously.
   private void ThreadStartingPoint()
   {
       Window1 tempWindow = new Window1();
       tempWindow.Show();
       System.Windows.Threading.Dispatcher.Run();
   }
This method is the starting point for the new thread. We create a new window under the control of this thread.
WPF automatically creates a new Dispatcher to manage the new thread. All we have to do to make the window
functional is to start the Dispatcher.
        return weather;
    }
           Return weather
       End Function
GetWeatherAsync would use one of the techniques described earlier, such as creating a background thread, to do
the work asynchronously, not blocking the calling thread.
One of the most important parts of this pattern is calling the MethodName Completed method on the same
thread that called the MethodName Async method to begin with. You could do this using WPF fairly easily, by
storing CurrentDispatcher—but then the nongraphical component could only be used in WPF applications, not
in Windows Forms or ASP.NET programs.
The DispatcherSynchronizationContext class addresses this need—think of it as a simplified version of
Dispatcher that works with other UI frameworks as well.
public class WeatherComponent2 : Component
{
    public string GetWeather()
    {
        return fetchWeatherFromServer();
    }
requestingContext = (DispatcherSynchronizationContext)DispatcherSynchronizationContext.Current;
        // Launch thread
        fetcher.BeginInvoke(null, null);
    }
        GetWeatherCompletedEventArgs e =
            new GetWeatherCompletedEventArgs(null, false, null, weather);
        return e.Weather;
    }
           requestingContext = CType(DispatcherSynchronizationContext.Current,
   DispatcherSynchronizationContext)
           Return e.Weather
       End Function
Nested Pumping
Sometimes it is not feasible to completely lock up the UI thread. Let’s consider the Show method of the
MessageBox class. Show doesn’t return until the user clicks the OK button. It does, however, create a window
that must have a message loop in order to be interactive. While we are waiting for the user to click OK, the
original application window does not respond to user input. It does, however, continue to process paint
messages. The original window redraws itself when covered and revealed.
Some thread must be in charge of the message box window. WPF could create a new thread just for the
message box window, but this thread would be unable to paint the disabled elements in the original window
(remember the earlier discussion of mutual exclusion). Instead, WPF uses a nested message processing system.
The Dispatcher class includes a special method called PushFrame, which stores an application’s current
execution point then begins a new message loop. When the nested message loop finishes, execution resumes
after the original PushFrame call.
In this case, PushFrame maintains the program context at the call to MessageBox.Show, and it starts a new
message loop to repaint the background window and handle input to the message box window. When the user
clicks OK and clears the pop-up window, the nested loop exits and control resumes after the call to Show.
Stale Routed Events
The routed event system in WPF notifies entire trees when events are raised.
   <Canvas MouseLeftButtonDown="handler1"
           Width="100"
           Height="100"
           >
     <Ellipse Width="50"
              Height="50"
              Fill="Blue"
              Canvas.Left="30"
              Canvas.Top="50"
              MouseLeftButtonDown="handler2"
              />
   </Canvas>
When the left mouse button is pressed over the ellipse, handler2 is executed. After handler2 finishes, the event
is passed along to the Canvas object, which uses handler1 to process it. This happens only if handler2 does not
explicitly mark the event object as handled.
It’s possible that handler2 will take a great deal of time processing this event. handler2 might use PushFrame
to begin a nested message loop that doesn’t return for hours. If handler2 does not mark the event as handled
when this message loop is complete, the event is passed up the tree even though it is very old.
Reentrancy and Locking
The locking mechanism of the common language runtime (CLR) doesn’t behave exactly as one might imagine;
one might expect a thread to cease operation completely when requesting a lock. In actuality, the thread
continues to receive and process high-priority messages. This helps prevent deadlocks and make interfaces
minimally responsive, but it introduces the possibility for subtle bugs. The vast majority of the time you don’t
need to know anything about this, but under rare circumstances (usually involving Win32 window messages or
COM STA components) this can be worth knowing.
Most interfaces are not built with thread safety in mind because developers work under the assumption that a
UI is never accessed by more than one thread. In this case, that single thread may make environmental changes
at unexpected times, causing those ill effects that the DispatcherObject mutual exclusion mechanism is
supposed to solve. Consider the following pseudocode:
Most of the time that’s the right thing, but there are times in WPF where such unexpected reentrancy can really
cause problems. So, at certain key times, WPF calls DisableProcessing, which changes the lock instruction for
that thread to use the WPF reentrancy-free lock, instead of the usual CLR lock.
So why did the CLR team choose this behavior? It had to do with COM STA objects and the finalization thread.
When an object is garbage collected, its Finalize method is run on the dedicated finalizer thread, not the UI
thread. And therein lies the problem, because a COM STA object that was created on the UI thread can only be
disposed on the UI thread. The CLR does the equivalent of a BeginInvoke (in this case using Win32’s
 SendMessage ). But if the UI thread is busy, the finalizer thread is stalled and the COM STA object can’t be
disposed, which creates a serious memory leak. So the CLR team made the tough call to make locks work the
way they do.
The task for WPF is to avoid unexpected reentrancy without reintroducing the memory leak, which is why we
don’t block reentrancy everywhere.
See also
   Single-Threaded Application with Long-Running Calculation Sample
      WPF Unmanaged API Reference
      11/21/2022 • 2 minutes to read • Edit Online
Windows Presentation Foundation (WPF) libraries expose a number of unmanaged functions that are intended
for internal use only. They should not be called from user code.
In This Section
Activate Function
CreateIDispatchSTAForwarder Function
Deactivate Function
ForwardTranslateAccelerator Function
LoadFromHistory Function
ProcessUnhandledException Function
SaveToHistory Function
SetFakeActiveWindow Function
See also
  Advanced
       Activate Function (WPF Unmanaged API Reference)
       11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for windows management.
Syntax
   void Activate(
       const ActivateParameters* pParameters,
       __deref_out_ecount(1) LPUNKNOWN* ppInner,
       );
Parameters
pParameters
A pointer to the window's activation parameters.
ppInner
A pointer to the address of a single-element buffer that contains a pointer to an IOleDocument object.
Requirements
Platforms: See .NET Framework System Requirements.
DLL:
In the .NET Framework 3.0 and 3.5: PresentationHostDLL.dll
In the .NET Framework 4 and later: PresentationHost_v0400.dll
.NET Framework Version: Available since 3.0
See also
   WPF Unmanaged API Reference
       CreateIDispatchSTAForwarder Function (WPF
       Unmanaged API Reference)
       11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for thread and windows management.
Syntax
   HRESULT CreateIDispatchSTAForwarder(
      __in IDispatch *pDispatchDelegate,
      __deref_out IDispatch **ppForwarder
   )
Parameters
Property Value/Return Value
pDispatchDelegate
A pointer to an IDispatch interface.
ppForwarder
A pointer to the address of an   IDispatch   interface.
Requirements
Platforms: See .NET Framework System Requirements.
DLL:
In the .NET Framework 3.0 and 3.5: PresentationHostDLL.dll
In the .NET Framework 4 and later: PresentationHost_v0400.dll
.NET Framework Version: Available since 3.0
See also
   WPF Unmanaged API Reference
       Deactivate Function (WPF Unmanaged API
       Reference)
       11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for windows management.
Syntax
   void Deactivate()
Requirements
Platforms: See .NET Framework System Requirements.
DLL:
In the .NET Framework 3.0 and 3.5: PresentationHostDLL.dll
In the .NET Framework 4 and later: PresentationHost_v0400.dll
.NET Framework Version: Available since 3.0
See also
   WPF Unmanaged API Reference
       ForwardTranslateAccelerator Function (WPF
       Unmanaged API Reference)
       11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for windows management.
Syntax
   HRESULT ForwardTranslateAccelerator(
      MSG* pMsg,
      VARIANT_BOOL appUnhandled
   )
Parameters
pMsg
A pointer to a message.
appUnhandled
 true when the app has already been given a chance to handle the input message, but has not handled it;
otherwise, false .
Requirements
Platforms: See .NET Framework System Requirements.
DLL:
In the .NET Framework 3.0 and 3.5: PresentationHostDLL.dll
In the .NET Framework 4 and later: PresentationHost_v0400.dll
.NET Framework Version: Available since 3.0
See also
   WPF Unmanaged API Reference
       LoadFromHistory Function (WPF Unmanaged API
       Reference)
       11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for windows management.
Syntax
   HRESULT LoadFromHistory_export(
           IStream* pHistoryStream,
           IBindCtx* pBindCtx
   )
Parameters
pHistoryStream
A pointer to a stream of history information.
pBindCtx
A pointer to a bind context.
Requirements
Platforms: See .NET Framework System Requirements.
DLL:
In the .NET Framework 3.0 and 3.5: PresentationHostDLL.dll
In the .NET Framework 4 and later: PresentationHost_v0400.dll
.NET Framework Version: Available since 3.0
See also
   WPF Unmanaged API Reference
       ProcessUnhandledException Function (WPF
       Unmanaged API Reference)
       11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for exception handling.
Syntax
   void __stdcall ProcessUnhandledException(
      __in_ecount(1) BSTR errorMsg
   )
Parameters
errorMsg
The error message.
Requirements
Platforms: See .NET Framework System Requirements.
DLL:
In the .NET Framework 3.0 and 3.5: PresentationHostDLL.dll
In the .NET Framework 4 and later: PresentationHost_v0400.dll
.NET Framework Version: Available since 3.0
See also
   WPF Unmanaged API Reference
       SaveToHistory Function (WPF Unmanaged API
       Reference)
       11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for windows management.
Syntax
   HRESULT SaveToHistory(
      __in_ecount(1) IStream* pHistoryStream
   )
Parameters
pHistoryStream
A pointer to the history stream.
Requirements
Platforms: See .NET Framework System Requirements.
DLL:
In the .NET Framework 3.0 and 3.5: PresentationHostDLL.dll
In the .NET Framework 4 and later: PresentationHost_v0400.dll
.NET Framework Version: Available since 3.0
See also
   WPF Unmanaged API Reference
      SetFakeActiveWindow Function (WPF Unmanaged
      API Reference)
      11/21/2022 • 2 minutes to read • Edit Online
This API supports the Windows Presentation Foundation (WPF) infrastructure and is not intended to be used
directly from your code.
Used by the Windows Presentation Foundation (WPF) infrastructure for windows management.
Syntax
   void __stdcall SetFakeActiveWindow(
      HWND hwnd
   )
Parameters
hwnd
A window handle.
Requirements
Platforms: See .NET Framework System Requirements.
DLL: PresentationHost_v0400.dll
.NET Framework Version: Available since 4
See also
   WPF Unmanaged API Reference