Resumen del capítulo 23. Desencadenadores y comportamientos
Nota:
Este libro se publicó en la primavera de 2016 y no se ha actualizado desde entonces. Gran parte del libro sigue siendo útil, pero algunos de los materiales están anticuados y algunos temas ya no son completamente correctos o completos.
Los desencadenadores y los comportamientos son similares, ya que ambos están diseñados para usarse en archivos XAML con el fin de simplificar las interacciones de los elementos más allá del uso de los enlaces de datos y para ampliar la funcionalidad de los elementos XAML. Los desencadenadores y los comportamientos casi siempre se usan con objetos visuales de la interfaz de usuario.
Para admitir desencadenadores y comportamientos, tanto VisualElement
como Style
admiten dos propiedades de colección:
VisualElement.Triggers
yStyle.Triggers
de tipoIList<TriggerBase>
VisualElement.Behaviors
yStyle.Behaviors
de tipoIList<Behavior>
Desencadenadores
Un desencadenador es una condición (un cambio de propiedad o la activación de un evento) que da como resultado una respuesta (otro cambio de propiedad o ejecución de código). La propiedad Triggers
de VisualElement
y Style
es de tipo IList<TriggersBase>
. TriggerBase
es una clase abstracta de la que derivan cuatro clases selladas:
Trigger
para respuestas basadas en cambios de propiedadEventTrigger
para respuestas basadas en activaciones de eventosDataTrigger
para respuestas basadas en enlaces de datosMultiTrigger
para respuestas basadas en varios desencadenadores
El desencadenador siempre se establece en el elemento cuya propiedad está cambiando por el desencadenador.
El desencadenador más sencillo
La clase Trigger
comprueba si se ha cambiado un valor de propiedad y responde estableciendo otra propiedad del mismo elemento.
Trigger
define tres propiedades:
Property
de tipoBindableProperty
Value
de tipoObject
Setters
de tipoIList<SetterBase>
, la propiedad de contenido deTrigger
Además, Trigger
requiere que se la siguiente propiedad heredada de TriggerBase
se establezca en:
TargetType
para indicar el tipo del elemento con el que está asociadoTrigger
.
Property
y Value
componen la condición, y la colección Setters
es la respuesta. Cuando el elemento Property
indicado tiene el valor indicado por Value
, se aplican los objetos Setter
de la colección Setters
. Cuando Property
tiene un valor diferente, se quitan los establecedores. Setter
define dos propiedades que son iguales a las dos primeras propiedades de Trigger
:
En el ejemplo EntryPop se muestra cómo un Trigger
aplicado a un Entry
puede aumentar el tamaño de Entry
a través de la propiedad Scale
cuando la propiedad IsFocused
de Entry
es true
.
Aunque no es común, Trigger
se puede establecer en el código, como se muestra en el ejemplo EntryPopCode.
En el ejemplo StyledTriggers se muestra cómo se puede establecer Trigger
en Style
para que se aplique a varios elementos Entry
.
Acciones y animaciones de desencadenadores
También es posible ejecutar un poco de código basado en un desencadenador. Este código puede ser una animación destinada a una propiedad. Una forma habitual es usar EventTrigger
, que define dos propiedades:
Event
de tipostring
, el nombre de un eventoActions
de tipoIList<TriggerAction>
, una lista de acciones que se ejecutarán como respuesta.
Para usar esto, debe escribir una clase que derive de TriggerAction<T>
, generalmente TriggerAction<VisualElement>
. Puede definir las propiedades de esta clase. Se trata de propiedades de CLR sin formato en lugar de propiedades enlazables porque TriggerAction
no se deriva de BindableObject
. Debe reemplazar el método Invoke
al que se llama cuando se invoca la acción. El argumento es el elemento de destino.
La clase ScaleAction
de la biblioteca Xamarin.FormsBook.Toolkit es un ejemplo. Llama a la propiedad ScaleTo
para animar la propiedad Scale
de un elemento. Dado que una de sus propiedades es de tipo Easing
, la clase EasingConverter
permite usar los campos estáticos Easing
estándar en XAML.
En el ejemplo EntrySwell se muestra cómo invocar ScaleAction
desde objetos EventTrigger
que supervisan los eventos Focused
y Unfocused
.
En el ejemplo CustomEasingSwell se muestra cómo definir una función de aceleración personalizada para ScaleAction
en un archivo de código subyacente.
También puede invocar acciones mediante Trigger
(como se distingue de EventTrigger
). Esto requiere que tenga en cuenta que TriggerBase
define dos colecciones:
EnterActions
de tipoIList<TriggerAction>
ExitActions
de tipoIList<TriggerAction>
En el ejemplo EnterExitSwell se muestra cómo usar estas colecciones.
Más desencadenadores de eventos
La clase ScaleUpAndDownAction
de la biblioteca Xamarin.FormsBook.Toolkit llama a ScaleTo
dos veces para escalar y reducir verticalmente. En el ejemplo ButtonGrowth se usa esto con un estilo EventTrigger
para proporcionar comentarios visuales cuando se presiona un elemento Button
. Esta animación doble también es posible mediante dos acciones en la colección de tipo DelayedScaleAction
.
La clase ShiverAction
de la biblioteca Xamarin.FormsBook.Toolkit define una acción Shiver personalizable. En el ejemplo ShiverButtonDemo se muestra este comportamiento.
La clase NumericValidationAction
de la biblioteca Xamarin.FormsBook.Toolkit está restringida a elementos Entry
y establece la propiedad TextColor
en rojo si la propiedad Text
no es double
. En el ejemplo TriggerEntryValidation se muestra este comportamiento.
Desencadenadores de datos
DataTrigger
es similar a Trigger
, salvo que en lugar de supervisar una propiedad para los cambios de valor, supervisa un enlace de datos. Esto permite que una propiedad de un elemento afecte a una propiedad de otro elemento.
DataTrigger
define tres propiedades:
En el ejemplo GenderColors se requiere la biblioteca SchoolOfFineArt y se establecen los colores de los nombres de los alumnos en azul o rosa en función de la propiedad Sex
:
En el ejemplo ButtonEnabler se establece la propiedad IsEnabled
de Entry
en False
si la propiedad Length
de la propiedad Text
de Entry
es igual a 0. Observe que la propiedad Text
se inicializa en una cadena vacía; de forma predeterminada, es null
, y DataTrigger
no funcionaría correctamente.
Combinar condiciones en MultiTrigger
MultiTrigger
es una colección de condiciones. Cuando todos son true
, se aplican los establecedores. La clase define dos propiedades:
Conditions
de tipoIList<Condition>
Setters
de tipoIList<Setter>
Condition
es una clase abstracta y tiene dos clases descendientes:
PropertyCondition
, que tiene propiedadesProperty
yValue
comoTrigger
BindingCondition
, que tiene propiedadesBinding
yValue
comoDataTrigger
En el ejemplo AndConditions, BoxView
solo se colorea cuando se activan cuatro elementos Switch
.
En el ejemplo OrConditions se muestra cómo puede convertir BoxView
en un color cuando cualquiera de los cuatro elementos Switch
está activado. Esto requiere una aplicación de la ley de De Morgan e invertir toda la lógica.
La combinación de la lógica AND y OR no es tan fácil y, por lo general, requiere elementos Switch
invisibles para los resultados intermedios. En el ejemplo XorConditions se muestra cómo se puede habilitar Button
si uno de dos elementos Entry
tiene algún texto escrito, pero no si ambos tienen algún texto escrito.
Comportamientos
Todo lo que puede hacer con un desencadenador, también puede hacerlo con un comportamiento, pero los comportamientos siempre requieren una clase que deriva de Behavior<T>
e invalida los dos métodos siguientes:
El argumento es el elemento al que está asociado el comportamiento. Por lo general, el método OnAttachedTo
asocia algunos controladores de eventos y OnDetachingFrom
los desasocia. Dado que este tipo de clase normalmente guarda algún estado, normalmente no se puede compartir en Style
.
El ejemplo BehaviorEntryValidation es similar a TriggerEntryValidation, salvo que usa un comportamiento; la clase NumericValidationBehavior
de la biblioteca Xamarin.FormsBook.Toolkit.
Comportamientos con propiedades
Behavior<T>
deriva de Behavior
, que se deriva de BindableObject
, de modo que las propiedades enlazables se pueden definir en un comportamiento. Estas propiedades pueden estar activas en los enlaces de datos.
Esto se muestra en el programa EmailValidationDemo que usa la clase ValidEmailBehavior
en la biblioteca Xamarin.FormsBook.Toolkit. ValidEmailBehavior
tiene una propiedad enlazable de solo lectura y sirve como origen en los enlaces de datos.
El ejemplo EmailValidationConv utiliza este mismo comportamiento para mostrar otro tipo de indicador para indicar que una dirección de correo electrónico es válida.
El ejemplo EmailValidationTrigger es una variación del ejemplo anterior. ButtonGlide usa DataTrigger
en combinación con ese comportamiento.
Alternancia y casillas
Es posible encapsular el comportamiento de un botón de alternancia en una clase, como ToggleBehavior
en la biblioteca Xamarin.FormsBook.Toolkit y, a continuación, definir todos los objetos visuales para la alternancia completa en XAML.
En el ejemplo ToggleLabel se usa ToggleBehavior
con DataTrigger
para usar Label
con dos cadenas de texto para la alternancia.
El ejemplo FormattedTextToggle amplía este concepto cambiando entre dos objetos FormattedString
.
La clase ToggleBase
de la biblioteca Xamarin.FormsBook.Toolkit se deriva de ContentView
, define una propiedad IsToggled
e incorpora un elemento ToggleBehavior
para la lógica de alternancia. De este modo, resulta más fácil definir el botón de alternancia en XAML, tal como se muestra en el ejemplo TraditionalCheckBox.
SwitchCloneDemo incluye una clase SwitchClone
que se deriva de ToggleBase
y usa una clase TranslateAction
para construir un botón de alternancia similar a Xamarin.FormsSwitch
.
RotateAction
en Xamarin.FormsBook.Toolkit proporciona una animación que se usa para crear una opción animada en el ejemplo LeverToggle.
Respuesta a pulsaciones
Una desventaja de EventTrigger
es que no se puede adjuntar a TapGestureRecognizer
para responder a las pulsaciones. Solucionar ese problema es el propósito de TapBehavior
en Xamarin.FormsBook.Toolkit.
En el ejemplo BoxViewTapShiver se usa TapBehavior
para usar el elemento ShiverAction
anterior para los elementos BoxView
que se pulsan.
En el ejemplo ShiverViews se muestra cómo se reduce el marcado mediante la encapsulación de una clase ShiverView
.
Botones de radio
La biblioteca Xamarin.FormsBook.Toolkittambién tiene una clase RadioBehavior
para crear botones de radio agrupados por un nombre de grupo string
.
El programa RadioLabels usa cadenas de texto para su botón de radio. En el ejemplo RadioStyle se usa Style
para la diferencia de la apariencia entre los botones seleccionados y no seleccionados. En el ejemplo RadioImages se usan imágenes en casillas para sus botones de radio:
En el ejemplo TraditionalRadios se dibujan botones de radio tradicionales con un punto dentro de un círculo.
Atenuaciones y orientación
El ejemplo final, MultiColorSliders, permite cambiar entre tres vistas de selección de color diferentes mediante botones de radio. Las tres vistas se intensifican y atenúan con FadeEnableAction
en la biblioteca Xamarin.FormsBook.Toolkit.
El programa también responde a los cambios de orientación entre vertical y horizontal con GridOrientationBehavior
en la biblioteca Xamarin.FormsBook.Toolkit.