4. XAML 的命名空间和命名空间映射

WPF学习目录

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

1. XAML命名空间

举例:

WPF内置控件有一个Button类,当我们引用了某个三方组件中,也有一个Button类,那这个时候,XAML是如何区分的呢?

我们可以看到Windows元素中有这样一段代码,这里其实就是对XAML命名空间进行声明。

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp2"
使用特性声明XML名称空间。这些特性能被放入任何元素的开始标签中。
但约定要求, 在文档中需要使用的所有名称空间应在第一个标签中声明,正如在这个示例中所做的那样。
一旦声明一个名称空间,在文档中的任何地方都可以使用该名称空间。

1.1 相关解释

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

上面这一行是WPF核心命名空间,它包含了WPF的类,包括用来构建用户界面的控件。

在该例中,该名称空间的声明没有使用名称空间前缀,所以它成为整个文档的默认名称空间。

换句话说,除非另行指明, 每个元素自动位于这个名称空间。

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

上面这是XAML名称空间。它包含各种XAML 实用特性,这些特性可影响文档的解释方式。该名称空间被映射为前缀x。这意味着可 通过在元素名称之前放置名称空间前缀x来使用该名称空间(例如<x:ElementName>)。

1.2 为什么使用名称空间

XML名称空间的名称和任何特定的NET名称空间都不匹配。

XAML的创建者选择这种设计的原因有两个:

  • 按照约定,XML名称空间通常是URI(如上面所示)。
    • 这些URI看起来像是在指明Web上的位置, 但实际上不是。
    • 通过使用URI格式的名称空间不同组织就基本不会无意中使用相同的名称空间创建不同的基于XML的语言。因为 schemas.com 域归Microsoft所有,只有Microsoft会在XML名称空间的名称中使用它。
  • XAML 中使用的 XML 名称空间和 .NET 名称空间不是一一对应的, 如果一一对应的话,会显著增加 XAML 文档的复杂程度。
    • WPF包含了十几种名称空间(所有这些名称空间都以 System. Windows 开头)。 如果每个.NET 名称空间都有不同的 XML 名称空间,那就需要为使用的每个控件指定确切的 XML 名称空间, 这很快就会使 XAML 文档变得混乱不堪。 所以, WPF创建人员选择了这种方法, 将所有这些.NET名称空间组合到单个XML名称空间中。因为在不同的.NET名称空间中都有一部分WPF类,并且所有这些类的名称都不相同, 所以这种设计是可行的。

名称空间信息使得 XAML 解析器可找到正确的类。 例如, 当查找 Window 和 Grid 元素时,首先会查找默认情况下它们所在的WPF名称空间, 然后查找相应的.NET名称空间, 直至找到 System.Windows.Window 类System.Windows.Controls.Grid类

1.3 实际代码

xmlns特性是XML中的一个特性,用来声明命名空间。在WPF中,是依靠System.Windows.Markup.XmlnsDefinitionAttribute特性来实现这个功能。

它的实际代码:

System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Controls");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Documents");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shapes");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shell");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Navigation");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Data");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Controls.Primitives");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Media.Animation");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Input");
System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Media");

如:

<x:MyElementName></x:MyElementName>

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"实际上对应的代码是:

System.Windows.Markup.XmlnsDefinitionAttribute("http://schemas.microsoft.com/winfx/2006/xaml", "System.Windows.Markup");

2. 如何通过XAML命名空间引用三方组件或系统组件?

引用三方或系统组件的过程是先引入命名空间前缀,再通过命名空间前缀使用该命名空间下的相应类。

这里以Nuget 包 BlurWindow 为例,这个包里有一个窗体透明的BlurWindows类。

1、安装nuget包

image

2、引入命名空间前缀

xmlns:blur="clr-namespace:TianXiaTech;assembly=BlurWindow"

3、使用外部组件

<blur:BlurWindow x:Class="ImportXmlns.MainWindow">
      ......
</blur:BlurWindow>

3.映射到自定义类和程序集

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

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

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

  • clr-namespace: 在程序集中声明的 CLR 命名空间,此程序集包含要作为元素公开的公共类型。
  • assembly= 包含部分或全部引用的 CLR 命名空间的程序集。
    • 此值通常为程序集的名称而不是路径,且不包含扩展名(例如 .dll 或 .exe)。
    • 程序集路径必须创建为包含要映射的 XAML 的项目文件中的项目引用。
    • 为了并入版本控制和强名称签名, assembly 该值可以是由定义的字符串 AssemblyName ,而不是简单的字符串名称。

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

3.1 映射到当前程序集

如果要在与引用自定义类的应用程序代码相同的程序集内定义引用的 clr-namespace,则可省略 assembly。 或者,这种情况的等效语法是指定 assembly= 且等号后不含任何字符串标记。

如果在同一程序集中定义,则自定义类无法用作页面的根元素。 分部类无需映射;仅需映射应用程序中不是页面分部类的类(若要将其引用为 XAML 中的元素)。

4. 设计器命名空间和 XAML 模板中的其他前缀

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

适用于 Visual Studio 的 WPF 设计器使用通常映射到前缀的设计器命名空间 d: 。

适用于 WPF 的更高的项目模板可以预映射此 XAML 命名空间,以支持 WPF 设计器与 Visual Studio 和其他设计环境之间的 XAML 交换。

此设计 XAML 命名空间用于在设计器中往返基于 XAML 的 UI 时保持设计状态。

它也用于 d:IsDataSource(在设计器中启用运行时数据源)等功能。

可能看到的另一个映射前缀是 mc:

mc: 用于标记兼容,使用一种并不一定特定于 XAML 的标记兼容模式 。

某种程度上,标记兼容功能可用于在框架之间或跨后备实现的其他边界交换 XAML、在 XAML 架构上下文之间运行、为设计器中限制模式提供兼容性等。

5. WPF 和程序集加载

WPF 的 XAML 架构上下文与 WPF 应用程序模型集成,后者又使用的 CLR 定义的概念 AppDomain。
下面的序列说明 XAML 架构上下文如何解释如何在运行时或设计时加载程序集或查找类型,具体取决于 WPF 使用 AppDomain 和其他因素。

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

如果名称是限定的,则对 Assembly.Load(String) 限定名称调用。
如果限定名称的短名称和公钥标记匹配从中加载标记的程序集,则返回此程序集。
使用短名称 + 公钥标记调用 Assembly.Load(String) 。
如果名称不合格,请调用 Assembly.LoadWithPartialName 。

WPF学习目录

posted @ 2021-07-04 21:34  x_amos  阅读(713)  评论(0编辑  收藏  举报