XAML

XAML e Binding : l’utilità della proprietà UpdateSourceTrigger

Supponiamo di voler effettuare il binding tra la proprietà Text di una TextBox della nostra UI ed una proprietà di tipo String definita nel ViewModel associato alla nostra pagina. Impostando la modalità di binding a TwoWay, ci rendiamo subito conto che il set della proprietà del ViewModel avviene solo ed esclusivamente quando il campo di testo perde il fuoco (quindi sul lost focus).

<TextBox x:Name="MyTextBox" Text="{Binding MyText, Mode=TwoWay}"/>

 

public string MyText
{
get { return this.myText; }
set
{
if (this.myText!= value)
{
this.myText= value;
this.OnPropertyChanged("MyText");
}
}
}

Talvolta questo non è il comportamento desiderato ed abbiamo la necessità che la nostra proprietà del ViewModel venga aggiornata ogni qual volta cambia il testo all’interno del campo.

La spiegazione di questo comportamento sta nel valore di default che la proprietàUpdateSourceTrigger del binding assume nel caso di una TextBox. LaUpdateSourceTrigger determina il momento in cui la sorgente del binding (binding source) viene aggiornata dalla destinazione del binding (binding target) nel caso di modalità two-way. Nel nostro caso il binding source è la proprietà del nostro ViewModel (ossia MyText) mentre il binding target è la proprietà Text della nostra TextBox (ricordiamo che è la proprietà di default del binding in una TextBox, ecco perchè non compare nella markup expression dell’esempio).

I possibili valori dell’enumerativo assegnabili alla UpdateSourceTrigger sono :

  • Default : il binding source è aggiornato quando il valore del binding target cambia;
  • Explicit : il binding source è aggiornato solo quando viene invocato in maniera esplicita il metodo BindingExpression.UpdateSource();

Per ogni controllo della UI il valore è tipicamente Default e nel caso della TextBox, in particolare, significa che il corrispondente binding source verrà aggiornato al lost focus.

Per cambiare il comportamento basta specificare nella markup expression di binding l’UpdateSourceTrigger ad Explicit.

<TextBox x:Name="MyTextBox"
         Text="{Binding MyText, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
         TextChanged="MyTextBox_TextChanged"/>

Come si evince dallo XAML è però necessario un ulteriore passo ossia quello di registrare l’evento di TextChanged della TextBox ed all’interno dell’event handler ricavere la binding expression per invocare su di essa l’esplicito aggiornamento del binding source.

private void MyTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    this.MyTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

Da codice, attraverso il metodo GetBindingExpression() sul controllo della UI è possibile ricavare l’espressione di binding per una specifica dependecy property (nel nostro caso la proprietà Text). Sull’espressione è poi possibile forzare l’aggiornamento del binding source attraverso il metodo UpdateSource().