Xamarin.Forms 中的 XAML 自定义命名空间架构

Download Sample下载示例

可通过声明库的 XAML 命名空间来引用库中的类型,其中命名空间声明指定公共语言运行时 (CLR) 命名空间名称和程序集名称:

<ContentPage ...
             xmlns:controls="clr-namespace:MyCompany.Controls;assembly=MyCompany.Controls">
    ...
</ContentPage>

但是,在 xmlns 定义中指定 CLR 命名空间和程序集名称可能很难处理且容易出错。 此外,如果库包含多个命名空间中的类型,则可能需要多个 XAML 命名空间声明。

另一种方法是定义映射到一个或多个 CLR 命名空间的自定义命名空间架构,例如 http://mycompany.com/schemas/controls。 这使单个 XAML 命名空间声明能够引用程序集中的所有类型,即使它们位于不同的命名空间中也是如此。 它还支持单个 XAML 命名空间声明引用多个程序集中的类型。

有关 XAML 命名空间的详细信息,请参阅 Xamarin.Forms 中的 XAML 命名空间

定义自定义命名空间架构

示例应用程序包含公开一些简单控件的库,例如 CircleButton

using Xamarin.Forms;

namespace MyCompany.Controls
{
    public class CircleButton : Button
    {
        ...
    }
}

库中的所有控件都驻留在 MyCompany.Controls 命名空间中。 这些控件可以通过自定义命名空间架构向调用程序集公开。

自定义命名空间架构通过 XmlnsDefinitionAttribute 类定义,该类指定 XAML 命名空间与一个或多个 CLR 命名空间之间的映射。 XmlnsDefinitionAttribute 具有两个参数:XAML 命名空间名称和 CLR 命名空间名称。 XAML 命名空间名称存储在 XmlnsDefinitionAttribute.XmlNamespace 属性中,CLR 命名空间名称存储在 XmlnsDefinitionAttribute.ClrNamespace 属性中。

注意

XmlnsDefinitionAttribute 类还有一个名为 AssemblyName 的属性,可以选择将该属性设置为程序集的名称。 仅当从 XmlnsDefinitionAttribute 引用的 CLR 命名空间位于外部程序集中时,才需要这样做。

应在项目中的程序集级别定义 XmlnsDefinitionAttribute,其中包含将在自定义命名空间架构中映射的 CLR 命名空间。 以下示例显示了来自示例应用程序的 AssemblyInfo.cs 文件:

using Xamarin.Forms;
using MyCompany.Controls;

[assembly: Preserve]
[assembly: XmlnsDefinition("http://mycompany.com/schemas/controls", "MyCompany.Controls")]

此代码创建一个自定义命名空间架构,该架构将 http://mycompany.com/schemas/controls URL 映射到 MyCompany.Controls CLR 命名空间。 此外,Preserve 属性在程序集上指定,用于确保链接器保留程序集中的所有类型。

重要说明

Preserve 属性应应用于通过自定义命名空间架构映射的程序集中的类,或应用于整个程序集。

然后,自定义命名空间架构可用于 XAML 文件中的类型解析。

使用自定义命名空间架构

若要使用自定义命名空间架构中的类型,XAML 编译器需要有一个代码引用,即从使用类型的程序集引用到定义类型的程序集。 这可以通过向程序集添加一个包含 Init 方法的类来实现,该程序集定义了将通过 XAML 使用的类型:

namespace MyCompany.Controls
{
    public static class Controls
    {
        public static void Init()
        {
        }
    }
}

然后,可以从使用自定义命名空间架构中的类型的程序集调用 Init 方法:

using Xamarin.Forms;
using MyCompany.Controls;

namespace CustomNamespaceSchemaDemo
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            Controls.Init();
            InitializeComponent();
        }
    }
}

警告

未能包含此类代码引用将导致 XAML 编译器无法找到包含自定义命名空间架构类型的程序集。

若要使用 CircleButton 控件,需声明 XAML 命名空间,其中命名空间声明指定自定义命名空间架构 URL:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="http://mycompany.com/schemas/controls"
             x:Class="CustomNamespaceSchemaDemo.MainPage">
    <StackLayout Margin="20,35,20,20">
        ...
        <controls:CircleButton Text="+"
                               BackgroundColor="Fuchsia"
                               BorderColor="Black"
                               CircleDiameter="100" />
        <controls:CircleButton Text="-"
                               BackgroundColor="Teal"
                               BorderColor="Silver"
                               CircleDiameter="70" />
        ...
    </StackLayout>
</ContentPage>

然后,可以通过使用 controls 命名空间前缀声明 CircleButton 实例,将其添加到 ContentPage 中。

若要查找自定义命名空间架构类型,Xamarin.Forms 将在引用的程序集中搜索 XmlnsDefinitionAttribute 实例。 如果 XAML 文件中元素的 xmlns 属性与 XmlnsDefinitionAttribute 中的 XmlNamespace 属性值匹配,Xamarin.Forms 将尝试使用 XmlnsDefinitionAttribute.ClrNamespace 属性值来解析类型。 如果类型解析失败,Xamarin.Forms 将继续尝试基于任何其他匹配的 XmlnsDefinitionAttribute 实例进行类型解析。

结果是显示两个 CircleButton 实例:

Circle buttons