使用自定义命名空间和前缀改进 XAML (WPF/Silverlight) 指南






4.76/5 (35投票s)
清理和管理您的 XAML 引用。这可以通过使用自定义命名空间(方案 URL)和自定义前缀来完成。
引言
在处理任何类型的应用程序时,将解决方案拆分成多个项目(程序集)和命名空间是一个好主意。随着项目的增长,您会发现命名空间的数量也会随之增加。如果您打算在 XAML 代码中使用这些命名空间中的类/控件,则必须使用以下语法声明它们。
xmlns:PREFIX="clr-namespace:NAMESPACE"
一个例子可以是
xmlns:conv="clr-namespace:Sandworks.Silverlight.NamespaceExample.Converters"
如果您引用了其他程序集,您还需要添加程序集名称。
xmlns:PREFIX="clr-namespace:NAMESPACE;assembly=ASSEMBLYNAME"
例如
xmlns:lib="clr-namespace:Sandworks.Silverlight.NamespaceExample.ClassLibrary.Converters
;assembly=Sandworks.Silverlight.NamespaceExample.ClassLibrary"
当您在项目中添加新的 XAML 控件(无论是 UserControl
还是 Page
)时,一些命名空间会默认添加。
这看起来应该是这样的
<UserControl x:Class="Sandworks.Silverlight.NamespaceExample.MainPage"
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"
但是,如前所述,当您的项目开始增长并且您需要使用不同的命名空间和程序集时,您的引用可能会开始堆积,并且您的 XAML 代码会变得臃肿。
实际示例
在代码中,您会发现以下项目
这些项目反映了一个真实应用程序可能的样子。所有控件都组织在单独的命名空间 Controls
中(甚至可以是另一个程序集),对于 Converters
也是如此。然后您可能有另一个包含更多转换器的程序集。也许这个程序集包含一些在您公司所有项目中使用的全局转换器。
查看 MainPage
的 XAML,您会注意到以下内容
<UserControl x:Class="Sandworks.Silverlight.NamespaceExample.MainPage"
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:my="clr-namespace:Sandworks.Silverlight.NamespaceExample.Controls"
xmlns:conv="clr-namespace:Sandworks.Silverlight.NamespaceExample.Converters"
xmlns:lib=
"clr-namespace:Sandworks.Silverlight.NamespaceExample.ClassLibrary.Converters;
assembly=Sandworks.Silverlight.NamespaceExample.ClassLibrary"
对于这个小型项目,我已经有了 3 个声明。想象一下再有 5 个程序集,以及 20 个 UserControl
使用了所有这些程序集。您最终会复制/粘贴、重复代码……
但是,我们有什么办法可以清理我们的 XAML 呢?
选项 1:自定义命名空间
在示例项目中,我将一个 Calendar
(非默认控件)添加到 MainPage
。您会看到 Visual Studio 会添加对 System.Windows.Controls
的引用,并会在您的 MainPage
中添加以下内容。
请注意以下事项
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
- 它添加了 sdk 作为前缀,而不是添加“my”或任何其他词。如果我们能在添加自定义控件时触发这种行为,那就太好了。
- 它添加了一个常规(方案)URL,而不是 clr-namespace + assembly 引用。
要实现此行为,您需要执行以下步骤。
- 转到您要将 CLR 命名空间映射到自定义命名空间的项目。
- 在
Properties
下打开AssemblyInfo.cs
。 - 将以下内容添加到您的代码顶部。
using System.Windows.Markup;
- 添加
XmlnsPrefix
和XmlnsDefinition
属性。
示例
[assembly: XmlnsPrefix("http://schemas.sandworks.com/sl/", "sw")]
[assembly: XmlnsDefinition("http://schemas.sandworks.com/sl/",
"Sandworks.Silverlight.NoNamespaceExample.Controls")]
[assembly: XmlnsDefinition("http://schemas.sandworks.com/sl/",
"Sandworks.Silverlight.NoNamespaceExample.Converters")]
如您所见,我们使用 XmlnsDefinition
属性将多个 CLR 命名空间映射到单个自定义命名空间。这样做的优点是您不限于单个程序集。在可下载的源代码中,您会看到应用程序和类库的这些定义。您可以考虑将所有控件、转换器、实用工具等组织到一个项目范围的命名空间下。
所以,我们之前是这样的
xmlns:my="clr-namespace:Sandworks.Silverlight.NamespaceExample.Controls"
xmlns:conv="clr-namespace:Sandworks.Silverlight.NamespaceExample.Converters"
xmlns:lib="clr-namespace:Sandworks.Silverlight.NamespaceExample.ClassLibrary.Converters;
assembly=Sandworks.Silverlight.NamespaceExample.ClassLibrary"
现在我们是这样的
xmlns:sw="http://schemas.sandworks.com/sl/"
再说一遍,想象一下再有 5 个程序集,以及 20 个 UserControl
使用了所有这些程序集。不再臃肿!
无论您引用 1 个还是 500 个程序集,您都将只使用这个自定义命名空间。
哦,如果您还没有注意到,XmlnsPrefix
声明了(该命名空间的)默认前缀,该前缀应该自动添加。当我添加 Calendar
时,我们自动获得了 sdk 前缀,现在对于我自己的控件,我将自动获得 sw 前缀。
选项 2:无命名空间
现在您不必停在选项 1。您实际上可以摆脱所有额外的命名空间。如前所述,您不限于单个程序集。这意味着多个程序集可以声明相同的命名空间。
如果您查看默认的 UserControl
,您总是会看到这一行。
<UserControl x:Class="Sandworks.Silverlight.NoNamespaceExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
好了,现在您可以将所有 CLR 命名空间映射到此自定义命名空间,如下所示。
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation",
"Sandworks.Silverlight.NoNamespaceExample.Controls")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation",
"Sandworks.Silverlight.NoNamespaceExample.Converters")]
现在您实现了 2 个目标
- 您无需在 XAML 控件中添加额外的命名空间引用。
- 您摆脱了前缀。由于表示命名空间在没有前缀的情况下声明,因此您的所有控件、转换器等都可以在没有前缀的情况下访问。这对于使用 IntelliSense 非常有用。
我个人更喜欢选项 1。完全删除命名空间和前缀也可能在更大的项目中成为问题。我倾向于为公司范围的程序集创建一个自定义命名空间,为项目特定的程序集/项目创建另一个自定义命名空间。
下载
源代码包含 2 种场景。一种是常规命名空间使用,另一种是自定义命名空间。
在此下载:Sandworks.Silverlight.NamespaceExample.zip
有关此主题的更多信息,请访问http://msdn.microsoft.com/en-us/library/cc189061(VS.95).aspx。
尽情享用!
历史
- 2010 年 9 月 22 日:初始帖子