WPF frente a Ciclo de vida de aplicaciones de Xamarin.Forms

Xamarin.Forms toma una gran cantidad de guías de diseño de los anteriores marcos basados en XAML, especialmente WPF. Sin embargo, en otros aspectos se desvía significativamente, lo que puede resultar problemático para las personas que intentan realizar la migración. En este documento se intentan identificar algunos de esos problemas y se proporcionan instrucciones, siempre que sea posible, para relacionar los conocimientos de WPF con Xamarin.Forms.

Ciclo de vida de la aplicación

El ciclo de vida de una aplicación en WPF y Xamarin.Forms es similar. Ambos se inician en código externo (plataforma) y abren la interfaz de usuario mediante una llamada de método. La diferencia es que Xamarin.Forms siempre se inicia en un ensamblado específico de la plataforma que, después, inicializa y crea la interfaz de usuario para la aplicación.

WPF

  • Main method > App > MainWindow

Nota:

De forma predeterminada, el método Main se genera automáticamente y no es visible en el código.

Xamarin.Forms

  • iOS: Main method > AppDelegate > App > ContentPage
  • Android: MainActivity > App > ContentPage
  • UWP: Main method > App(UWP) > MainPage(UWP) > App > ContentPage

La clase Application

Tanto WPF como Xamarin.Forms tienen una clase Application que se crea como singleton. En la mayoría de los casos, las aplicaciones se derivarán de esta clase para proporcionar una aplicación personalizada, aunque esto no es estrictamente necesario en WPF. Ambos exponen una propiedad Application.Current para localizar el singleton creado.

Propiedades globales y persistencia

Tanto WPF como Xamarin.Forms tienen un diccionario Application.Properties disponible donde puede almacenar objetos globales de nivel de aplicación que son accesibles en cualquier lugar de la aplicación. La diferencia clave es que Xamarin.Forms conservará los tipos primitivos almacenados en la colección cuando se suspenda la aplicación y los recargará cuando se vuelva a iniciar la aplicación. WPF no admite automáticamente ese comportamiento; en su lugar, la mayoría de los desarrolladores usan el almacenamiento aislado o la compatibilidad integrada con Settings.

Definición de páginas y árbol visual

WPF usa Window como elemento raíz para cualquier elemento visual de nivel superior. Esto define un objeto HWND en el mundo de Windows para mostrar información. Puede crear y mostrar simultáneamente todas las ventanas que quiera en WPF.

En Xamarin.Forms, el objeto visual de nivel superior siempre está definido por la plataforma; por ejemplo, en iOS es UIWindow. Xamarin.Forms representa el contenido en estas representaciones de plataforma nativas mediante una clase Page. Cada clase Page de Xamarin.Forms representa una "página" única en la aplicación, y solo está visible una cada vez.

Tanto el objeto Window en WPF como el objeto Page en Xamarin.Forms incluyen una propiedad Title para influir en el título que se muestra, y ambos tienen una propiedad Icon para mostrar un icono específico para la página (tenga en cuenta que el título y el icono no siempre están visibles en Xamarin.Forms). Además, puede cambiar las propiedades visuales comunes en ambos, como el color de fondo o la imagen.

Técnicamente es posible mostrar la representación en dos vistas de plataforma independientes (por ejemplo, definir dos objetos UIWindow y hacer que el segundo se represente en una pantalla externa o AirPlay). Para ello, se requiere código específico de la plataforma y no es una característica que admita directamente el propio Xamarin.Forms.

Vistas

La jerarquía visual de ambos marcos es similar. En WPF es un poco más profunda debido a su compatibilidad con documentos WYSIWYG.

WPF

DependencyObject - base class for all bindable things
   Visual - rendering mechanics
      UIElement - common events + interactions
         FrameworkElement - adds layout
            Shape - 2D graphics
            Control - interactive controls

Xamarin.Forms

BindableObject - base class for all bindable things
   Element - basic parent/child support + resources + effects
      VisualElement - adds visual rendering properties (color, fonts, transforms, etc.)
         View - layout + gesture support

Ciclo de vida de las vistas

Xamarin.Forms está orientado principalmente a escenarios para dispositivos móviles. Por lo tanto, las aplicaciones se activan, suspenden y reactivan a medida que el usuario interactúa con ellas. Esto es similar a hacer clic fuera del objeto Window en una aplicación WPF, y hay un conjunto de métodos con sus eventos correspondientes que puede invalidar o enlazar para supervisar este comportamiento.

Fin Método de WPF Método de Xamarin.Forms
Activación inicial ctor + Window.OnLoaded ctor + Page.OnStart
Mostrado Window.IsVisibleChanged Page.Appearing
Oculto Window.IsVisibleChanged Page.Disappearing
Suspender o perder el foco Window.OnDeactivated Page.OnSleep
Activar o establecer el foco Window.OnActivated Page.OnResume
Cerrada Window.OnClosing + Window.OnClosed N/D

Ambas plataformas admiten la ocultación o visualización de controles secundarios, en WPF se trata de una propiedad IsVisible de tres estados (visible, oculto y contraído). En Xamarin.Forms, solo están visibles u ocultos mediante la propiedad IsVisible.

Layout

El diseño de página se produce en las mismas dos fases (medición y organización) que en WPF. Puede enlazar con el diseño de página reemplazando los métodos siguientes en la clase Page de Xamarin.Forms:

Método Fin
OnChildMeasureInvalidated El tamaño preferido de un elemento secundario ha cambiado.
OnSizeAllocated Se ha asignado un ancho o una altura a la página.
Evento LayoutChanged El diseño o el tamaño de la página han cambiado.

No hay ningún evento de diseño global al que se llame actualmente, ni existe un evento global CompositionTarget.Rendering como en WPF.

Propiedades de diseño comunes

WPF y Xamarin.Forms admiten Margin para controlar el espaciado alrededor de un elemento y Padding para controlar el espaciado dentro de un elemento. Además, la mayoría de las vistas de diseño de Xamarin.Forms tienen propiedades para controlar el espaciado (por ejemplo, fila o columna).

Aparte de esto, la mayoría de los elementos tienen propiedades para influir en su posicionamiento en el contenedor primario:

WPF Xamarin.Forms Fin
HorizontalAlignment HorizontalOptions Opciones de izquierda/centro/derecha/estirar
VerticalAlignment VerticalOptions Opciones arriba/centro/abajo/estirar

Nota:

La interpretación real de estas propiedades depende del contenedor primario.

Vistas de diseño

WPF y Xamarin.Forms usan controles de diseño para posicionar los elementos secundarios. En la mayoría de los casos, son muy similares en términos de funcionalidad.

WPF Xamarin.Forms Estilo de diseño
StackPanel StackLayout Apilamiento infinito de izquierda a derecha o de arriba a abajo
Grid Cuadrícula Formato tabular (filas y columnas)
DockPanel N/D Acoplamiento a los bordes de la ventana
Lienzo AbsoluteLayout Posicionamiento de píxeles y coordenadas
WrapPanel N/D Ajuste de la pila
N/D RelativeLayout Posicionamiento basado en reglas relativas

Nota:

Xamarin.Forms no admite un objeto GridSplitter.

Ambas plataformas usan propiedades adjuntas para ajustar los elementos secundarios.

Representación

Los mecanismos de representación para WPF y Xamarin.Forms son radicalmente diferentes. En WPF, los controles que crea representan directamente el contenido en píxeles en la pantalla. WPF mantiene dos gráficos de objetos (árboles) para representar el contenido: el árbol lógico representa los controles tal como se definen en el código o en XAML, y el árbol visual muestra la representación real que se produce en la pantalla y que realiza directamente el elemento visual (por medio de un método de dibujo virtual) o la cual se realiza mediante un objeto ControlTemplate definido con XAML que se puede reemplazar o personalizar. Normalmente, el árbol visual es más complejo, ya que incluye elementos como bordes alrededor de los controles, etiquetas para contenido implícito, etc. WPF incluye un conjunto de API (LogicalTreeHelper y VisualTreeHelper) para examinar estos dos gráficos de objetos.

En Xamarin.Forms, los controles que define en un objeto Page son objetos de datos simples. Son similares a la representación del árbol lógico, pero nunca representan contenido por sí mismos. En su lugar, son el modelo de datos que influye en la representación de los elementos. La representación real se realiza mediante un conjunto independiente de representadores visuales que se asignan a cada tipo de control. Estos representadores se registran en cada uno de los proyectos específicos de la plataforma mediante ensamblados de Xamarin.Forms específicos de la plataforma. Puede ver una lista aquí. Además de reemplazar o extender el representador, Xamarin.Forms también admite Efectos, que se pueden usar para influir en la representación nativa en cada plataforma.

Árbol lógico o visual

No hay ninguna API expuesta para recorrer el árbol lógico en Xamarin.Forms, pero puede usar reflexión para obtener la misma información. Por ejemplo, este es un método que puede enumerar elementos secundarios lógicos con reflexión.

Elementos gráficos

Xamarin.Forms incluye un sistema de gráficos para dibujar elementos primitivos denominado Shapes. Para obtener más información sobre Shapes, consulte Xamarin.Forms Shapes. Además, puede incluir bibliotecas de terceros como SkiaSharp para obtener dibujos 2D multiplataforma.

Recursos

WPF y Xamarin.Forms tienen el concepto de recursos y diccionarios de recursos. Puede colocar cualquier tipo de objeto en un diccionario de recursos (ResourceDictionary) con una clave y, después, consultarlo con {StaticResource} para obtener cosas que no cambiarán o {DynamicResource} para obtener cosas que pueden cambiar en el diccionario en tiempo de ejecución. El uso y la mecánica son los mismos con una diferencia: Xamarin.Forms requiere la definición de un objeto ResourceDictionary para asignarlo a la propiedad Resources, mientras que WPF crea uno previamente y lo asigna automáticamente.

Por ejemplo, consulte la definición siguiente:

WPF

<Window.Resources>
   <Color x:Key="redColor">#ff0000</Color>
   ...
</Window.Resources>

Xamarin.Forms

<ContentPage.Resources>
   <ResourceDictionary>
      <Color x:Key="redColor">#ff0000</Color>
      ...
   </ResourceDictionary>
</ContentPage.Resources>

Si no define el objeto ResourceDictionary, se genera un error en tiempo de ejecución.

Estilos

Los estilos también son totalmente compatibles con Xamarin.Forms y se pueden usar para definir el tema de los elementos de Xamarin.Forms que componen la interfaz de usuario. Admiten desencadenadores (propiedades, eventos y datos), herencia mediante BasedOn y búsquedas de valores en recursos. Los estilos se aplican a los elementos explícitamente por medio de la propiedad Style o implícitamente sin proporcionar una clave de recurso, igual que en WPF.

Estilos de dispositivo

WPF tiene un conjunto de propiedades predefinidas (almacenadas como valores estáticos en un conjunto de clases estáticas, como SystemColors) que dictan los colores del sistema, las fuentes y las métricas en forma de valores y claves de recursos. Xamarin.Forms es similar, pero define un conjunto de estilos de dispositivo para representar las mismas cosas. El marco proporciona estos estilos y se establecen en valores basados en el entorno en tiempo de ejecución (por ejemplo, accesibilidad).

WPF

<Label Text="Title" Foreground="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}" />

Xamarin.Forms

<Label Text="Title" Style="{DynamicResource TitleStyle}" />