XAML and WPF

来源:互联网 发布:php邀请码演示代码 编辑:程序博客网 时间:2024/05/22 03:04
XAML and WPF
XAML-Extensible Application Markup Language
WPF-Windows Presentation Foundation
Extensible Application Markup Language (XAML) is a markup language for declarative application programming. Windows Presentation Foundation (WPF) implements a Extensible Application Markup Language (XAML) loader and provides Extensible Application Markup Language (XAML) language support for Windows Presentation Foundation (WPF) types such that you can create the majority of your application UI in Extensible Application Markup Language (XAML) markup.
In This Section
XAML Overview

XAML Syntax Terminology

Code-Behind and XAML

XAML and Custom Classes

Markup Extensions and XAML

XAML Namespaces and Namespace Mapping

WPF Namescopes

Inline Styles and Templates

Whitespace Processing in XAML

TypeConverters and XAML

XAML Namespace (x:) Language Features

WPF Namespace XAML Extensions

Markup Compatibility (mc:) Language Features

Related Sections
WPF Architecture

Base Elements

Element Tree and Serialization

Properties

Events

Input and Commands

Resources

Styling and Templating

WPF Fundamentals: Content Models

Threading Model

XAML Overview
This topic describes the features of the Extensible Application Markup Language (XAML) language and demonstrates how you can use XAML to write Windows Presentation Foundation (WPF) applications. This topic specifically describes XAML as implemented by Windows Presentation Foundation (WPF). XAML itself is a larger language concept than Windows Presentation Foundation (WPF).
This topic contains the following sections.
XAML is a Declarative Language With Flow Control Support

XAML Object Elements

Setting Properties

Markup Extensions

Typeconverter-Enabled Attribute Values

Collection Types and XAML Collection Properties

XAML Content Properties

Case and Whitespace in XAML

More about XAML Syntax

XAML Root Elements and xmlns

Events and XAML Code-Behind

x:Name

Attached Properties and Attached Events

Base Classes and XAML

XAML Security

What's Next

Related Topics
XAML is a Declarative Language With Flow Control Support
XAML simplifies creating a UI for the .NET Framework 3.0 programming model. 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, joined to the markup through partial class definitions. The ability to mix code with markup in XAML is important because XML by itself is declarative, and does not really suggest a model for flow control. An XML based declarative language is very intuitive for creating interfaces ranging from prototype to production, especially for people with a background in web design and technologies. Unlike most other markup languages, XAML directly represents the instantiation of managed objects. This general design principle enables simplified code and debugging access for objects that are created in XAML.
XAML files are XML files that generally have the .xaml extension.
The following XAML example shows how little markup is necessary to create a button as part of a UI. The created button has default visual presentation through theme styles, and default behaviors through its class design.

XAML
程序代码 程序代码
<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>


XAML Object Elements
XAML has a set of rules that map object elements into classes or structures, attributes into properties or events, and XML namespaces to CLR namespaces. XAML elements map to Microsoft .NET types as defined in referenced assemblies, and the attributes map to members of those types.

The preceding example specified two object elements: <StackPanel> (with a closing tag), and <Button /> (which also had several attributes; attributes are discussed in an upcoming section). The strings 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 the XAML loader to create a new instance of the named class when your XAML page is either compiled or interpreted. Each instance is created by calling the default constructor of the underlying class or struct and storing the result. To be usable as an object element in XAML, the class must expose a public default (parameterless) constructor.

Setting Properties
Properties in XAML are set by setting properties on an object element, using a variety of possible syntaxes. Which syntaxes can be used for a given property will vary, based on the characteristics of the property that you are setting.

By setting values of properties, you add features or characteristics to object elements. The initial state of the underlying object instance for an object element is based on the default constructor behavior. Typically, you want something other than a completely default class instance.

Attribute Syntax
In XAML, properties can often be expressed as attributes. Attribute syntax is the most streamlined property setting syntax and will be the most intuitive syntax to use for developers that have used markup languages in the past. For example, the following markup creates a button that has red text and a blue background, as well as display text specified as Content.

XAML
程序代码 程序代码
<Button Background="Blue" Foreground="Red" Content="This is a button"/>


Property Element Syntax
For some properties of an object element, attribute syntax is not possible, because the object or information necessary to provide the property value cannot be adequately expressed as a simple string. For these cases, a different syntax known as property element syntax can be used. Property element syntax sets the referenced property of the containing element with a new instance of the type that the property takes as its value (with the value-setting instance typically specified as another object element). The syntax for a property element is <TypeName.Property>. For properties where both attribute and property element syntax are supported, the two syntaxes generally have the same result, although subleties such as whitespace handling can vary slightly between syntaxes. If an attribute syntax is possible, using the attribute syntax is typically more convenient and enables a more compact markup, but that is just a matter of style, not a technical limitation. The following example shows the same properties being set as in the previous attribute syntax example, but this time by using property element syntax for all properties of the Button.

XAML
程序代码 程序代码
<Button>
  <Button.Background>
    <SolidColorBrush Color="Blue"/>
  </Button.Background>
  <Button.Foreground>
    <SolidColorBrush Color="Red"/>
  </Button.Foreground>
  <Button.Content>
    This is a button
  </Button.Content>
</Button>


Properties and Class Inheritance
Properties as they appear as XAML attributes on a WPF element are often inherited from base classes. For example, in the previous example, the Background property is not an immediately declared property on the Button class if you were to look at the class definition. Instead, Background is inherited from the base Control class.

Markup Extensions
When properties take a reference type value, these properties will often require either property element syntax (which always creates a new instance), or an object reference through a markup extension. A markup extension usage can potentially return an existing instance, and thus can be more versatile or might incur less object overhead. Markup extensions are a XAML concept. In attribute syntax, curly braces ({ and }) indicate a markup extension usage. This usage directs the XAML loader to escape from the general treatment of attribute values as either a literal string or a directly string-convertible value. The attribute value should instead be provided by the logic within the backing class for the relevant markup extension. The most commonly used markup extensions for application programming are Binding Markup Extension, used for data binding e­xpressions, and the resource references StaticResource Markup Extension and DynamicResource Markup Extension. By using markup extensions, you can use attribute syntax to provide reference values for properties even if that property does not support an attribute syntax for direct object instantiation.

For instance, the following example sets the value of the Style property using attribute syntax. The Style property takes an instance of the Style class, a by-reference type that by default could not be specified within 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.

XAML
程序代码 程序代码
<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>


Resources are just one markup extension usage enabled by either WPF or XAML. For a reference listing of markup extensions, see WPF Namespace XAML Extensions or XAML Namespace (x:) Language Features. For more information about markup extensions, see Markup Extensions and XAML.

Typeconverter-Enabled Attribute Values
In the Attribute Syntax 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. But many WPF types or members of those types extend the basic string attribute processing behavior, such that instances of more complex object types can be specified as attribute values through a string. At the code level, this processing is accomplished by specifying a CLR type converter that processes the string attribute value. The Thickness structure type, commonly used to indicate measurements of a rectangular area such as a Margin, is an example of a type that has a special typeconverter-enabled attribute syntax exposed for all properties that take that type, to provide ease of use in XAML markup. The following example uses a typeconverter-enabled attribute syntax to provide a value for a Margin:

XAML
程序代码 程序代码
<Button Margin="10,20,10,30" Content="Click me"/>


The preceding 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, and four key properties of Thickness are set as attributes on the new instance:

XAML
程序代码 程序代码
<Button Content="Click me">
  <Button.Margin>
    <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
  </Button.Margin>
</Button>


Again, whether to use the typeconverter-enabled syntax or a more verbose equivalent syntax is a coding style choice, but the typeconverter-enabled syntax promotes more streamlined markup.

For more information on how typeconverter-enabled attribute syntax is supported, see TypeConverters and XAML.

Collection Types and XAML Collection Properties
XAML specifies a language feature whereby the object element that represents a collection type can be deliberately omitted from markup. When a XAML loader processes a property that takes a collection type, an instance of the appropriate collection type is created implicitly, even if the object element for that collection is not present in the markup. In the SDK 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.

Implicit collection syntax is available for types that implement IList or IDictionary, or for arrays.

You have already seen an example of an implicit collection syntax without it being called out, in the XAML resources example:

XAML
程序代码 程序代码
<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>


With the exception of the root element, every object element on a page 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, or one of the items within a collection. In the case of the resources example, the Resources property takes an object of type ResourceDictionary. The following example is equivalent syntax with the object element for the ResourceDictionary specified explicitly.

XAML
程序代码 程序代码
<Page.Resources>
    <ResourceDictionary>
        <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
        <Style TargetType="Border" x:Key="PageBackground">
          <Setter Property="Background" Value="Blue"/>
        </Style>

    ...

    </ResourceDictionary>
  </Page.Resources>
  <StackPanel>
    <Border Style="{StaticResource PageBackground}">

    ...

    </Border>
  </StackPanel>
</Page>


The Resources collection is an example of a collection property that is present on all WPF framework-level elements. Setting this property in XAML requires the property element syntax. Each enclosed object element within the property element becomes an item of the collection (an IDictionary implementation). Although the collection type itself typically does have a property or indexer that contains the items, that property cannot be specified in markup; it is entirely implied. For the ResourceDictionary, that property is the Item indexer.

For a more complete resource dictionary usage example, see How to: Define and Reference a Resource.

XAML Content Properties
XAML specifies a language feature whereby any class that can be used as a XAML object element can designate exactly one of its properties to be the XAML content property for instances of the class. When a XAML loader processes an object element that has a XAML content property, any XML child elements of that object element are processed as if they were contained within an implicit property element tag representing that content property. Within your markup, property element syntax for the XAML content property can be omitted. Any child elements you specify in markup will become the value of the XAML content property.

You have already seen an example of a XAML content property without it being called out: the very first example in this topic.

XAML
程序代码 程序代码
<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>


Here, 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 property element: StackPanel derives from Panel. Panel defines Panel.Children as its XAML content property. All derived classes of Panel thus have that XAML content property, and the property element for Panel.Children can be omitted.

Omitted UIElementCollection object element: The Panel.Children property takes the type UIElementCollection, which implements IList. Therefore the UIElementCollection object element tag can be omitted, based on the XAML defined rules for collections. In this case, UIElementCollection actually cannot be instantiated as an object element. You do not even have the option of declaring that collection object explicitly. This is because UIElementCollection does not expose a default constructor. Several other WPF collection types also do not expose constructors for object element usage, because the XAML collection syntax handling still allows them to work in XAML implicitly. That is why the UIElementCollection object element is shown commented in the example; if uncommented, the example would not compile.

XAML
程序代码 程序代码
<StackPanel>
  <StackPanel.Children>
    <!--<UIElementCollection>-->
    <Button>
      <Button.Content>
        Click Me
      </Button.Content>
    </Button>
    <!--</UIElementCollection>-->
  </StackPanel.Children>
</StackPanel>


Inner Text and XAML Content Properties
The StackPanel / Button example has still another variation.

XAML
程序代码 程序代码
<StackPanel>
  <Button>Click Me</Button>
</StackPanel>


Notice the change in how the display text for the Button is specified. The Content property was specified in attribute syntax before; this time the display string is the inner text within a Button object element. This syntax works because Content is the XAML content property of the Button base class ContentControl. The string within the element is evaluated based on the property type of the Content property, which is Object. Object does not attempt any string type conversion, therefore the value of the Content property becomes the literal string value. Alternatively, the content within the Button could have been any single Object. Controls such as Button generally define the XAML content property for the class such that the XAML content property can be used for UI and display text, for control compositing, or both.

The ability to place strings within the element as content to produce markup that resembles other common markup languages is particularly important for the flow document model (for details, see Documents in Windows Presentation Foundation) and for localization (see Globalization for the Windows Presentation Foundation).

XAML Content Property Values Must Be Contiguous
The value of a XAML content property must be given either entirely before or entirely after any other property elements on that object element. This is true whether the value of a XAML content property is specified as a string, or as one or more objects. For instance, the following markup does not compile:

程序代码 程序代码

<Button>I am a
  <Button.Background>Blue</Button.Background>
blue button</Button>

This is illegal essentially because if this syntax were 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>

Content Models
A class might support a usage as a XAML 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. For some controls that have more complex content models, the content model is documented as a separate conceptual topic. See Content Models.

Case and Whitespace in XAML
XAML is case sensitive. Object elements, property elements, and attribute names must all be specified by using the proper casing when compared by name to the underlying type in the assembly, or to a member of a type. The values for attributes are not always case sensitive. Case sensitivity for values will depend on the type converter behavior associated with the property that takes the value, or the property value type. For instance, properties that take the Boolean type can take either true or True as equivalent values, but only because the default string type conversion for Boolean already permits these as equivalents.

XAML loaders and serializers will ignore or drop all nonsignificant whitespace, and will normalize any significant whitespace. This behavior is generally only of consequence when you specify strings within XAML content properties. In simplest terms, XAML converts space, linefeed and tab characters into spaces, and then preserves one space if found at either end of a contiguous string. The full explanation of XAML whitespace handling is not covered in this topic. For details, see Whitespace Processing in XAML.

More about XAML Syntax
Implicit collection syntax and XAML content properties are both features of the XAML language that enable omission of certain inferred tags. The goal of these features is to make the parent-child relationships of elements on a page more apparent when authoring or examining the markup.

For more information about attribute syntax and property element syntax, as well as other terms that are used when describing XAML syntax throughout the SDK documentation, see XAML Syntax Terminology.

XAML Root Elements and xmlns
XAML files must have only one root element, in order to be a both well-formed XML file and a valid XAML file. Typically you should choose an element that is part of the application model (for example, Window or Page for a page, ResourceDictionary for an external dictionary, or Application for the application definition root). The following example shows the root element of a typical XAML file for a WPF page, with the root element Page.

XAML
程序代码 程序代码
<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 the XAML loader which namespaces contain the element definitions. The xmlns attribute specifically indicates the default xmlns namespace. Within the default xmlns namespace, object elements in the markup can be specified without a prefix. For most WPF application scenarios, and for virtually all of the examples given in the WPF sections of the SDK, the default xmlns namespace is mapped to the WPF namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation. The xmlns:x attribute indicates an additional xmlns namespace, which maps the XAML language namespace http://schemas.microsoft.com/winfx/2006/xaml. Required language components defined by the XAML specification are prefixed by x: when referenced in the markup of a file with this mapping. This usage of xmlns to define a scope for usage and mapping is consistent with the XML 1.0 specification. Note that the xmlns attributes are only strictly necessary on the root element of the page or application. xmlns definitions will apply to all child elements of the root (this behavior is again consistent with the XML 1.0 specification for xmlns.) xmlns attributes are also permitted on other elements beneath the root, and would apply to any child elements of the defining element. However, this usage is not typical, because frequent definition or redefinition of xmlns namespaces can result in a markup style that is difficult to read.

The WPF assemblies are known to contain the WPF namespaces because of configuration that is part of your project build file. Assemblies are also mapped in the targets files. Therefore, mapping the xmlns is all that is necessary in order to reference XAML elements that come from WPF assemblies. For your own custom assemblies, or for assemblies outside of WPF, you can specify the assembly as part of the xmlns mapping. For more information about how xmlns namespaces and the namespaces of the backing code in assemblies are related, see XAML Namespaces and Namespace Mapping.

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. This x: prefix will be used to map the XAML namespace in the templates for projects, in examples, and in documentation throughout this SDK. The x: prefix/XAML namespace contain several programming constructs that you will use quite frequently in your XAML. The following is a listing of the most common x: prefix/XAML namespace programming constructs you will use:

x:Type: Constructs a Type reference based on a type name. This is used to specify attributes that take Type, such as System.Windows.Style.TargetType.

x:Key: Sets a unique key for resources in a ResourceDictionary.

x:Class: Specifies the CLR namespace and class name for the class that provides code-behind for a XAML page.

x:Static: Enables a value reference to a static value that is not otherwise a XAML settable property.

There are also more programming constructs in the x: prefix/XAML namespace, which are not as common. For details, see XAML Namespace (x:) Language Features.

Events and XAML Code-Behind
Most WPF applications consist of both markup and code-behind. Within a project, the XAML is written as a .xaml file. and a CLR language such as Microsoft Visual Basic .NET or C# is used to write a code-behind file. When a XAML file is compiled, the location of the XAML code-behind file for each XAML page is identified by specifying a namespace and class as the x:Class attribute of the root element of the XAML page.

In the examples so far, you have seen several buttons, but none of these buttons had any logical behavior associated with them yet. The primary application-level mechanism for adding a behavior for an object element is to use an existing event of the element class, and to write a specific handler for that event that is invoked when that event is raised at runtime. The event name and the name of the handler to use are specified in the markup, whereas the code that implements your handler is defined in the code-behind.
 
 
原创粉丝点击