Condividi tramite


XAML Syntax Terminology

This topic defines the terms that are used to describe the elements of Extensible Application Markup Language (XAML) syntax. These terms are used frequently throughout the remainder of this software development kit (SDK). This topic expands on the basic terminology introduced in the XAML Overview.

This topic contains the following sections. Origin of XAML Syntax TerminologyObject Element SyntaxAttribute SyntaxProperty Element SyntaxXAML Content SyntaxAttached PropertiesAttached EventsXml NamespacesMarkup ExtensionsOptional and Nonrecommended XAML UsagesRelated Topics

Origin of XAML Syntax Terminology

The XAML syntax terminology defined here is also defined or referenced within the XAML language specification. XAML is a language based on XML and follows XML structural rules. Some of the terminology is shared from or is based on the terminology commonly used when describing the XML language or the XML Document Object Model (DOM).

Object Element Syntax

Object element syntax is the XAML markup syntax that instantiates a common language runtime (CLR) class or struct by declaring an XML element. This syntax resembles the element syntax of other markup languages such as HTML. Object element syntax begins with a left angle bracket (<), followed immediately by the type name of the class or struct being instantiated. Zero or more spaces can follow the type name, and zero or more attributes may also be declared on the object element, with one or more spaces separating each attribute name="value" pair. Finally, one of the following must be true:

  • The element and tag must be closed by a forward slash (/) followed immediately by a right angle bracket (>).

  • The opening tag must be completed by a right angle bracket (>). Other object elements, property elements, or inner text, can follow the opening tag. Exactly what content may be contained here is typically constrained by the object model of the element; see Content Syntax section in this topic. The equivalent closing tag for the object element must also exist, in proper nesting and balance with other opening and closing tag pairs.

For example, the following example is object element syntax that instantiates a new instance of the Button class, and also specifies a Name attribute and a value for that attribute:

<Button Name="CheckoutButton"/>

The following example is object element syntax that also includes Extensible Application Markup Language (XAML) content property syntax. The inner text contained within will be used to set the TextBox Extensible Application Markup Language (XAML) content property, Text.

<TextBox>This is a Text Box</TextBox>

Attribute Syntax

Attribute syntax is the XAML markup syntax that sets a value for a property, or names an event handlers for an event, by declaring an attribute on an element. The element is always declared through object element syntax. The attribute name must match the CLR member name of either a property or an event. The attribute name is followed by an assignment operator (=). The attribute value must be a string enclosed within two quotation marks (").

In order to be set through attribute syntax, a property must be public, must be read-write, and must have a property value type that can be instantiated or referenced by a XAML loader. For events, the event must be public and have a public delegate. The property or event must be a member of the class or struct that is instantiated by the containing object element.

The attribute value is filled by one of the following, using this processing order:

  1. If the XAML loader encounters a curly brace, or an object element that derives from MarkupExtension, then the referenced markup extension is evaluated first rather than processing as a string, and the object returned by the markup extension is used. 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 runtime, and is not a new object.

  2. If the property is declared with a designated 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 between primitive types, or a check for names in an enumeration (which return the matching values).

For example, using the same markup as previously shown, the following example is the attribute syntax used to assign a string value for the Name property:

<Button Name="CheckoutButton"/>

The Name property is a member of the members table for the Button class. Button is a derived class of FrameworkElement class that defines Name.

Processing of Attribute Values

The string value contained within the opening and closing quotation marks is processed by a XAML loader. For properties, the default processing behavior is determined by the type of the underlying CLR property. If the property is a primitive type, then the attribute value is assigned based on implicit conversion of the string to the relevant primitive type. If the property is an enum, then the string is treated as a name defined by that enum and the matching value from the enum is returned. If the property is not a primitive type or enum, then the attribute value must be handled by a type converter that is declared on either the property itself or the destination type. The type converter must provide a conversion that accepts a string and must result in an instance of the type of the underlying CLR property. The conversion step might also be deferred through a markup extension .

Property and Event Member Name References

When specifying an attribute, you can reference any property or event that exists within the members table 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.

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.

Property names are sometimes provided as the value of an attribute, rather than the attribute name, and 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, and by some context factors such as whether a style or template has a target type. 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 typeconverter. For a more complete description of the lookup semantics, see PropertyPath XAML Syntax.

Property Element Syntax

Property element syntax is a syntax that diverges somewhat from the basic XML syntax. In XML, the value of an attribute is a de facto string, with the only possible variation being which string encoding format is being used other than UTF-8. In XAML, you can assign other object elements to be the value of a property. This capability is enabled by the property element syntax. Instead of the property being specified as an attribute within the element tag, the property is specified using an opening element tag in elementTypeName.propertyName form, the value of the property is specified, then the property element is closed.

Specifically, the syntax begins with a left angle bracket (<), followed immediately by the type name of the class or structure that the property element syntax is contained within. This is followed immediately by a single dot (.), then by the name of a property that must exist within the members table of the specified type, then by a right angle bracket (>). The value to be assigned to the property is contained within the property element. Typically, the value is given as one or more object elements, because specifying objects as values is the scenario that property element syntax is intended to address. Finally, an equivalent closing tag specifying the same elementTypeName.propertyName combination must be provided, in proper nesting and balance with other element tags. For example, the following is property element syntax for the ContextMenu property of a Button.

<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 can also be given as inner text, but only if the property type being specified is a primitive value type, such as String, or enum where a name is specified. These two usages are uncommon, because each of these cases also supports 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 whitespace 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 whitespace preservation is active (for details, see Whitespace Processing in XAML).

A property element is not part of the logical tree. It is just a particular syntax for setting a property, and is not an element that has an instance backing it.

Property Element Syntax for Collection Types

The XAML specification requires XAML loader implementations to be able to identify properties where the value type is a collection. The WPF implementation is based on managed code, and its XAML loader identifies collection types through one of the following:

If the type of a property is a collection, then the inferred collection type does not need to be specified in the markup. Instead, the elements that are intended to become the items in the collection are specified as one or more child elements of the collection type property element. Each such item is evaluated to an object during loading and added to the collection by calling the Add method of the implicit collection. For example, the Triggers property of Style takes the specialized collection type TriggerCollection. But it is not necessary to instantiate a TriggerCollection 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.

An implicit collection element creates a member in the logical tree, even though it does not appear in the markup as an element. Usually the constructor of the owning type performs the instantiation for the collection that is one of its properties, which adds the collection to the tree.

XAML Content Syntax

XAML content syntax is a syntax that is only enabled on classes that specify the ContentPropertyAttribute as part of their class declaration. The ContentPropertyAttribute requires a parameter that specifies the property by name that is defined to be the content property for that type of element (including derived classes). The property thus designated is the XAML content property of an element. When processed by a XAML loader, any child elements or inner text that are found between the opening and closing tags of the element will be assigned to be the value of that XAML content property. Property element tags on an element are not assigned this way; they are processed first and are not considered to be "content".

As with any other property, the XAML content property of an object will be of a specific type. That type can be the Object type. The type of that content property helps define the content model of an object. For instance, a type of Object is loose in the sense that any object may become the content, but even this loose typing entails that the content must be a single object. The single object might be a collection object, but even so there can be only one such collection object assigned to be the content.

Content models for particular types are described on the class pages for that type, or are written as separate conceptual topics for families of types and are linked to from each relevant type reference.

Content Syntax for Collection Types

In order to accept more than a single object element (or inner text) as content, the type of the content property must specifically be a collection type. Similar to property element syntax for collection types, a XAML loader must identify types that are collection types. If an element has a XAML content property, and the type of the XAML content property is a collection. The implied collection type does not need to be specified in the markup as an object element, and the XAML content property does not need to be specified as a property element. Therefore the apparent content model in the markup can now have more than one child element assigned as the content. The following is content syntax for a Panel subclass. All Panel derived classes establish the XAML content property to be Children, which requires a value of type UIElementCollection.

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>

Note that neither the property element for Children nor the element for the UIElementCollection are 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 extraneous intervening property element tags or collection objects. In fact, UIElementCollection cannot be specified in markup as an object element, by design. Because its only intended use is as an implicit collection, UIElementCollection does not expose a public default 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 loader 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 loader.

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, only additional 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 whitespace will be difficult to detect visually in the markup if property elements are interspersed with inner text.

Attached Properties

Attached properties are a programming concept introduced in XAML whereby properties can be owned and defined by a type, but set on any element. The primary scenario that attached properties are intended for is to enable child elements in an element tree 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 type, but handlers may be attached on any object. 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 an 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.

Xml Namespaces

None of the preceding syntax examples specified a namespace other than the default namespace. In typical WPF applications the default namespace is specified to be the WPF namespace. You can specify namespaces other than the default namespace and still use essentially the same kinds of syntax, but anywhere where a class is named that is not accessible within the default namespace, that class name must be preceded with the prefix of the XML namespace that was used to map the corresponding CLR namespace. For instance, <custom:MyElement/> is object element syntax to instantiate an instance of the MyElement class, where the CLR namespace containing that class (and possibly the external assembly that contains that namespace) was previously mapped to the custom prefix.

For more information about XML namespaces and XAML, see XAML Namespaces and Namespace Mapping.

Markup Extensions

XAML defines a markup extension programming entity that enables an escape from the normal XAML loader processing of attributes or object elements, and defers the processing to a backing class. The WPF implementation of a XAML loader uses the MarkupExtension abstract class as the basis for all of the markup extensions supported by WPF. The character that identifies a markup extension to a XAML loader 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 markup extensions in WPF are intended primarily to provide a means to reference other already-existing objects, or deferred references to objects that will be evaluated at runtime, while using attribute syntax. For instance, a simple data binding is accomplished by specifying the {Binding} markup extension in place of the value type that a given property would ordinarily take. Many of the markup extensions enable an attribute syntax for properties where an attribute syntax would not otherwise be possible. For instance, a Style object is a relatively complex reference type that contains several other properties, each of which also take byref objects and not primitives. But styles are typically created as a resource, and then referenced through one of the two markup extensions that request a resource. The 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 follows:

<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 nondefault StaticResourceExtension constructor, where the parameter as taken from the extension string declares the requested ResourceKey. MyStyle is expected to be the x:Key Attribute 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 XAML. For a reference of markup extensions and other XAML programming features, see XAML Namespace (x:) Language Features and WPF Namespace XAML Extensions.

Optional and Nonrecommended XAML Usages

Optional Property Element Usages

Optional property element usages include being specific about "spelling out" element content properties that the XAML loader considers implicit. For example, when you declare the contents of a Menu, you could choose to explicitly declare the Items collection of the Menu as a <Menu.Items> property element tag, and place each MenuItem within <Menu.Items>, rather than using the implicit XAML loader behavior that all child elements of a Menu must be a MenuItem and are placed in the Items collection. Sometimes the optional usages can help to visually clarify the object structure as represented in the markup. Or sometimes an explicit property element usage can avoid markup that is technically functional but visually confusing, such as nested markup extensions within an attribute value.

Full typeName.memberName Qualified Attributes

typeName .memberName form for an attribute actually works more universally than just the routed event case, but in other applications that form is superfluous and you should avoid it, if only for reasons of markup style and readability. In the following example, each of the three references to the Background attribute are completely equivalent:

<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:

<!--<Button Label.Background="Blue">Does not work</Button> -->

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 loader behavior is to then process Label.Background as an attached property. Label.Background is not an attached property, and this usage fails.

baseTypeName.memberName Property Elements

In an analogous way to how typename.membername form works for attribute syntax, a basetypename.membername syntax works for property element syntax. For instance, the following syntax works:

<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 for style reasons.

See Also

Concepts

XAML Overview
Dependency Properties Overview
TypeConverters and XAML
XAML and Custom Classes

Other Resources

XAML Namespace (x:) Language Features
WPF Namespace XAML Extensions