Xamarin.Forms 中的 XAML 自定义命名空间架构
可通过声明库的 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
实例: