XAM270 Data Binding in Xamarin.Forms

Exercise 2: Keeping the UI and data in sync using bindings (XAM270)

In this exercise you'll implement two-way binding for your UI; this will ensure UI data changes are sent to the code-behind. You'll then implement INotifyPropertyChanged to ensure that the UI is updated when the underlying data is changed.

To complete the exercise, you will need Visual Studio for Windows or macOS with the Xamarin development tools installed. You will also need either an emulator/simulator or a device to run the exercise on. Please see the setup page if you need help installing the Xamarin development environment.

Open the starter solution

This exercise is a continuation of the previous exercise. You can use your existing solution or begin from the prior Exercise 1 > Completed solution in your copy of the cloned or downloaded course materials.


Add support for two-way bindings

Not all properties default to two-way binding so you'll set the binding mode explicitly.

  1. Open the MainPage.xaml markup file and on each {Binding} you created earlier, set the Mode to be "TwoWay". Remember you won't use quotes in the markup extension properties!
<Picker x:Name="country" SelectedItem="{Binding Country, Mode=TwoWay}" />

<Label Text="Current Design was Adopted on" FontAttributes="Bold" />
<DatePicker x:Name="adopted" MinimumDate="01/01/1700" HorizontalOptions="Start" 
            Date="{Binding DateAdopted, Mode=TwoWay}" />

<Label Text="Has Shield" FontAttributes="Bold" />
<Switch x:Name="hasShield" IsToggled="{Binding IncludesShield, Mode=TwoWay}" />

<Label Text="Fun Fact" FontAttributes="Bold" />
<Label x:Name="description" Text="{Binding Description}" />

Add support for property change notifications

In this part, you'll see why you need INotifyPropertyChanged, and then implement it on our Flag object.

  1. Open the MainPage.xaml.cs code behind file and locate the OnShow method.
  2. You want to modify your Flag object in some way that is independent of the UI.

    Add a year to the Flag.DateAdopted property by calling .AddYears(1) and assigning the returning value back to the DateAdopted property. Note: you must assign the property since DateTime is immutable.

    private async void OnShow(object sender, EventArgs e)
    {
        CurrentFlag.DateAdopted = CurrentFlag.DateAdopted.AddYears(1);
    
        await DisplayAlert(CurrentFlag.Country,
            $"{CurrentFlag.DateAdopted:D} - {CurrentFlag.IncludesShield}: {CurrentFlag.MoreInformationUrl}",
            "OK");
    }
    
  3. Run the application and note the current date displayed. Press the Show button in the tool bar. It should display the flag details but the year should be incremented in the alert dialog. Make note of the year displayed.
  4. Dismiss the alert dialog and notice that the UI is still displaying the original year even though the data is changing in the underlying model.

    The problem is that Xamarin.Forms is unaware of the property being changed - to make it aware, you need to implement the INotifyPropertyChanged interface on the Flag class.
  5. Open Flag.cs in the FlagData project.
  6. Modify the Flag class to implement System.ComponentModel.INotifyPropertyChanged. The implementation requires a single event named PropertyChanged.

    If you add the interface definition to the class, you can place your cursor on it and use ALT+ENTER (Windows) or CMD+ENTER (macOS) to get Visual Studio to provide a dummy implementation for you.
    public class Flag : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        ...
    }
    
  7. You'll create a helper-method to raise the PropertyChanged event named RaisePropertyChanged. The method will accept a string parameter which is the text name of the property that has changed.

    • .NET 4.5 includes an attribute CallerMemberNameAttribute in the System.Runtime.CompilerServices namespace which you can use to get the compiler to identify the property that has been changed. Check the code below for an example. Alternatively, you can have the caller pass the name using the C# nameof() compiler feature.
    • Make sure to test the event for null before raising it. You can either use the built-in C# null check support, or for earlier versions of C#, test the event for null, or assign the event to an empty delegate (this is called the null pattern).
    using System.Runtime.CompilerServices;
    ...
    public class Flag : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        ...
        private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    
  8. You'll change the DateAdopted property first but you should perform these steps for every property which could be changed independent of the UI.
  9. Change the existing DateAdopted auto-property into a field-backed property and when it is changed, call the new RaisePropertyChanged method to notify the UI.

    Hints:

    • Make sure to compare the two values - it's inefficient to raise a property change notification if the value has not changed.
    • Assign the new value.
    • Raise the property change notification using your new method.
    private DateTime _dateAdopted;
    ...
    public DateTime DateAdopted
    {
        get { return _dateAdopted; }
        set
        {
            if (_dateAdopted != value)
            {
                _dateAdopted = value;
                // Can pass the property name as a string,
                // -or- let the compiler do it because of the
                // CallerMemberNameAttribute on the RaisePropertyChanged method.
                RaisePropertyChanged();
            }
        }
    }
    
  10. Run the application, scroll down to the Current Design was Adopted On DatePicker and tab the Show button - you should see the date changing when it's changed in the underlying Flag object. You can fix the other properties if you like - you aren't changing any of them, but they would all need to raise the PropertyChanged notification to properly notify the UI in a production application. The completed project included with the lab materials will take this extra step.

    • It can be helpful to create a method which does the field comparison and assignment so you only have to call that method in each property setter. Check the completed project for an example.
  11. You can also remove the x:Name attributes off all the XAML objects you are now binding - this removes the private field mapped to the control and reduces the Intellisense "clutter" with unused objects.

Exercise summary

In this exercise, you have taken an existing Xamarin.Forms application and modified it to use Data Binding to populate the UI. You have successfully added two-way binding and implemented the INotifyPropertyChanged interface on your model object.

You can view the completed solution in the Exercise 2 > Completed folder of your copy of the cloned or downloaded course materials.

Go Back