Compartir vía


Eventos de cambio de propiedades

Windows Presentation Foundation (WPF) define varios eventos que se producen como respuesta a un cambio en el valor de una propiedad. A menudo, la propiedad es una propiedad de dependencia. A veces, el propio evento es un evento enrutado y, otras, es un evento de Common Language Runtime (CLR) estándar. La definición del evento varía según el escenario, porque algunos cambios de propiedad deben enrutarse a través de un árbol de elementos, mientras que otros cambios de propiedad, generalmente, solo son de interés para el objeto en el que se modifica la propiedad.

Identificar un evento de cambio de propiedad

No todos los eventos que informan de un cambio de propiedad se identifican de manera explícita como evento de cambio de propiedad mediante un patrón de signatura o de nomenclatura. Por lo general, la descripción del evento de la documentación del SDK indica si el evento está vinculado directamente a un cambio de valor de propiedad y proporciona referencias cruzadas entre la propiedad y el evento.

Eventos RoutedPropertyChanged

Algunos eventos usan un delegado y un tipo de datos de evento que se usan explícitamente para los eventos de cambio de propiedad. El tipo de datos del evento es RoutedPropertyChangedEventArgs<T>y el delegado es RoutedPropertyChangedEventHandler<T>. El delegado y los datos del evento tienen un parámetro de tipo genérico que se usa para especificar el tipo real de la propiedad que cambia al definir el controlador. Los datos del evento contienen dos propiedades, OldValue y NewValue, que se pasan como argumento de tipo en los datos del evento.

La parte "Routed" del nombre indica que el evento con la propiedad cambiada se registra como evento enrutado. La ventaja de enrutar un evento con la propiedad cambiada es que el nivel superior de un control puede recibir eventos con la propiedad cambiada si las propiedades de los elementos secundarios (las partes compuestas del control) cambian de valor. Por ejemplo, supongamos que crea un control que incorpora un control RangeBase, como Slider. Si el valor de la propiedad Value cambia en la parte del control deslizante, puede que quiera controlar ese cambio en el control primario en lugar de en la parte.

Dado que tiene un valor anterior y uno nuevo, puede ser tentador usar este controlador de eventos como un validador para el valor de propiedad. Sin embargo, no es la intención de diseño de la mayoría de los eventos con la propiedad cambiada. Por lo general, los valores se proporcionan para que pueda actuar sobre esos valores en otras áreas de la lógica del código, pero no se recomienda modificar los valores desde el controlador de eventos y es posible que se cause una recursividad involuntaria según cómo se implemente el controlador.

Si la propiedad es una propiedad de dependencia personalizada o si trabaja con una clase derivada donde ha definido el código de creación de instancias, hay un mecanismo mucho mejor para realizar el seguimiento de cambios de propiedad. Este mecanismo está integrado en el sistema de propiedades de WPF: las devoluciones de llamada del sistema de propiedades CoerceValueCallback y PropertyChangedCallback. Para obtener más información acerca de cómo puede usar el sistema de propiedades de WPF para la validación y la coerción, consulte Devoluciones de llamada y validación de las propiedades de dependencia y Propiedades de dependencia personalizadas.

Eventos DependencyPropertyChanged

Otro par de tipos que forman parte de un escenario de evento de cambio de propiedad son DependencyPropertyChangedEventArgs y DependencyPropertyChangedEventHandler. No se enrutan los eventos para estos cambios de propiedad: son eventos CLR estándares. DependencyPropertyChangedEventArgs es un tipo de notificación de datos de evento inusual porque no deriva de EventArgs y DependencyPropertyChangedEventArgs es una estructura, no una clase.

Los eventos que usan DependencyPropertyChangedEventArgs y DependencyPropertyChangedEventHandler son ligeramente más comunes que los eventos RoutedPropertyChanged. Un ejemplo de un evento que usa estos tipos es IsMouseCapturedChanged.

Igual que RoutedPropertyChangedEventArgs<T>, DependencyPropertyChangedEventArgs también comunica un valor antiguo y uno nuevo de la propiedad. Además, se aplican las mismas consideraciones sobre lo que puede hacer con los valores. Por lo general, no se recomienda que intente volver a cambiar los valores en el remitente como respuesta al evento.

Desencadenadores de propiedad

Un concepto estrechamente relacionado con un evento de cambio de propiedad es un desencadenador de propiedad. Un desencadenador de propiedad se crea dentro de un estilo o una plantilla y le permite crear un comportamiento condicional basado en el valor de la propiedad donde se asigna el desencadenador de propiedad.

La propiedad de un desencadenador de propiedad debe ser una propiedad de dependencia. Puede ser (y, con frecuencia, lo es) una propiedad de dependencia de solo lectura. Un buen indicador de si una propiedad de dependencia expuesta por un control está diseñada parcialmente como un desencadenador de propiedad es si el nombre de propiedad comienza por "Is". Las propiedades que tienen este nombre suelen ser una propiedad de dependencia booleana de solo lectura en que el escenario principal para la propiedad está informando de un estado de control que puede tener consecuencias en la interfaz de usuario en tiempo real y, por lo tanto, es un candidato de desencadenador de propiedad.

Algunas de estas propiedades también tienen un evento de cambio de propiedad dedicado. Por ejemplo, la propiedad IsMouseCaptured tiene un evento de cambio de propiedad IsMouseCapturedChanged. La propiedad es de solo lectura, con su valor ajustado por el sistema de entrada, y dicho sistema de entrada genera IsMouseCapturedChanged en cada cambio en tiempo real.

En comparación con un evento de cambio de propiedad auténtico, el uso de un desencadenador de propiedad para actuar sobre un cambio de propiedad tiene algunas limitaciones.

Los desencadenadores de propiedad funcionan mediante una lógica de coincidencia exacta. Especifica una propiedad y un valor que indica el valor específico por el que el desencadenador se activa. Por ejemplo: <Setter Property="IsMouseCaptured" Value="true"> ... </Setter>. Debido a esta limitación, la mayoría de los usos de desencadenadores de propiedad será para propiedades booleanas o propiedades que usan un valor de enumeración dedicado, donde el intervalo de valores posibles es lo bastante administrable para definir un desencadenador para cada caso. O bien pueden existir desencadenadores de propiedad solo para valores especiales, como cuando un recuento de elementos llega a cero, y no habría ningún desencadenador que reconociera los casos en los que vuelve a cambiar el valor de la propiedad en dirección contraria a cero de nuevo (en lugar de desencadenadores para todos los casos, es posible que necesite aquí un controlador de evento de código o un comportamiento predeterminado que vuelva a alternar el estado del desencadenador cuando el valor no sea cero).

La sintaxis del desencadenador de propiedad es análoga a una instrucción "if" en programación. Si se cumple la condición del desencadenador, el valor "body" del desencadenador de propiedad será "executed". El valor "body" de un desencadenador de propiedad no es código, sino marcado. Este marcado está limitado al uso de uno o más elementos Setter para establecer otras propiedades del objeto donde se aplica el estilo o la plantilla.

Para desplazar la condición "if" de un desencadenador de propiedad que presenta una amplia variedad de posibles valores, se suele recomendar establecer ese mismo valor de propiedad en un valor predeterminado mediante un elemento Setter. De este modo, el establecedor que contiene Trigger tendrá prioridad cuando la condición del desencadenador sea true y el elemento Setter que no esté dentro de Trigger tendrá prioridad siempre que la condición del desencadenador sea false.

Los desencadenadores de propiedad, por lo general, suelen ser adecuados para escenarios donde pueden cambiar una o varias propiedades de apariencia, en función del estado de otra propiedad del mismo elemento.

Para obtener más información acerca de los desencadenadores de propiedad, consulte Aplicar estilos y plantillas.

Vea también