Esquemas de espacio de nombres personalizado XAML en Xamarin.Forms

Se puede hacer referencia a los tipos de una biblioteca en XAML declarando un espacio de nombres XAML para la biblioteca, especificando en la declaración del espacio de nombres el nombre del espacio de nombres de Common Language Runtime (CLR) y un nombre de ensamblado:

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

Sin embargo, especificar un espacio de nombres CLR y un nombre de ensamblado en una definición xmlns puede ser incómodo y propenso a errores. Además, pueden ser necesarias varias declaraciones de espacios de nombres XAML si la biblioteca contiene tipos en varios espacios de nombres.

Un enfoque alternativo consiste en definir un esquema de espacio de nombres personalizado, como http://mycompany.com/schemas/controls, que se asigna a uno o varios espacios de nombres CLR. Esto permite que una única declaración de espacio de nombres XAML haga referencia a todos los tipos de un ensamblado, aunque se encuentren en espacios de nombres diferentes. También permite que una única declaración de espacio de nombres XAML haga referencia a tipos de varios ensamblados.

Para obtener más información sobre los espacios de nombres XAML, consulta Espacios de nombres XAML en Xamarin.Forms.

Definir un esquema de espacio de nombres personalizado

La aplicación de ejemplo contiene una biblioteca que expone algunos controles simples, como CircleButton:

using Xamarin.Forms;

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

Todos los controles de la biblioteca residen en el espacio de nombres MyCompany.Controls. Estos controles se pueden exponer a un ensamblado de llamada a través de un esquema de espacio de nombres personalizado.

Un esquema de espacio de nombres personalizado se define con la clase XmlnsDefinitionAttribute, que especifica la asignación entre un espacio de nombres XAML y uno o más espacios de nombres CLR. XmlnsDefinitionAttribute toma dos parámetros: el nombre del espacio de nombres XML/XAML y el nombre del espacio de nombres CLR. El nombre del espacio de nombres XAML se almacena en la propiedad XmlnsDefinitionAttribute.XmlNamespace y el nombre del espacio de nombres CLR se almacena en la propiedad XmlnsDefinitionAttribute.ClrNamespace.

Nota:

La clase XmlnsDefinitionAttribute también tiene una propiedad denominada AssemblyName, que puede establecerse opcionalmente en el nombre del ensamblado. Esto solo es necesario cuando un espacio de nombres CLR al que se hace referencia desde un elemento XmlnsDefinitionAttribute está en un ensamblado externo.

XmlnsDefinitionAttribute debe definirse en el nivel de ensamblado del proyecto que contiene los espacios de nombres CLR que se asignarán en el esquema de espacio de nombres personalizado. En el ejemplo siguiente se muestra el archivo AssemblyInfo.cs de la aplicación de ejemplo:

using Xamarin.Forms;
using MyCompany.Controls;

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

Este código crea un esquema de espacio de nombres personalizado que asigna la dirección URL http://mycompany.com/schemas/controls al espacio de nombres CLR MyCompany.Controls. Además, el atributo Preserve se especifica en el ensamblado para asegurarse de que el enlazador conserva todos los tipos en el ensamblado.

Importante

El atributo Preserve debe aplicarse a las clases del ensamblado que se asignan a través del esquema de espacio de nombres personalizado o aplicarse a todo el ensamblado.

Después, el esquema de espacio de nombres personalizado se puede usar para la resolución de tipos en archivos XAML.

Consumo de un esquema de espacio de nombres personalizado

Para consumir tipos del esquema de espacio de nombres personalizado, el compilador XAML requiere que haya una referencia de código del ensamblado que consume los tipos, al ensamblado que define los tipos. Esto se puede lograr agregando una clase que contiene un método Init al ensamblado que define los tipos que se consumirán a través de XAML:

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

El método Init se puede llamar entonces desde el ensamblado que consume tipos del esquema del espacio de nombres personalizado:

using Xamarin.Forms;
using MyCompany.Controls;

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

Advertencia

Si no se incluye dicha referencia de código, el compilador XAML no podrá encontrar el ensamblado que contiene los tipos de esquema de espacio de nombres personalizado.

Para consumir el control CircleButton, se declara un espacio de nombres XAML, con la declaración del espacio de nombres especificando la dirección URL del esquema del espacio de nombres personalizado:

<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>

Luego, se pueden agregar instancias de CircleButton a ContentPage declarándolas con el prefijo del espacio de nombres controls.

Para buscar los tipos de esquema de espacio de nombres personalizados, Xamarin.Forms buscará ensamblados a los que se hace referencia para las instancias XmlnsDefinitionAttribute. Si el atributo xmlns de un elemento de un archivo XAML coincide con el valor de la propiedad XmlNamespace en un XmlnsDefinitionAttribute, Xamarin.Forms intentará usar el valor de la propiedad XmlnsDefinitionAttribute.ClrNamespace para la resolución del tipo. Si se produce un error en la resolución de tipo, Xamarin.Forms seguirá intentando la resolución de tipo basándose en cualquier instancia XmlnsDefinitionAttribute adicional que coincida.

El resultado es que se muestran dos instancias de CircleButton:

Botones circulares