No tenga miedo de MXML. Es genial para diseñar vistas. Si escribe sus propios componentes reutilizables, escribirlos en ActionScript a veces puede darle un poco más de control, pero para las vistas no reutilizables MXML es mucho mejor. Es más escueto, los enlaces son extremadamente fáciles de configurar, etc.
Sin embargo, los enlaces en ActionScript puro no tienen por qué ser tan molestos. Nunca será tan simple como en MXML donde se hacen muchas cosas por ti, pero se puede hacer sin demasiado esfuerzo.
Lo que tiene es BindingUtils
y sus métodos bindSetter
y bindProperty
. Casi siempre uso el primero, ya que generalmente quiero trabajar, o llamo al invalidateProperties
cuando cambian los valores, casi nunca me gusta establecer una propiedad.
Lo que necesita saber es que estos dos devuelven un objeto del tipo ChangeWatcher
, si desea eliminar el enlace por alguna razón, debe aferrarse a este objeto. Esto es lo que hace que los enlaces manuales en ActionScript sean un poco menos convenientes que los de MXML.
Vamos a empezar con un ejemplo sencillo:
BindingUtils.bindSetter(nameChanged, selectedEmployee, "name");
Esto establece una unión que se llamará al método nameChanged
cuando la propiedad name
en el objeto en la variable selectedEmployee
cambios. El método nameChanged
recibirá el nuevo valor de la propiedad name
como argumento, por lo que debe tener este aspecto:
private function nameChanged(newName : String) : void
El problema con este ejemplo simple es que una vez que haya configurado esta unión se disparará cada vez la propiedad del objeto especificado cambia. El valor de la variable selectedEmployee
puede cambiar, pero el enlace aún está configurado para el objeto al que apuntaba la variable.
Hay dos maneras de resolver este: ya sea para mantener el ChangeWatcher
devuelto por BindingUtils.bindSetter
alrededor y llame unwatch
en él cuando se quiere eliminar el enlace (y luego la creación de una nueva unión en su lugar), o se unen a ti mismo. Primero te mostraré la primera opción, y luego explicaré lo que quiero decir uniéndote a ti mismo.
El currentEmployee
se podría hacer en un par de captador/definidor e implementado como esto (sólo muestra el colocador):
public function set currentEmployee(employee : Employee) : void {
if (_currentEmployee != employee) {
if (_currentEmployee != null) {
currentEmployeeNameCW.unwatch();
}
_currentEmployee = employee;
if (_currentEmployee != null) {
currentEmployeeNameCW = BindingUtils.bindSetter(currentEmployeeNameChanged, _currentEmployee, "name");
}
}
}
Lo que sucede es que cuando la propiedad currentEmployee
se establece que mira para ver si había un valor anterior, y si es así, quita el enlace para ese objeto (currentEmployeeNameCW.unwatch()
), establece la variable privada y, a menos que el nuevo valor sea null
, establece un nuevo enlace para la propiedad name
. Lo más importante es que guarda el ChangeWatcher
devuelto por la llamada vinculante.
Este es un patrón de encuadernación básico y creo que funciona bien. Sin embargo, hay un truco que se puede usar para hacerlo un poco más simple. Usted puede unirse a usted mismo en su lugar. En lugar de configurar y eliminar enlaces cada vez que cambia la propiedad currentEmployee
, puede hacer que el sistema de enlace lo haga por usted. En su creationComplete
manejador (o constructor o por lo menos algún tiempo antes de tiempo) se puede establecer una unión de este modo:
BindingUtils.bindSetter(currentEmployeeNameChanged, this, ["currentEmployee", "name"]);
Esto establece una unión no sólo a la propiedad currentEmployee
en this
, sino también a la propiedad name
en este objeto. Por lo tanto, cada vez que se cambie el método se llamará al currentEmployeeNameChanged
. No es necesario guardar el ChangeWatcher
porque nunca será necesario eliminar el enlace.
La segunda solución funciona en muchos casos, pero he encontrado que la primera es a veces necesario, especialmente cuando se trabaja con los atascamientos en las clases no vista (ya que this
tiene que ser un despachador de eventos y la currentEmployee
tiene que ser enlazable para que funcione).
Excelente escritura. Esto fue muy útil. ¡Gracias! – airportyh
Excelente redacción de hecho. – Kevin
Escritura impresionante de hecho! Una pregunta rápida. ¿No sería un enfoque simple para la primera solución simplemente verificar si currentEmployeeNameCW es nulo? Si no es nulo, entonces existe una vinculación, así que llame a currentEmployeeNameCW.unwatch(). Parece una solución más generalizada y aún muy sucinta. – rinogo