让你编写的控件库在 XAML 中有一个统一的漂亮的命名空间(xmlns)和命名空间前缀

简介: 原文 让你编写的控件库在 XAML 中有一个统一的漂亮的命名空间(xmlns)和命名空间前缀 在 WPF XAML 中使用自己定义的控件时,想必大家都能在 XAML 中编写出这个控件的命名空间了。然而——我写不出来,除非借助 ReSharper。

原文 让你编写的控件库在 XAML 中有一个统一的漂亮的命名空间(xmlns)和命名空间前缀

在 WPF XAML 中使用自己定义的控件时,想必大家都能在 XAML 中编写出这个控件的命名空间了。然而——我写不出来,除非借助 ReSharper。

如果控件能够有一个漂亮的命名空间和命名空间前缀呢?——好吧,还是写不出来,不过,至少漂亮些。本文将指导你自定义在 XAML 中使用的命名空间。


达到什么样的效果?

<UserControl
    x:Class="HuyaHearhira.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:w="http://walterlv.github.io/demo" <Grid> <w:DemoPage /> </Grid> </UserControl> 

注意到 DemoPage 所在的命名空间了吗?是 http://walterlv.github.io/demo 哦。而且,命名空间前缀是 w。这是不是比下面这种看得清爽多了呢?

<UserControl
    x:Class="HuyaHearhira.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:newCsprojDemo="clr-namespace:Walterlv.NewCsprojDemo;assembly=Walterlv.NewCsprojDemo"> <Grid> <newCsprojDemo:DemoPage /> </Grid> </UserControl> 

当然,好处不止是更清爽,还有更多,总结起来是这三个:

  1. 利于 API 的升级
    例如你写了一个库提供了一些可以在 XAML 中使用的控件,但是后来随着功能的强大你把程序集拆分成了多个。这时,如果没有这样的命名空间定义,那就意味着使用你的库的大量开发者需要手工修改 XAML 中的命名空间前缀定义。而使用了这样的命名空间定义的方法后,开发者只需要重新编译一遍即可。
  2. 简化命名空间前缀
    如果你的库有多个命名空间下都提供控件,那么可以使用命名空间定义将这些 C#/.NET 命名空间都映射到同一个 url 下,使得 XAML 中的命名空间声明可以更少。
  3. 更加清晰的命名空间声明 可以通过将命名空间前缀定义得更加清晰,更有效地利用每一个字符,而不是一些结构化的 clr-namespace 和 assembly

这是怎么做到的呢?

在 System.Windows.Markup 命名空间下,有两个程序集级别的 Attribute,分别是 XmlnsDefinition 和 XmlnsPrefixXmlnsDefinition 定义某个 C# 命名空间和一段命名空间字符串是等意的,XmlnsPrefix 定义此命名空间的默认前缀(只是默认而已)。

using System.Windows.Markup;

[assembly: XmlnsDefinition("http://walterlv.github.io/demo", "Walterlv.NewCsprojDemo")]
[assembly: XmlnsPrefix("http://walterlv.github.io/demo", "w")] 

于是,利用这两个 Attribute 能够达到本文一开始的奇妙的效果。

如果你用工具(例如 ReSharper)自动生成命名空间前缀时,才会使用这样默认的命名空间前缀,否则,你随便填。

还有什么更高级的玩法吗?

也许你注意到 WPF 有一些一开始就帮你生成好的命名空间前缀,例如这些:

<UserControl
    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"> </UserControl> 

如果我们也把命名空间定义到这里会如何呢?

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "Walterlv.NewCsprojDemo")]

哇,我们竟然可以不用带前缀啦!

<UserControl
    x:Class="HuyaHearhira.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid> <DemoPage /> </Grid> </UserControl> 

这在项目内为一些几乎侵染全部代码的标记扩展是很棒的一波语法糖。例如——自己实现的本地化标记扩展。

一些限制

值得注意的是,XAML 命名空间的定义只会在外部程序集生效。这是说,如果你在 A 程序集中定义了命名空间,那么只有引用了 A 程序集的 B 或者 C 才可以使用到新定义的命名空间;A 程序集自身是没有办法使用此命名空间的。


参考资料

本文会经常更新,请阅读原文: https://walterlv.com/post/define-xmlns-of-for-xaml.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

目录
相关文章
|
6月前
|
C++
【C++ 命名空间】C++ 命名空间与嵌套命名空间入门指南
【C++ 命名空间】C++ 命名空间与嵌套命名空间入门指南
117 0
|
XML JSON 自然语言处理
SAP UI5 XML 视图中数据绑定路径语法的难点和易混淆点的专题讲解
SAP UI5 XML 视图中数据绑定路径语法的难点和易混淆点的专题讲解
|
编译器 C#
C#中导入其它自定义的命名空间
c#中怎么导入其它自定义的命名空间首先要确保已经导入了想要导入的自定义的命名空间。如上图这时编译器应该会报错,此时就需要手动去添加引用了,cs文件默认没有添加引用,只是加载了想要导入的命名空间,但是没有添加引用,所以需要自己要手动添加引用。切记!然后会有一个对话框选择你想引用的命名空间,点击确定即可。注意:一般而言,C#中如果没有改变那么一般项目的类名都默认是Program,在引用时需要注...
102 1
C#中导入其它自定义的命名空间
|
XML JSON JavaScript
SAP Fiori Elements 应用里标准模板 XML Fragment 加载的逻辑和 XMLPreprocessor 的作用
SAP Fiori Elements 应用里标准模板 XML Fragment 加载的逻辑和 XMLPreprocessor 的作用
|
XML 缓存 前端开发
SAP UI5 xml 视图里定义的控件,运行时如何创建其实例的?
SAP UI5 xml 视图里定义的控件,运行时如何创建其实例的?
|
XML JSON JavaScript
SAP UI5 XML 视图在实例化时就已经确定了 BindingSyntax 的实现版本了
SAP UI5 XML 视图在实例化时就已经确定了 BindingSyntax 的实现版本了
如何在 SAP Spartacus 自定义 UI 里使用标准 UI 的上下文数据 - let 关键字的用法
如何在 SAP Spartacus 自定义 UI 里使用标准 UI 的上下文数据 - let 关键字的用法
如何在 SAP Spartacus 自定义 UI 里使用标准 UI 的上下文数据 - let 关键字的用法
|
C# Windows
【C#】wpf中的xmlns命名空间为什么是一个网址,代表了什么意思
原文:【C#】wpf中的xmlns命名空间为什么是一个网址,代表了什么意思 新建一个wpf的项目,我们先来看下它默认的命名空间都是哪些? 可以看到xmlns有的是网址,有的是clr-namespace开头的一串字母。
1719 0
|
C# Windows .NET
XAML的命名空间
原文:XAML的命名空间 一个最简单的XAML例子   xmlns特征的语法格式如下:xmlns[:可选的映射前缀]="名称空间" xmlns后可以跟一个可选的映射前缀,之间用冒号分隔,如果没有写可选映射前缀,就意味着所有来自这个名称空间的标签都不用加前缀,这个没有映射前缀的名称空间称为“默认名称空间”,默认名称空间只能有一个。
648 0