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}" />