WPF XAML 的 XAML 命名空间和命名空间映射

本主题进一步介绍了 WPF XAML 文件的根标记中经常发现的两个 XAML 命名空间映射的存在和用途。 它还介绍如何生成类似的映射,以应用在您自己的代码中定义的元素和/或在独立的程序集内定义的元素。

什么是 XAML 命名空间

XAML 命名空间实际上是 XML 命名空间概念的扩展。 指定 XAML 命名空间的方法依赖于 XML 命名空间语法、使用 URI 作为命名空间标识符的约定、使用前缀提供从同一标记源引用多个命名空间的方法等。 添加到 XML 命名空间的 XAML 定义的主要概念是,XAML 命名空间既意味着标记用法的唯一性范围,又影响标记实体可能由特定 CLR 命名空间和引用的程序集提供支持的方式。 后一个考虑因素也受 XAML 架构上下文的概念的影响。 出于考虑 WPF 如何处理 XAML 命名空间,一般来说,可以将 XAML 命名空间视为默认 XAML 命名空间、XAML 语言命名空间,以及通过 XAML 标记直接映射到特定 CLR 命名空间和引用的程序集的其他 XAML 命名空间。

WPF 和 XAML 命名空间声明

在许多 XAML 文件的根标记的命名空间声明中,你将看到通常有两个 XML 命名空间声明。 第一个声明将整个 WPF 客户端/框架 XAML 命名空间映射为默认值:

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

第二个声明将单独的 XAML 命名空间映射到 x: 前缀(通常)。

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

这些声明之间的关系是 x: 前缀映射支持作为 XAML 语言定义的一部分的内部函数,WPF 是一个实现,它使用 XAML 作为语言,并定义 XAML 对象的词汇。 由于 WPF 词汇的用法比 XAML 内部函数用法更为常见,因此 WPF 词汇映射为默认值。

用于映射 XAML 语言内置功能支持的前缀约定,在项目模板、示例代码以及此 SDK 中的语言功能文档中得到了遵循。 XAML 命名空间定义许多常用的功能,这些功能甚至对于基本 WPF 应用程序来说也是必要的。 例如,若要通过分部类将任何代码隐藏联接到 XAML 文件,必须将该类命名为 x:Class 相关 XAML 文件的根元素中的属性。 或者,您希望作为键控资源访问的 XAML 页面中定义的任何元素,都应在相关元素上设置 x:Key 属性。 有关 XAML 的这些方面和其他方面的详细信息,请参阅 WPF 中的 XAMLXAML 语法详细信息

映射到自定义类和程序集

可以使用前缀声明中的一系列标记 xmlns 将 XML 命名空间映射到程序集,这类似于将标准 WPF 和 XAML 内部函数 XAML 命名空间映射到前缀的方式。

语法采用以下可能的命名标记和以下值:

clr-namespace: 程序集中声明的 CLR 命名空间,其中包含要公开为元素的公共类型。

assembly= 包含部分或全部引用的 CLR 命名空间的程序集。 此值通常只是程序集的名称,而不是路径,并且不包括扩展(如 .dll 或 .exe)。 必须在包含要映射的 XAML 的项目文件中将该程序集的路径建立为项目引用。 为了结合版本控制和强名称签名,assembly 的值可以是由 AssemblyName 定义的字符串,而不是简单的字符串名称。

请注意,将 clr-namespace 标记与其值分隔的字符是冒号(:),而将标记与其值分隔 assembly 的字符是等号(=)。 这两个标记之间要使用的字符是分号。 此外,不要在声明中的任意位置包含任何空格。

基本自定义映射示例

以下代码定义了一个示例自定义类:

namespace SDKSample {
    public class ExampleClass : ContentControl {
        public ExampleClass() {
        ...
        }
    }
}
Namespace SDKSample
    Public Class ExampleClass
        Inherits ContentControl
         ...
        Public Sub New()
        End Sub
    End Class
End Namespace

然后,此自定义类编译为一个库,根据项目设置(未显示)命名 SDKSampleLibrary

若要引用此自定义类,还需要将其作为当前项目的引用,通常可在 Visual Studio 中使用解决方案资源管理器 UI。

现在,你已有一个包含类的库,并在项目设置中引用了该类,可以在 XAML 中将以下前缀映射添加为根元素的一部分:

xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary"

若要将其全部放在一起,以下是包含自定义映射的 XAML 以及根标记中典型的默认值和 x: 映射,然后使用前缀引用在该 UI 中实例化 ExampleClass

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

映射到当前程序集

assembly 如果 clr-namespace 引用的程序集与引用自定义类的应用程序代码在同一程序集中定义,则可以省略它。 或者,此案例的等效语法是指定 assembly=,没有后面的字符串标记。

如果在同一程序集中定义,则自定义类不能用作页面的根元素。 只有在 XAML 中引用为元素时,非应用程序页面分部类的类才需要映射;分部类本身不需要映射。

将 CLR 命名空间映射为程序集内的 XML 命名空间

WPF 定义 XAML 处理器使用的 CLR 属性,以便将多个 CLR 命名空间映射到单个 XAML 命名空间。 此属性XmlnsDefinitionAttribute被放置在生成该程序集的源代码中的程序集级别。 WPF 程序集源代码使用此属性将各种通用命名空间(例如 System.WindowsSystem.Windows.Controls)映射到 http://schemas.microsoft.com/winfx/2006/xaml/presentation 命名空间。

采用 XmlnsDefinitionAttribute 两个参数:XML/XAML 命名空间名称和 CLR 命名空间名称。 可以存在多个 XmlnsDefinitionAttribute CLR 命名空间,以便将多个 CLR 命名空间映射到同一个 XML 命名空间。 映射后,还可以通过在分部类代码隐藏页中提供适当的 using 语句来引用这些命名空间的成员,而无需完全限定。 如需了解详情,请访问 XmlnsDefinitionAttribute

来自 XAML 模板的设计器命名空间和其他前缀

如果使用的是 WPF XAML 的开发环境和/或设计工具,你可能会注意到 XAML 标记中还有其他定义的 XAML 命名空间/前缀。

Visual Studio 的 WPF 设计器使用通常映射到前缀 d:的设计器命名空间。 WPF 的最新项目模板可能会预先映射此 XAML 命名空间,以支持在 Visual Studio 的 WPF 设计器和其他设计环境之间交换 XAML。 此设计 XAML 命名空间用于在设计器中往返基于 XAML 的 UI 时延续设计状态。 它还用于在设计器中启用运行时数据源的功能 d:IsDataSource

你可能会看到映射的另一个前缀是 mc:mc: 用于标记兼容性,并利用不一定特定于 XAML 的标记兼容性模式。 在某种程度上,标记兼容性功能可用于在框架之间或跨支持实现的其他边界交换 XAML、在 XAML 架构上下文之间工作、为设计器中的有限模式提供兼容性等。 有关标记兼容性概念及其与 WPF 的关系的详细信息,请参阅 标记兼容性(mc:) 语言功能

WPF 和程序集加载

WPF 的 XAML 架构上下文与 WPF 应用程序模型集成,后者又使用 CLR 定义的概念 AppDomain。 以下序列描述 XAML 架构上下文如何根据 WPF 的使用 AppDomain 和其他因素解释如何在运行时或设计时加载程序集或查找类型。

  1. 从最近加载的程序集开始,循环访问 AppDomain该程序集,查找与名称的所有方面匹配的已加载程序集。

  2. 如果名称是限定的,则调用 Assembly.Load(String) 限定的名称。

  3. 如果限定名称的短名称 + 公钥标记与从中加载标记的程序集匹配,则返回该程序集。

  4. 使用短名称 + 公钥令牌调用 Assembly.Load(String)

  5. 如果名称不限定,则调用 Assembly.LoadWithPartialName

未编译的 XAML 不使用第 3 步;没有从程序集加载的文件。

已编译的 WPF XAML(通过 XamlBuildTask 生成)不使用已加载的程序集( AppDomain 步骤 1)。 此外,从 XamlBuildTask 输出中不应未限定名称,因此步骤 5 不适用。

编译的 BAML(通过 PresentationBuildTask 生成)使用所有步骤,尽管 BAML 也不应包含未限定的程序集名称。

另请参阅