当前位置: 首页 > news >正文

让你编写的控件库在 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-namespaceassembly

这是怎么做到的呢?

System.Windows.Markup 命名空间下,有两个程序集级别的 Attribute,分别是 XmlnsDefinitionXmlnsPrefixXmlnsDefinition 定义某个 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 程序集自身是没有办法使用此命名空间的。


参考资料

  • wpf - How to make XmlnsDefinition work on the local assembly? - Stack Overflow
  • XmlnsDefinition doesn’t work in the same assembly

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • Sdk 风格的 csproj 对 WPF/UWP 支持不太好?有第三方 SDK 可以用!MSBuild.Sdk.Extras
  • 为博客或个人站点的 Markdown 添加 LaTeX 公式支持
  • 如何让 .NET Core 命令行程序接受密码的输入而不显示密码明文
  • 如何编写 WPF 的标记扩展 MarkupExtension,即便在 ControlTemplate/DataTemplate 中也能生效
  • PasswordVault —— 在 UWP 应用中安全地保存密码
  • 如何在 MSBuild Target(Exec)中报告编译错误和编译警告
  • 将 .NET Core 项目打一个最简单的 NuGet 源码包,安装此包就像直接把源码放进项目一样
  • 使用 LINQ to XML,.NET 让生成 XML 文件变得和直接写 XML 一样轻松
  • git subtree 不断增加的推送时间,解不玩的冲突!这篇文章应该能救你
  • 阻止某个 NuGet 包意外升级
  • 解读 Microsoft.NET.Sdk 的源码,你能定制各种奇怪而富有创意的编译过程
  • 在 Visual Studio 的解决方案资源管理器中隐藏一些文件
  • 长期支持 LTS(Long-term Support)是怎样的一种支持方式
  • .NET Standard 的管理策略
  • 如何在 .NET/C# 代码中安全地结束掉一个控制台应用程序?通过发送 Ctrl+C 信号来结束
  • 0基础学习移动端适配
  • Android Volley源码解析
  • conda常用的命令
  • cookie和session
  • extract-text-webpack-plugin用法
  • MySQL QA
  • Python实现BT种子转化为磁力链接【实战】
  • React组件设计模式(一)
  • scala基础语法(二)
  • Vue全家桶实现一个Web App
  • 爱情 北京女病人
  • 创建一种深思熟虑的文化
  • 给第三方使用接口的 URL 签名实现
  • 理解在java “”i=i++;”所发生的事情
  • 深入浅出webpack学习(1)--核心概念
  • 一、python与pycharm的安装
  • 鱼骨图 - 如何绘制?
  • Mac 上flink的安装与启动
  • 关于Android全面屏虚拟导航栏的适配总结
  • 选择阿里云数据库HBase版十大理由
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • #100天计划# 2013年9月29日
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • ( 10 )MySQL中的外键
  • (23)Linux的软硬连接
  • (差分)胡桃爱原石
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (离散数学)逻辑连接词
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)fock函数详解
  • ***利用Ms05002溢出找“肉鸡
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET 8.0 发布到 IIS
  • .NET关于 跳过SSL中遇到的问题
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • /bin/bash^M: bad interpreter: No such file or directory
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)