Writing code that sets the properties of user interface controls to the required data is a tried-and-tested technique for wiring a user interface (UI) to a data source, but can result in having to write lengthy and repetitive code to ensure that the UI is correctly synchronized.
Writing code to wire a user interface to a data source doesn’t have to feel like the dark ages! In this blog post, I’m going to detail an alternative to manually connecting a UI to its data source. Data binding is a technique to automatically synchronize a user interface with its data source and can vastly simplify how your app displays and interacts with data.
Data Binding 101
Data binding connects two objects, called the source 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
. For information about setting the BindingContext
 in XAML, see From Data Bindings to MVVM.
The Binding
markup extension can specify several properties, including Path
and Mode
. The Path
property is used to specify the property name of the source object to use for the binding. However, this property name can be omitted provided that it’s the first item in the Binding
markup extension.
The Mode
property is used to specify the direction in which property value changes will propagate:
- A
OneWay
binding propagates changes from the source to the target. - A
TwoWay
binding propagates changes in both directions, ensuring that the source and target objects are always synchronized. - A
OneWayToSource
binding propagates changes from the target to the source, and is mainly used for read-only bindable properties.
In Xamarin.Forms, the Mode
property defaults to OneWay
, and can be omitted unless a different BindingMode
is required.
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 the INotifyPropertyChanged
interface. Implementing this interface will provide notifications to any data-bound controls when the underlying property value changes. The following code example shows the source DetailsViewModel
class, which is data bound from XAML, and how it implements the INotifyPropertyChanged
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, as shown in the following screenshots:
Note that as a best practice to avoid unnecessary events being fired, the PropertyChanged
event isn’t raised if the property value does not change.
Wrapping Up
Data binding is used to synchronize a UI with its data source, and simplifies how a Xamarin.Forms application displays and interacts with its data. Provided that the source object implements the INotifyPropertyChanged
interface, changes in the source object are automatically pushed to the target object by the binding framework, and changes in the target object can be optionally pushed to the source object.
For more information about data binding, see Data Binding Basics. For more information about the INotifyPropertyChanged interface, see From Data Bindings to MVVM. Xamarin University also provides a class on data binding in Xamarin.Forms. Ready to take your data binding skills to the next level? Check out the next post in our data binding series, where you will learn advanced techniques like control-to-control bindings and converters.
0 comments