65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (35投票s)

2010年9月22日

Ms-PL

4分钟阅读

viewsIcon

102469

downloadIcon

914

清理和管理您的 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"
  1. 它添加了 sdk 作为前缀,而不是添加“my”或任何其他词。如果我们能在添加自定义控件时触发这种行为,那就太好了。
  2. 它添加了一个常规(方案)URL,而不是 clr-namespace + assembly 引用。

要实现此行为,您需要执行以下步骤。

  1. 转到您要将 CLR 命名空间映射到自定义命名空间的项目。
  2. Properties 下打开 AssemblyInfo.cs
  3. 将以下内容添加到您的代码顶部。
    using System.Windows.Markup;
  4. 添加 XmlnsPrefixXmlnsDefinition 属性。

示例

[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 日:初始帖子
© . All rights reserved.