Sorpresa: el orden sí importa (de los binding del ComboBox)

Nunca había imaginado que el orden de las propiedades de un elemento XAML importara. De hecho siempre las he puesto en el orden que me es más fácil de leer, por ejemplo agrupando las propiedades de diseño, las de datos, las attached… Pero hoy he descubierto que algo puede suceder (algo malo, claro) dependiendo del orden cuando trabajamos en un ComboBox. El ejemplo:

<ComboBox DockPanel.Dock="Top"
          ItemsSource="{Binding Clientes}"
          SelectedItem="{Binding Cobro.Cliente, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/>

Siguiendo un orden lógico, enlazo primero ItemsSource para rellenar el Combo, y después SelectedItem para indicar cual de los elementos está seleccionado. Aunque nunca he visto esto como algo imperativo (aunque lo describa así) y de hecho en muchas ocasiones no respeto este orden, al considerarlo una declaración. Pero como titulo, el orden sí importa, y la consecuencia es: a veces la propiedad Cobro.Cliente puede establecerse a null por accidente. ¿Cómo? Intento mostrarlo paso a paso:

  • Al asignar el DataContext que afecta a este combo, no hay problema y los datos se cargan bien: el contenido del combo y el elemento seleccionado.
  • Si después cambio ese DataContext (o en mi caso lo elimino, asignando null para que deje de actuar el binding, antes de ocultar los elementos), ese cambio se propaga a los binding que contiene en orden: primero se aplica al ItemsSource, y después al SelectedItem.

Consecuencia: en un momento dado, ItemsSource pierde su origen, estableciéndose a null, por lo que el ComboBox automáticamente pone SelectedItem a null… pero SelectedItem sigue enlazado con el DataContext original, por lo que pone la propiedad correspondiente (Cobro.Cliente en mi caso) a null. Después se termina de propagar el nuevo DataContext a null, pero nada nuevo pasa, el daño ya está hecho.

Tenemos más información de este comportamiento en el foro de msdn, donde evidentemente indican la obvia solución: invertir las propiedades en XAML, así:

<ComboBox DockPanel.Dock="Top"
          SelectedItem="{Binding Cobro.Cliente, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
          ItemsSource="{Binding Clientes}"/>

Esto soluciona el problema en mi caso.

Supongo que es un problema de diseño de difícil solución, pero para mí ha sido una desagradable sorpresa, ya que en XAML trabajamos siempre a un alto nivel de abstracción, casi de forma declarativa, y tener que preocuparnos por cosas como estas (donde es fácil confundirse y difícil detectar la causa de que una propiedad se te borre/cambie sola) es una pequeña desilusión. Con lo que me gusta a mí abstraerme…

Anuncios
Esta entrada fue publicada en Binding, WPF, XAML. Guarda el enlace permanente.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s