WPF en comparación con Xamarin.Forms: semejanzas y diferencias

Plantillas de control

WPF admite el concepto de plantillas de control que proporcionan las instrucciones de visualización de un control (Button, ListBox, etc.). Como se mencionó anteriormente, Xamarin.Forms usa clases de representación concretas para esto, las cuales interactúan con la plataforma nativa (iOS, Android, etc.) para visualizar el control.

Sin embargo, Xamarin.Forms tiene un tipo ControlTemplate que se usa para crear temas de objetos Page. Proporciona una definición de un objeto Page que proporciona contenido coherente, pero permite al usuario de la página cambiar colores, fuentes, etc., e incluso agregar elementos para que sea único para la aplicación.

Esto se usa habitualmente para crear cuadros de diálogo de autenticación y solicitudes de confirmación, y para proporcionar una apariencia de página normalizada, pero que se puede personalizar dentro de la aplicación. Como parte de esta compatibilidad, se usan muchos controles conocidos con nombre de WPF:

  1. ContentPage
  2. ContentView
  3. ContentPresenter
  4. TemplateBinding

Pero es importante saber que estos no sirven para el mismo propósito en Xamarin.Forms. Para más información sobre esta característica, consulte la página de documentación.

XAML

XAML se usa como lenguaje de marcado declarativo para WPF y Xamarin.Forms. En la mayor parte, la sintaxis es idéntica: la diferencia principal es que los objetos se definen o crean mediante los grafos XAML.

  • Xamarin.Forms admite la especificación XAML 2009; esto facilita la definición de datos como objetos string, int, etc., así como la definición de tipos genéricos y el envío de argumentos a constructores.

  • Actualmente, no hay ninguna manera de cargar XAML dinámicamente como lo hace WPF con XamlReader. Sin embargo, puede obtener la misma funcionalidad básica con un paquete NuGet.

Extensiones de marcado

Xamarin.Forms admite la extensión de XAML a través de extensiones de marcado, de forma parecida a como lo hace WPF. De serie, tiene los mismos bloques de creación básicos:

  1. {x:Array}
  2. {Binding}
  3. {DynamicResource}
  4. {x:Null}
  5. {x:Static}
  6. {StaticResource}
  7. {x:Type}

Además, incluye {x:Reference} de la especificación XAML 2009 y una extensión de marcado {TemplateBinding} que se usa para la versión especializada de ControlTemplate compatible con Xamarin.Forms.

Advertencia

La compatibilidad con ControlTemplate no es la misma, aunque tenga el mismo nombre.

Xamarin.Forms también admite extensiones de marcado personalizadas, pero la implementación es ligeramente diferente. En WPF, debe efectuar la derivación desde MarkupExtension: una clase base abstracta. En Xamarin.Forms, esto se reemplaza por una interfaz IMarkupExtension o IMarkupExtension<T> que es más flexible.

Al igual que WPF, el único método necesario es un método ProvideValue que devuelva el valor de la extensión de marcado.

Infraestructura de enlace

Uno de los conceptos básicos que se llevan a cabo es una infraestructura de enlace de datos que permite conectar las propiedades visuales con las propiedades de datos de .NET. Esto permite patrones arquitectónicos como MVVM. El diseño básico es idéntico: tiene una clase base enlazable, BindableObject, que en WPF es la clase DependencyObject. Esta clase base se usa como antecesor raíz para todos los objetos que participarán como destinos en el enlace de datos. A continuación, las clases derivadas exponen objetos BindableProperty que actúan como almacenamiento de respaldo de los valores de propiedad (estos se definen como objetos DependencyProperty en WPF).

Definición de propiedades enlazables

La definición de una propiedad enlazable en Xamarin.Forms es la misma que en WPF:

  1. El objeto se debe derivar de BindableObject.
  2. Debe haber un campo estático público de tipo BindableProperty declarado para definir la clave de almacenamiento de respaldo de la propiedad.
  3. Debe haber un contenedor de propiedades de instancia pública que use GetValue y SetValue para recuperar y cambiar el valor de las propiedades.

Para obtener un ejemplo completo, consulte Propiedades enlazables en Xamarin.Forms.

Propiedades adjuntas

Las propiedades asociadas son un subconjunto de la propiedad enlazable y funcionan de la misma manera que lo hacen en WPF. La principal diferencia es que el contenedor de propiedades se omite en este caso y se reemplaza por un conjunto de métodos get/set estáticos en la clase propietaria. Para más información, consulte Propiedades asociadas de Xamarin.Forms.

Uso del motor de enlace

El proceso para usar el motor de enlace es el mismo que en WPF. Se puede usar en código subyacente mediante la creación de un objeto Binding vinculado a un objeto de origen (cualquier tipo de .NET) y un valor de propiedad opcional (si se omite, trata el objeto de origen como la propiedad en sí, al igual que WPF). A continuación, puede usar SetBinding en cualquier BindableObject para asociar el enlace a BindableProperty.

Como alternativa, puedes definir la relación de enlace en XAML mediante BindingExtension. Tiene los mismos valores básicos que la extensión en WPF.

La compatibilidad con los enlaces y el motor se parecen más a la implementación de Silverlight que a WPF. Faltan varias características que no se implementaron en Xamarin.Forms:

  • No hay compatibilidad con las siguientes características de los enlaces:
    • BindingGroupName
    • BindsDirectlyToSource
    • IsAsync
    • MultiBinding
    • NotifyOnSourceUpdated
    • NotifyOnTargetUpdated
    • NotifyOnValidationError
    • UpdateSourceTrigger
    • UpdateSourceExceptionFilter
    • ValidatesOnDataErrors
    • ValidatesOnExceptions
    • ValidationRules collection
    • XPath
    • XmlNamespaceManager

RelativeSource

No se admiten los enlaces RelativeSource. En WPF, estos le permiten enlazar a otros elementos visuales definidos en XAML. En Xamarin.Forms, esta misma funcionalidad se puede lograr mediante la extensión de marcado {x:Reference}. Por ejemplo, suponiendo que tenemos un control con el nombre "otherControl" que tiene una propiedad Text, podemos enlazarlo de esta manera:

WPF

Text={Binding RelativeSource={RelativeSource otherControl}, Path=Text}

Xamarin.Forms

Text={Binding Source={x:Reference otherControl}, Path=Text}

Se puede usar la misma funcionalidad para la característica {RelativeSource Self}. Sin embargo, no hay compatibilidad con la localización de antecesores por tipo ({RelativeSource FindAncestor}).

Contexto de enlace

En WPF, puede definir un valor de propiedad DataContext que representa el origen de enlace predeterminado. Si no se define el origen de un enlace, se usa este valor de propiedad. El valor se hereda en la parte inferior del árbol visual, lo que permite definirlo en un nivel superior y que los elementos secundarios puedan usarlo.

En Xamarin.Forms, la misma característica está disponible, pero el nombre de la propiedad es BindingContext.

Convertidores de valores

Los convertidores de valores son totalmente compatibles con Xamarin.Forms, al igual que WPF. Se usa la misma forma de interfaz, pero Xamarin.Forms tiene la interfaz definida en el espacio de nombres Xamarin.Forms.

Modelo-Vista-Modelo de vista

MVVM es totalmente compatible con WPF y Xamarin.Forms.

WPF incluye un RoutedCommand integrado que se usa en algunas ocasiones; Xamarin.Forms no tiene compatibilidad integrada con comandos más allá de la definición de interfaz de ICommand. Puede incluir diversos marcos de MVVM para agregar las clases base necesarias para implementar MVVM.

INotifyPropertyChanged e INotifyCollectionChanged

Ambas interfaces son totalmente compatibles con los enlaces de Xamarin.Forms. A diferencia de muchos marcos basados en XAML, las notificaciones de cambio de propiedad se pueden generar en subprocesos en segundo plano en Xamarin.Forms (al igual que WPF) y el motor de enlace pasará correctamente al subproceso de interfaz de usuario.

Además, ambos entornos admiten SynchronizationContext y async/await para realizar una serialización de subprocesos adecuada. WPF incluye la clase Dispatcher en todos los elementos visuales, Xamarin.Forms tiene un método estático Device.BeginInvokeOnMainThread que también se puede usar (aunque es preferible usar SynchronizationContext para la codificación multiplataforma).

  • Xamarin.Forms incluye un elemento ObservableCollection<T> que admite notificaciones de cambio de colección.
  • Puede usar BindingBase.EnableCollectionSynchronization para habilitar las actualizaciones entre subprocesos de una colección. La API es ligeramente diferente de la variación de WPF, consulte los documentos para obtener los detalles de uso.

Plantillas de datos

Las plantillas de datos se admiten en Xamarin.Forms para personalizar la representación de una fila (celda) ListView. A diferencia de WPF que puede usar elementos DataTemplate para cualquier control orientado al contenido, Xamarin.Forms solo los usa actualmente para ListView. La definición de plantilla se puede definir insertada (asignada a la propiedad ItemTemplate) o como un recurso de ResourceDictionary.

Además, no son tan flexibles como su equivalente de WPF.

  1. El elemento raíz de DataTemplate debe ser siempre un objeto ViewCell.
  2. Los desencadenadores de datos son totalmente compatibles con una plantilla de datos, pero deben incluir una propiedad DataType que indique el tipo de propiedad a la que está asociado el desencadenador.
  3. DataTemplateSelector también se admite, pero se deriva de DataTemplate y, por tanto, se asigna directamente a la propiedad ItemTemplate (en lugar de a ItemTemplateSelector como en WPF).

ItemsControl

No hay ningún equivalente integrado a un elemento ItemsControl en Xamarin.Forms; pero hay uno personalizado para Xamarin.Forms disponible aquí.

Controles de usuario

En WPF, los elementos UserControl se usan para proporcionar una sección de la interfaz de usuario que tiene un comportamiento asociado. En Xamarin.Forms, usamos ContentView con el mismo propósito. Ambos admiten el enlace y la inclusión en XAML.

WPF incluye un elemento NavigationService poco utilizado que podría usarse para proporcionar una característica de navegación "similar a la de un explorador". Sin embargo, la mayoría de las aplicaciones no tuvieron en cuenta esto y, en su lugar, usaron elementos Window diferentes o secciones diferentes de la ventana para mostrar datos.

En los dispositivos telefónicos, las distintas pantallas suelen ser la solución y, por tanto, Xamarin.Forms incluye compatibilidad con varias formas de navegación:

Estilo de navegación Tipo de página
Basado en pila (inserción o extracción) NavigationPage
Maestro y detalles MasterDetailPage
Pestañas TabbedPage
Deslizar el dedo hacia la izquierda o la derecha CarouselView

NavigationPage es el enfoque más común, y cada página tiene una propiedad Navigation que se puede usar para insertar o extraer páginas de la pila de navegación. Esta es la clase equivalente más cercana a NavigationService que se encuentra en WPF.

Navegación a direcciones URL

WPF es una tecnología diseñada para entornos de escritorio y puede aceptar parámetros de línea de comandos para dirigir el comportamiento de inicio. Xamarin.Forms puede usar la vinculación de dirección URL profunda para saltar a una página en el inicio.