How to correctly use databinding with ListView and CollectionView

In this post I’ll show how to properly use the MVVM (Model – View – ViewModel) design pattern in Xamarin Forms with ListView and CollectionView. In this context, Databinding is the technique to bind data sources to one or more UI components. In particular I want to show you how to use the databinding for the items in our ListView or CollectionView.

Let’s start with an example: We have a list of items and we want to show them in our page. Each item has an action so we need to correctly use the databinding to associate that action to our correct ViewModel. View have two options here and I’ll show you both, then you can decide which one you prefer.

Listview method 1

Let’s say that in our page we have a ListView that contains our items MyItems. For each item we want to show a name and a button to delete that item. Let’s start creating our ListView and the ViewCell:

<ListView x:Name="MyList" ItemsSource="{Binding MyItems}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <Label Text="{Binding Name}"/>
                    <Button Text="Delete"/>
                </StackLayout>
            </ViewCell>
       </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

As you can see, we have associated the Text of our ViewCell to the property Name of our item. It’s clear that the datacontext of Item is different from the datacontext of the ListView. The first is usually our Item, while the second is usually the ViewModel associated with that particular page. In the previous XAML, I haven’t created a command for the button yet. For what we have said, if I write:

<Button Text="Delete" Command="{Binding DeleteCommand}" CommandParameter="{Binding .}"/>

The delete command must be included in our Item model but this is fundamentally wrong! We should have that command in the ViewModel associated with that page, so DeleteCommand should be exactly where MyItems is. How to do it? We have two options.

Option number 1

In this case we use the Name of our ListView to use the correct DataContext. Our XAML will be:

<ListView x:Name="MyList" ItemsSource="{Binding MyItems}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <Label Text="{Binding Name}"/>
                    <Button Text="Delete" Command="{Binding Path=BindingContext.DeleteCommand, Source={x:Reference Name=MyList}}" CommandParameter="{Binding .}"/>
                </StackLayout>
            </ViewCell>
       </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

the syntax of our Command is a bit strange but we are basically saying “Take MyList and using its BindingContext, use the DeleteCommand“.

This works incredibly well, there are only two things you have to notice:

  • You must use a name for your List.
  • The name in the Source of your Command must obviously be the same as the name in your ListView.
  • You cannot have your ViewCell content in another xaml file.

If one of these points is a problem for you, then let’s have a look to the second option.

Option number 2

In this case we use the name of our ViewModel to find the correct Datacontext:

<ListView x:Name="MyList" ItemsSource="{Binding MyItems}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <Label Text="{Binding Name}"/>
                    <Button Text="Delete" Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MyViewModel}}, Path=DeleteCommand}" CommandParameter="{Binding .}"/>
                </StackLayout>
            </ViewCell>
       </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

Also in that case the syntax of our command is a bit strange but we are just saying: “You can find the command DeleteCommand looking inside the ViewModel MyViewModel“. The good news is that in this case Intellisense will help us to find the correct name for our ViewModel.

Using the option number 2, you can avoid to use the name of your ListView and you could save the code of your ViewCell in another XAML file.

CollectionView

I’ll quickly show the code for the option 2 with a CollectionView. As you can see, the only real difference (other than the name) is that in the DataTemplate we don’t have to use the Viewcell we had to use with the ListView.

<CollectionView x:Name="MyCollection" ItemsSource="{Binding MyItems}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <StackLayout Orientation="Horizontal">
                <Label Text="{Binding Name}"/>
                <Button Text="Delete" Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MyViewModel}}, Path=DeleteCommand}" CommandParameter="{Binding .}"/>
            </StackLayout>
       </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Conclusion

We have seen how to use properly and easily use databinding with ListView and CollectionView. If you have other questions or doubts, leave here a comment and I’ll try my best to give you the answer you are looking for.