本文主要介绍XAML语言的功能,并演示如何使用XAML编写WPF应用。本文专门介绍WPF实现的XAML,要知道,XAML本身是比WPF更大的语言概念。、

一、什么是XAML

  XAML是一种声明性标记语言。应用于.NET Core编程模型时,XAML简化了为.NET Core应用创建UI的过程。你可以在声明XAML标记中创建可见的UI元素,然后使用代码隐藏文件(这些文件通过分部类<partial class>定义和标记相连接)将UI定义和运行时逻辑相分离。XAML直接以程序集中定义的一组特定后备类型标识对象的实例化。

  这与其他大多数标记语言不用,后者通常是与后备类型系统没有如此直接关系的解释语言。XAML实现了一个工作流。通过这个工作流,各方可以采用不同的工具来处理应用的UI和逻辑。

  以文本表示时,XAML文件通常具有.xaml扩展名的XML文件。通常以UTF-8编码对文件进行编码。

  下面的示例演示如何创建UI中的按钮:

<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>

二、XAML语法概述

  这些章节并不提供每个语法形式的完整信息,例如这些语法形式如何在后备类型系统中表示。

  1、XAML对象元素

  对象元素通常声明类型的实例。该类型是在将XAML用作语言的技术所引用的程序集中定义

例如,请再次查看之前演示的标记片段:

<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>

  每个实例都是在分析和加载 XAML 时通过调用基础类型的无参数构造函数来创建。

  2、特性语法(属性)

特性的值始终指定为包含在引号中的字符串。

例如,以下标记将创建一个具有红色文本和蓝色背景的按钮,还将创建指定为 Content 的显示文本:

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

  3、属性元素语法

对于这些情况,可以使用另一个语法,即属性元素语法。

结束标记的语法为 </TypeName.PropertyName>

以下示例演示在前面的特性语法示例中设置的相同属性,但这次对 Button 的所有属性使用属性元素语法:

<Button>
  <Button.Background>
    <SolidColorBrush Color="Blue"/>
  </Button.Background>
  <Button.Foreground>
    <SolidColorBrush Color="Red"/>
  </Button.Foreground>
  <Button.Content>
    This is a button
  </Button.Content>
</Button>

  4、集合语法

在这种情况下,子对象元素的集合是设置为集合属性的值。

  下面的示例演示用于设置 GradientStops(画笔的渐变停止点) 属性的值的集合语法:

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

  5、XAML内容属性

换言之,仅对内容属性而言,可以在 XAML 标记中设置该属性时省略属性元素,并在标记中生成更直观的父级/子级形式。

第二个元素显式显示 Border.Child:

<Border>
  <TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
  <Border.Child>
    <TextBox Width="300"/>
  </Border.Child>
</Border>

  例如,以下标记不会进行编译:

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

  6、文本内容

若要实现此功能,必须满足以下条件之一:

  • 例如,任何 ContentControl 都使用 Content 作为其内容属性,并且它属于类型 Object,这对于 ContentControl(如 Button)支持以下用法:<Button>Hello</Button>

  • 这种情况实际上并不常见。

  • 类型必须为已知的 XAML 语言基元。

  7、内容属性和集合语法结合

  考虑以下示例:

<StackPanel>
  <Button>First Button</Button>
  <Button>Second Button</Button>
</StackPanel>

  这是一个简单直观的标记,此标记由于两个不同的原因省略了两个标记。

  • Panel 将 Panel.Children 定义为其 XAML 内容属性。

  • (在本例中,UIElementCollection 实际上无法实例化,因为它不公开无参数构造函数,这便是 UIElementCollection 对象元素显示为注释掉的原因)。

    <StackPanel>
      <StackPanel.Children>
        <!--<UIElementCollection>-->
        <Button>First Button</Button>
        <Button>Second Button</Button>
        <!--</UIElementCollection>-->
      </StackPanel.Children>
    </StackPanel>

  8、特性语法(事件)

Button:

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

三、XAML中的大小写和空白

  Boolean 的本机 WPF XAML 分析程序类型转换已经允许将这些值作为等效值。

本文不包含有关 XAML 空白处理的完整说明。

四、标记扩展

  此用法指示 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>

标记扩展和 WPF XAML。

五、类型转换器

  但是很多 WPF 类型或这些类型的成员扩展了基本字符串特性处理行为,因此可以将更复杂的对象类型的实例指定为字符串和特性。

以下示例使用类型转换和特性语法来为 Margin 提供值:

<Button Margin="10,20,10,30" Content="Click me"/>

Thickness 的四个关键属性设置为新实例的特性:

<Button Content="Click me">
  <Button.Margin>
    <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
  </Button.Margin>
</Button>

例如 Cursor(用于鼠标指针的图像)。

六、XAML根元素和XAML命名空间

  以下示例演示 WPF 页的典型 XAML 文件的根元素,此根元素为 Page:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Page>

   xmlns:x 特性指示另一个 XAML 命名空间,该命名空间映射 XAML 语言命名空间http://schemas.microsoft.com/winfx/2006/xaml

XAML 名称范围与 XML 名称范围的不同仅在于:XAML 名称范围还包含有关进行类型解析和分析 XAML 时名称范围的元素如何受类型支持的信息。

但是,频繁定义或重新定义 XAML 命名空间会导致难以阅读 XAML 标记样式。

因此,为了引用来自 WPF 程序集的 XAML 元素,只需将默认 XAML 命名空间声明为默认 xmlns

   x:前缀

下面列出了最常用的 x: 前缀编程构造:

  • 在典型的 WPF 应用标记中的所有 x: 用法中,x:Key 可能占到 90%。

  • 必须具有这样一个类才能支持每个 WPF 编程模型的代码隐藏,因此即使没有资源,也几乎总是能看到映射的 x:

  • 某些动画方案中会发生这种情况。

  • x:Static:启用一个返回静态值的引用,该静态值不是与 XAML 兼容的属性。

  • x:Type 标记扩展用法是可选的。

七、XAML中的自定义前缀和自定义类型

  只要该类型能够正确地实现以支持正在尝试的 XAML 用法,就可以在 XAML 中引用该程序集中的类型。

通过使用该前缀,此 NumericUpDown 控件的一个实例声明为对象元素,以便 XAML 分析程序可找到包含该类型的 XAML 命名空间,从而找到包含该类型定义的后备程序集的位置

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

八、事件和XAML代码隐藏

  在 WPF 编程和应用程序模型中对 XAML 文件进行标记编译时,XAML 文件的 XAML 代码隐藏文件的位置是通过如下方式来标识的:以 XAML 根元素的 x:Class 特性形式指定一个命名空间和类。

在标记中指定事件名称以及要使用的处理程序的名称,而在代码隐藏中定义实现处理程序的代码。

<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;
    }
  }
}

  在提供定义同一分部类的代码隐藏时,将在与编译的应用相同的命名空间和类中合并生成的代码。

WPF 中的代码隐藏、事件处理程序和分部类要求。

但是,内联代码是一种通用性较低的方法,具有很多的限制。

  路由事件

Click 事件注册一个处理程序。

九、XAML命名元素

  默认情况下,通过处理XAML对象元素的对象图中创建的对象实例不具有唯一标识符或对象引用。相反,如果在代码中调用构造函数,则几乎总是使用构造函数结果作为构造的实例设置变量,以便以后在代码中使用该实例。为了对通过标记定义创建的对象提供标准化访问,XAML定义了x:Name特性。InitializeComponent。

  FindName 等实用工具方法,为可在运行时使用的 XAML 元素提供标识符。

  StackPanel:

<StackPanel Name="buttonContainer">
    <Button Click="RemoveThis">Click to remove this button</Button>
</StackPanel>

void RemoveThis(object sender, RoutedEventArgs e)
{
    FrameworkElement fe = e.Source as FrameworkElement;
    if (buttonContainer.Children.Contains(fe))
    {
        buttonContainer.Children.Remove(fe);
    }
}

WPF XAML 名称范围。

十、附加属性和附加事件

  但是,元素/类或更大的基础结构必须支持附加值的后备属性存储。

在特性语法中,可以采用 ownerType.propertyName 的形式指定附加属性。

ownerType 这种类型提供 XAML 处理器为获取或设置附加属性值所需要的访问器方法。

  附加属性的最常见方案是使子元素向其父元素报告属性值。

DockPanel 类激动人心的一面。

<DockPanel>
  <Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
  <Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>

附加属性概述。

附加事件概述。

十一、基类型和XAML

  元素级的特性和 CLR 对象模型的组合提供一组通用的属性,这些属性可以在大多数具体的 XAML 元素上设置,而不管具体的 XAML 元素及其基础类型。

十二、XAML安全性

  加载到完全受信任的应用中的 XAML 与承载应用具有相同的系统资源访问权限。

代码访问安全性差异。

十三、从代码中加载XAML

只要该属性在内容模型中是一个合适的属性,而该内容模型具有最终显示功能并且将通知执行引擎已向应用添加新内容,就可以通过在 XAML 中进行加载轻松地修改正在运行的应用的内容。

相关文章: