Arena - Binding avanzado de propiedades

Requerimiento

Tenemos una aplicación que modela encuestas de votación para una zona determinada:

El usuario nos pide ahora que no se pueda votar a los candidatos del PRO (este es un ejemplo didáctico, claro está que no queremos ofender ninguna postura política). Esto implica inhabilitar el botón "Sumar voto", pero ¿cómo? ¿debemos interceptar la selección de un candidato?

Recordemos que según la visión de Arena podemos establecer un nuevo binding entre la propiedad enabled del botón y una propiedad del modelo que nos diga si se habilita la posibilidad de votar. Esto se debe definir en nuestro modelo de la vista, es decir la Encuesta:

Agregamos el binding en EncuestaWindow:

Pero... ¡no funciona!

Efectivamente, no importa qué candidato seleccionemos... el botón sigue habilitado.

Lo que pasa es que la propiedad "getHabilitaVotar()" es de solo lectura, se calcula en base al candidato... pero cuando el candidato cambia no se vuelve a calcular.

1. Una primera opción podría ser redefinir el setter de candidato y disparar una falsa notificación de que la propiedad "habilitaVotar" cambió. Así funcionaba en las primeras dos versiones de Arena.

2. Pero una forma más declarativa (sin buscar tanto control del algoritmo) es definir esa dependencia que habilitaVotar tiene respecto del candidato:

Entonces, la propiedad habiitaVotar se registra como nuevo interesado (observer) en los cambios de la propiedad candidato:

Agregar otra restricción

Ahora nuestro cliente nos pide que por el momento no habilitemos la posibilidad de votar para la zona Capital. Esto agrega una nueva dependencia: no permitimos que el botón se dispare

  • si el partido es x o y
  • si la zona es z

La propiedad @Dependencies admite más de una propiedad:

Las constantes están definidas al comienzo de la clase Encuesta:

Otro ejemplo de dependencia

Dejamos otro ejemplo de una propiedad calculada en base a otras 3 propiedades:

¿Qué me aporta diseñar el binding?

El binding se define en forma declarativa: no nos importa desde qué evento se está disparando, nos basta con entender cuál es la relación entre elemento gráfico y su modelo correspondiente. Esta decisión de diseño nos simplifica enormemente la construcción de la UI.