Skip to main content

Databinding Scope in Xamarin.Forms

·5 mins

A question I have seen coming by a lot is: how to trigger a command from the ContextAction on an item in the ListView. While it seems straight-forward, implementation can be a bit tricky. This has everything to do with the databinding scope. This post will give you some background and show you how it’s done.

If you’re more interested in a video walkthrough; I’ve got you covered. The same will be explained here in this post. For more content, please feel free to subscribe to my YouTube channel and/or Twitch.

Outlining the Case #

I think the most obvious example case is the one I started this post with. In your app there is a ListView with items. As context actions on those items you have a delete action, but the delete Command doesn’t trigger. A screenshot of this scenario implemented on iOS can be seen underneath.

Screenshot of sample app with a ListView and a context action

Sample app with ListView and context action open on iOS

The Problem with Databinding Scope #

While I say “problem”, it is not really a problem, it’s just the way things work. However, I can see why it is a bit confusing. What happens is that your page view model is bound to the complete page, which probably has a collection of items that is shown in the ListView. However, whenever we look at a single item in the ListView, the scope suddenly shifts to the object bound to that one cell. It can be hard to explain in words, I’ve tried to capture it in an image which you see below. It will probably become more clearer when we see some code.

Schematic overview of the scopes in screenshot

Same screenshot as above with schematic overview of scopes

Solution #

So how do we go about this? Let me tell you the code for this is to be found here: https://github.com/jfversluis/DataBindingScopeSample.

First let’s have a look at my backing code. The first class ListModel is the class that represents one item in our collection. That means one item in our ListView. The MainPageViewModel class is the view model that is behind our whole page. In this class we have our collection that the ListView will show. Also notice it has a command to delete an item from this list.

Now, let’s have a look at the ListView I have in place. You can see the ItemsSource of the ListView is pointing to the MyItems property in MainPageViewModel.

You can already see where I’m going with this because of the comments. Because we point our ListView to the MyItems, that will mean each cell will be an instance of the ListModel object. That also means, that if we implement a context action as you can see in the first comment block, the {Binding DeleteCommand} will start looking for the DeleteCommand in the ListModel item. But we want our context action to look in the MainPageViewModel for this command.

It does not make any sense to add a delete command in each item. An item will not know if it’s part of a collection, let alone what code it needs to trigger to be deleted. We really want the delete command in the page view model and call upon that.

Point the Databinding Scope in the Right Direction #

To make our databinding scope work correctly, what we need to do is just point the binding in the right direction. Notice how I added the x:Name="ListOfPeople" on the ListView. Now look at the uncommented block of the MenuItem. You will notice how the binding tag will now specify a path, pointing to the BindingContext.DeleteCommand. Before I will explain this, notice how I now also specify the source. And that source is pointing to the name of the ListView.

By implementing the binding like this, we point back to the ListView and from there we reach into the BindingContext property first. Within that object currently assigned to the BindingContext, we go into the DeleteCommand. In our sample that means, we go to the BindingContext of the ListView, which is the MainPageViewModel and in the MainPageViewModel we point to the DeleteCommand.

Now read all that again three times and you might start to get it ;)

Databinding Scope with RelativeSource #

Since Xamarin.Forms 4.3 there is also the RelativeSource binding which will make this a bit easier. You can see that in the third comment block in the code above.

I don’t want to overload you with more information right now, but be sure to check it out on the docs or read this great blog by my good friend Javier.

In Closing #

I hope this post will make a bit clear how the scoping works. It’s kind of tough to explain, you probably need to play with it for a little to fully click. This example uses a ListView, but this also applies to CollectionView or CarouselView or any other control with a similar concept. Just try to analyze if you might be looking at an instance of one item as opposed to your page’s view model.

If you want to read a little bit more and see some real-life cases, check these StackOverflow answers. Here is one, two and three.

Once again, the code can be found on my GitHub: https://github.com/jfversluis/DataBindingScopeSample. If there are any questions or concerns, please let me know!