Data Binding
Data Binding 101
Data binding connects two objects, called thesource_and the_target. The_source_object provides the data. The_target_object, which must be a bindable property, will consume (and often display) data from the source object. For example, a Label(_target_object) will commonly bind its Text property to a public string property in a source object. The following diagram illustrates the binding relationship:
The main benefit of data binding is that you no longer have to worry about synchronizing data between your views and data source. Changes in the source object are automatically pushed to the target object behind-the-scenes by the binding framework, and changes in the target object can be optionally pushed back to the source object.
Establishing data binding is a two step process:
The BindingContext property of the target object must be set to the source.
A binding must be established between the target and the source. In XAML, this is achieved by using the Binding markup extension.
The following code, taken from the accompanying sample, shows an example of performing data binding in XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="DataBinding101.HomePage">
<StackLayout Padding="0,20,0,0">
<Label Text="Data Binding 101 Demo" FontAttributes="Bold" HorizontalOptions="Center" />
<Label Text="Forename:" />
<Entry Text="{Binding Forename, Mode=TwoWay}" />
<Label Text="Surname:" />
<Entry Text="{Binding Surname, Mode=TwoWay}" />
<StackLayout Padding="0,20,0,0" Orientation="Horizontal">
<Label Text="Your forename is:" />
<Label Text="{Binding Forename}" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Your surname is:" />
<Label Text="{Binding Surname}" />
</StackLayout>
</StackLayout>
</ContentPage>
Although the BindingContext property of the HomePage class (the target object) can be set in XAML, here it’s set in code-behind to DetailsViewModel (the source object):
public partial class HomePage : ContentPage
{
public HomePage ()
{
InitializeComponent ();
BindingContext = new DetailsViewModel ();
}
}
While the BindingContext property of each target object can be individually set, this isn’t necessary. BindingContext is a special property that’s inherited by all its children. Therefore, when the BindingContext on the ContentPage is set to DetailsViewModel, all of the children of the ContentPage have the same BindingContext, and can bind to public properties of DetailsViewModel
Property Change Notification
By default, the target object only receives the value of the source object when the binding is created. To keep the UI synchronized with the data source, we need a way to notify the target object when the source object has changed. This mechanism is provided by theINotifyPropertyChanged
interface. Implementing this interface will provide notifications to any data-bound controls when the underlying property value changes. The following code example shows the sourceDetailsViewModel
class, which is data bound from XAML, and how it implements theINotifyPropertyChanged
interface:
public class DetailsViewModel : INotifyPropertyChanged
{
string forename, surname;
public string Forename {
get {
return forename;
}
set {
if (forename != value) {
forename = value;
OnPropertyChanged ("Forename");
}
}
}
public string Surname {
get {
return surname;
}
set {
if (surname != value) {
surname = value;
OnPropertyChanged ("Surname");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged (string propertyName)
{
var changed = PropertyChanged;
if (changed != null) {
PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
}
}
}
The class fires a PropertyChanged event whenever the Forename or Surname properties change. Therefore, in the sample application, as the user enters their name, it’s simultaneously displayed by the two Label instances.