Esquemas de namespace personalizados XAML em Xamarin.Forms

Os tipos em uma biblioteca podem ser referenciados em XAML declarando um namespace XAML para a biblioteca, com a declaração de namespace especificando o nome do namespace CLR (Common Language Runtime) e um nome de assembly:

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

No entanto, especificar um namespace CLR e um nome de assembly em uma xmlns definição pode ser estranho e propenso a erros. Além disso, várias declarações de namespace XAML podem ser necessárias se a biblioteca contiver tipos em vários namespaces.

Uma abordagem alternativa é definir um esquema de namespace personalizado, como http://mycompany.com/schemas/controls, que mapeia para um ou mais namespaces CLR. Isso permite que uma única declaração de namespace XAML faça referência a todos os tipos em um assembly, mesmo que eles estejam em namespaces diferentes. Ele também permite que uma única declaração de namespace XAML faça referência a tipos em vários assemblies.

Para obter mais informações sobre namespaces XAML, consulte Namespaces XAML no Xamarin.Forms.

Definindo um esquema de namespace personalizado

O aplicativo de exemplo contém uma biblioteca que expõe alguns controles simples, como CircleButton:

using Xamarin.Forms;

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

Todos os controles na biblioteca residem no MyCompany.Controls namespace. Esses controles podem ser expostos a um assembly de chamada por meio de um esquema de namespace personalizado.

Um esquema de namespace personalizado é definido com a XmlnsDefinitionAttribute classe, que especifica o mapeamento entre um namespace XAML e um ou mais namespaces CLR. O XmlnsDefinitionAttribute usa dois argumentos: o nome do namespace XAML e o nome do namespace CLR. O nome do XmlnsDefinitionAttribute.XmlNamespace namespace XAML é armazenado na propriedade e o nome do namespace CLR é armazenado na XmlnsDefinitionAttribute.ClrNamespace propriedade.

Observação

A XmlnsDefinitionAttribute classe também tem uma propriedade chamada AssemblyName, que pode ser opcionalmente definida como o nome do assembly. Isso só é necessário quando um namespace CLR referenciado de um XmlnsDefinitionAttribute está em um assembly externo.

O XmlnsDefinitionAttribute deve ser definido no nível do assembly no projeto que contém os namespaces CLR que serão mapeados no esquema de namespace personalizado. O exemplo a seguir mostra o arquivo AssemblyInfo.cs do aplicativo de exemplo:

using Xamarin.Forms;
using MyCompany.Controls;

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

Esse código cria um esquema de namespace personalizado que mapeia a http://mycompany.com/schemas/controls URL para o MyCompany.Controls namespace CLR. Além disso, o Preserve atributo é especificado no assembly, para garantir que o vinculador preserve todos os tipos no assembly.

Importante

O Preserve atributo deve ser aplicado a classes no assembly que são mapeadas por meio do esquema de namespace personalizado ou aplicado a todo o assembly.

O esquema de namespace personalizado pode ser usado para resolução de tipo em arquivos XAML.

Consumindo um esquema de namespace personalizado

Para consumir tipos do esquema de namespace personalizado, o compilador XAML requer que haja uma referência de código do assembly que consome os tipos para o assembly que define os tipos. Isso pode ser feito adicionando uma classe que contém um Init método ao assembly que define os tipos que serão consumidos por meio de XAML:

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

Em seguida, o Init método pode ser chamado do assembly que consome tipos do esquema de namespace personalizado:

using Xamarin.Forms;
using MyCompany.Controls;

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

Aviso

A falha em incluir essa referência de código resultará na incapacidade do compilador XAML de localizar o assembly que contém os tipos de esquema de namespace personalizados.

Para consumir o CircleButton controle, um namespace XAML é declarado, com a declaração de namespace especificando a URL do esquema de namespace 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>

CircleButton As instâncias podem ser adicionadas ao declarando-as ContentPage com o prefixo de controls namespace.

Para localizar os tipos de esquema de namespace personalizados, Xamarin.Forms pesquisaremos assemblies referenciados para XmlnsDefinitionAttribute instâncias. Se o xmlns atributo de um elemento em um arquivo XAML corresponder ao valor da XmlNamespace propriedade em um XmlnsDefinitionAttribute, Xamarin.Forms o tentará usar o valor da XmlnsDefinitionAttribute.ClrNamespace propriedade para a resolução do tipo. Se a resolução de tipo falhar, Xamarin.Forms continuará a tentar a resolução de tipo com base em quaisquer instâncias correspondentes XmlnsDefinitionAttribute adicionais.

O resultado é que duas CircleButton instâncias são exibidas:

Botões circulares