XamarinXamarin.Forms

Xamarin.Forms Data Binding Context

Contents

In Xamarin applications, we sometimes see that the views move in a connected way or a UI element is updated dynamically. We can also do this in our own applications. How Does? Of course with Data Binding.

You can dynamically receive or send data from the user by binding a data or view to the view. For example, you can bind the data in a List to the ListView and then update this data through the ListView. Thus, you will develop an interactive application with the user. It is possible to do this with Data Bindings.

In this article, you will learn the basics of Data Binding, data flow and binding examples.

So let’s get started.

What is Data Binding?

Data Bindings bind between views and data in Xamarin applications. In other words, when changes occur in the data after the binding process, the views change. Or, when the appearance changes, the data can also change.

For instance,

  • Let’s say there is a slider and BoxView in the application. You can connect this slider with BoxView and change the opacity of BoxView when you slide the slider.
  • Or, you can connect an existing List in the ModelView class to the ListView and view the data in a list. You can even make changes to this data by running commands on the ListView.

Let’s examine the basic concepts of Data Bindings.

Data Binding Diagram
Data Binding Diagram

Data Bindings basically consist of four main components: target object, target property, binding source and path. And each bind contains these components.

Let’s assume that we connect the Students.Name property to the Text property of a Label. In this case, the target object is the Label, the target property is the Text property, the value used is Name, and the source is Student object.

Data Binding Modes

Binding doesn’t just have to be from the source to the destination. Binding can be target-to-source or two-ways, depending on how the application works. You can change the Binding.Mode according to whether you want the user to change the data in the application. Thus, you will provide a better user experience.

Data Binding Dataflow
Data Binding Dataflow

OneWay Binding

OneWay binding is updating the target property of changes in the source. But changes to the target don’t update the source. It is more convenient to use it for binding read-only data. If there is no change in the destination, it is necessary to connect OneWay instead of TwoWay. Thus, the application is less burdened.

TwoWay Binding

With TwoWay binding , it updates one variant on the source or target with another. TwoWay binding is more appropriate if the user editable view is to be binded to the resource. UI components such as CheckBox, RadioButton should be connected in this way.

OneWayToSource Binding

As the name suggests, the change in target is to update the source. OneWay is the opposite of tying.

OneTime Binding

It is appropriate to use in cases where the resource value does not change, ie if the data is static. OneTime binding allows the source to initialize the target. It does not reflect later changes on the target. This is a simple type of OneWay binding.

View To View Data Binding

In Xamarin.Forms apps, you can bind one view element to another view element. Thus, the change in one view affects the other. MVVM pattern is not used in view-to-view binding. So there is no need to create Model and ViewModel classes. Just connect View components together.

In the example I will show now, we will connect the BoxView and the slider and observe the changes. Also, we will bind a Label to the slider and change the Text property according to the value of the slider.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Blog.Views.BasicDataBindingPage">
    <ContentPage.Content>
        <StackLayout>
            <Grid  HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>

                <BoxView x:Name="boxview"
                         BackgroundColor="Gray"
                         HeightRequest="200"
                         HorizontalOptions="Center"
                         VerticalOptions="CenterAndExpand" />
                <Slider x:Name="opacitySlider"
                        Grid.Row="1" Grid.Column="0"
                        Maximum="1"
                        BindingContext="{x:Reference boxview}"
                        Value="{Binding Opacity, Mode=TwoWay}"
                        MaximumTrackColor="Gray"
                        MinimumTrackColor="Gray"/>
                <Label BindingContext="{x:Reference opacitySlider}"
                       Text="{Binding Value, StringFormat='Scale = {0:F1}'}"
                       Grid.Row="1" Grid.Column="1"
                       VerticalTextAlignment="Center"/>
                <Slider x:Name="rotationSlider"
                        Grid.Row="2" Grid.Column="0"
                        Maximum="360"
                        BindingContext="{x:Reference boxview}"
                        Value="{Binding Rotation, Mode=OneWayToSource}"
                        MaximumTrackColor="Gray"
                        MinimumTrackColor="Gray"/>
                <Label BindingContext="{x:Reference rotationSlider}"
                       Text="{Binding Value, StringFormat='Rotation = {0:F0}'}"
                       Grid.Row="2" Grid.Column="1"
                       VerticalTextAlignment="Center"
 />
            </Grid>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Here I binded BoxView’s x:Name value to Slider’s BindingContex value with x:Reference. I also binded the Slider’s Value property to the BoxView’s opacity. At the Label, I connected the Slider with x:Reference and print the value of the Text property with the StringFormat.

The binding mode of the Slider view named opacitySlider is TwoWay. Because I wanted the value of the Opacity property to be set to 1 instead of 0. If the mode was set to OneWayToSource rather than TwoWay, the Opacity value would initially be 0. So BoxView wouldn’t appear.

The screen output is as follows:

View To View Data Binding
View To View Data Binding

Data Binding to ListView with ObservableCollection

In the previous example, I binded one view to another view. Now I will show how to connect a ObservableCollection defined in ViewModel class to ListView. Binding data to the ListView will help you understand the Data Bindings topic better. You will often see the ListView structure in many applications anyway.

In this example I will bind a ObservableCollection holding student information to the view. I need a Model and ViewModel class. Thus, I will apply the MVVM pattern to the project. Since the layers of the projects developed with the MVVM pattern are developed separately from each other, it fully applies the Seperation of Concers principle. That’s why you can see the MVVM architecture in many Xamarin.Forms projects.

First add a Model folder to the project. Then create a class within this folder called Student. Create Number, Name, Surname variables in this class.

    public class Student
    {
        public int Number { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
    }

Now add a folder named ViewModel to the project and create a class named StudentViewModel in this folder. In the MVVM pattern, ViewModel provides the bind between View and Model. In this class, create an ObservableCollection collection where data is processed as follows.

    public class StudentViewModel
    {
        private ObservableCollection<Student> studentList;
        public ObservableCollection<Student> StudentList
        {
            get { return studentList; }
            set
            {
                studentList = value;
            }
        }
        public StudentViewModel()
        {
            StudentList=GetStudents();
        }
        private ObservableCollection<Student> GetStudents()
        {
            return new ObservableCollection<Student>
            {
                new Student{Number=1, Name="Alex",Surname="Doe"},
                new Student{Number=2, Name="Susan",Surname="Cox"},
                new Student{Number=3, Name="Natalia",Surname="Weston"},
                new Student{Number=4, Name="David",Surname="Hahn"}
            };
        }
    }

Finally, add a folder named View to the project and create a ContentPage named StudentPage within that folder. Then declare ContenPage’s BindingContext as below.

    <ContentPage.BindingContext>
        <bc:StudentViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <ListView ItemsSource="{Binding StudentList}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout Orientation="Horizontal">
                                <Label Text="{Binding Number}" FontSize="20" FontAttributes="Bold" TextColor="Gray" />
                                <Label Text="{Binding Name}" FontSize="20" />
                                <Label Text="{Binding Surname}" FontSize="20" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Here I binded StudentList’s to ListView’s ItemSource property. Thus, I declare that the source of ListView is the ObservableCollection collection named StudentList of the ViewModel class. In addition, I make the Text properties of the Labels in the ViewCell appear in the ListView by binding the StudentList’s properties.

Our screen output will look like this:

Data Binding to ListView with ObservableCollection
Data Binding to ListView with ObservableCollection

Data Binding Command

In Xamarin.Forms applications, we want to interact with view components such as button, ImageView. It is possible to interact with the Clicked handler of views on the code side of the XAML file. However, since there is no Clicked handler in the MVVM model, interactions are provided with the Command interface.

I want to interact with my StudentList example above through the Command interface and delete the last element in the list. For this, first inherit the ViewModel class from the INotifyPropertyChanged interface. Then implement this interface.

   public class StudentViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        private ObservableCollection<Student> studentList;
        public ObservableCollection<Student> StudentList
        {
            get { return studentList; }
            set
            {
                studentList = value;
                OnPropertyChanged("Student");
            }
        }
        public StudentViewModel()
        {
            StudentList = GetStudents();
        }
        private ObservableCollection<Student> GetStudents()
        {
            return new ObservableCollection<Student>
            {
                new Student{Number=1, Name="Alex",Surname="Doe"},
                new Student{Number=2, Name="Susan",Surname="Cox"},
                new Student{Number=3, Name="Natalia",Surname="Weston"},
                new Student{Number=4, Name="David",Surname="Hahn"}
            };
        }
        public ICommand DeleteCommand => new Command(Delete);
        private async void Delete()
        {
            StudentList.RemoveAt(StudentList.Count-1);
        }
    }

With the OnPropertyChanged (“Student”) method, I notify the view when there is a change in StudentList. Thus, when an element is deleted, the ListView component is updated.

Also notice how I use Command. I use the ICommand interface to add a command to the ViewModel and define the command method as above. Now let’s see how I binded this command to View.

    <ContentPage.BindingContext>
        <bc:StudentViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <ListView ItemsSource="{Binding StudentList}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout Orientation="Horizontal">
                                <Label Text="{Binding Number}" FontSize="20" FontAttributes="Bold" TextColor="Gray" />
                                <Label Text="{Binding Name}" FontSize="20" />
                                <Label Text="{Binding Surname}" FontSize="20" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <Button Text="DELETE LAST ITEM" Command="{Binding DeleteCommand}"/>
        </StackLayout>
    </ContentPage.Content>

I added a Button after ListView and connected the Command property with DeleteCommand in ViewModel. That is all. Now, every time we click the button, the last element of StudentList will be deleted and the ListView will be updated.

Our screen output will look like this:

Data Binding Command
Data Binding Command

Conclusion

To sum up, Data Bindings binds source and target objects. In Xamarin.Forms applications, we use it to bind views or to bind views to ViewModel. When an application interacts with the user, it offers a better experience.

In this article, I explained Data Contexts, binding modes, connecting View and ViewModel, and Command with examples. And also, to better understand this topic, you should understand the MVVM pattern well. I hope it was useful.

If you’re still not sure what to do, or if you got any errors, then I suggest you use the comment section below and let me know! I am here to help!

Also, share this blog post on social media and help more people learn.

Related Links

Serkan

Software Engineer. Problem solver. Music practitioner. Thinker. Industrious.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button