Carga de XAML en tiempo de ejecución en Xamarin.Forms
El espacio de nombres Xamarin.Forms.Xaml
incluye dos métodos de extensión LoadFromXaml
que se pueden usar para cargar y analizar XAML en tiempo de ejecución.
Fondo
Cuando se construye una clase XAML Xamarin.Forms, se llama indirectamente al método LoadFromXaml
. Esto ocurre porque el archivo de código subyacente de una clase XAML llama al método InitializeComponent
desde su constructor:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
Cuando Visual Studio compila un proyecto que contiene un archivo XAML, analiza el archivo XAML para generar un archivo de código de C# (por ejemplo, MainPage.xaml.g.cs) que contiene la definición del método InitializeComponent
:
private void InitializeComponent()
{
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(MainPage));
...
}
El método InitializeComponent
llama al método LoadFromXaml
para extraer el archivo XAML (o su binario compilado) de la biblioteca de .NET Standard. Después de la extracción, inicializa todos los objetos definidos en el archivo XAML, los conecta todos juntos en relaciones de elementos primarios y secundarios, adjunta controladores de eventos definidos en código a eventos establecidos en el archivo XAML y establece el árbol resultante de objetos como el contenido de la página.
Carga de XAML en tiempo de ejecución
Los métodos LoadFromXaml
son public
y, por tanto, se puede llamar desde aplicaciones Xamarin.Forms para cargar y analizar XAML en tiempo de ejecución. Esto permite escenarios como una aplicación que descarga XAML desde un servicio web, crea la vista necesaria a partir del XAML y la muestra en la aplicación.
Advertencia
La carga de XAML en tiempo de ejecución tiene un coste de rendimiento significativo y, por lo general, se debe evitar.
El siguiente código muestra un ejemplo de uso sencillo:
using Xamarin.Forms.Xaml;
...
string navigationButtonXAML = "<Button Text=\"Navigate\" />";
Button navigationButton = new Button().LoadFromXaml(navigationButtonXAML);
...
_stackLayout.Children.Add(navigationButton);
En este ejemplo, se crea una instancia de Button
, con su valor de propiedad Text
establecido a partir del XAML definido en string
. Después, se agrega Button
a un objeto StackLayout
que se ha definido en el XAML de la página.
Nota:
Los métodos de extensión LoadFromXaml
permiten especificar un argumento de tipo genérico. Sin embargo, rara vez es necesario especificar el argumento de tipo, ya que se deducirá del tipo de la instancia en la que funciona.
El método LoadFromXaml
se puede usar para inflar cualquier XAML, con el ejemplo siguiente que infla un objeto ContentPage
y luego, navega hacia él:
using Xamarin.Forms.Xaml;
...
// See the sample for the full XAML string
string pageXAML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\nxmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\nx:Class=\"LoadRuntimeXAML.CatalogItemsPage\"\nTitle=\"Catalog Items\">\n</ContentPage>";
ContentPage page = new ContentPage().LoadFromXaml(pageXAML);
await Navigation.PushAsync(page);
Acceso a elementos
Cargar XAML en tiempo de ejecución con el método LoadFromXaml
no permite el acceso fuertemente tipado a los elementos XAML que tienen nombres de objeto en tiempo de ejecución especificados (mediante x:Name
). No obstante, estos elementos XAML se pueden recuperar mediante el método FindByName
y, después, se puede acceder a ellos si es necesario:
// See the sample for the full XAML string
string pageXAML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\nxmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\nx:Class=\"LoadRuntimeXAML.CatalogItemsPage\"\nTitle=\"Catalog Items\">\n<StackLayout>\n<Label x:Name=\"monkeyName\"\n />\n</StackLayout>\n</ContentPage>";
ContentPage page = new ContentPage().LoadFromXaml(pageXAML);
Label monkeyLabel = page.FindByName<Label>("monkeyName");
monkeyLabel.Text = "Seated Monkey";
...
En este ejemplo, se infla el XAML de un objeto ContentPage
. Este XAML incluye un objeto Label
denominado monkeyName
, que se recupera mediante el método FindByName
, antes de establecer su propiedad Text
.