Databound Pickers are in much demand, and fortunately Karl Shifflett has created one that is excellent and easy to use. You add it to your program, wire up the data-binding and hey! presto! you’re in business.
The tricky bit comes when you want to put it in a ListView and bind to its contents while still being able to bind to other properties of your objects.
Here’s an example based on a program I wrote recently (the names have been changed to protect the guilty)…
Let’s start with our Model.
We have two classes that I’ve stripped down to the essentials. First is a Person class,
using System;
namespace BindablePicker
{
public class Person
{
public string Name { get; set; }
}
}
I also need to know how many Person objects I have, and since I don’t own the model for Person (it is from an API) I decide to create a PersonHolder class…
namespace BindablePicker
{
public class PersonHolder
{
public Person Person { get; set; }
public int Quantity { get; set; }
}
}
Let’s jump to the View Model. The first thing I need to do is to create a collection of Person Holders, and populate it,
public class PersonDisplayViewModel : INotifyPropertyChanged
{
public ObservableCollection<PersonHolder> PersonHolders { get; set; } =
new ObservableCollection<PersonHolder> ();
PersonHolder personHolder = new PersonHolder ();
personHolder.Person = new Person () { Name = "Jesse" };
PersonHolders.Add (personHolder);
personHolder = new PersonHolder ();
personHolder.Person = new Person () { Name = "Karl" };
PersonHolders.Add (personHolder);
}
Next, we’ll create an ObservableCollection for the values we want in the picker. Remember, this is a databound picker so we can assign the values dynamically, while the program is running. And we can change them in response to, e.g., events.
Let’s initialize the values in the constructor,
private ObservableCollection<string> pickerItems; public ObservableCollection<string> PickerItems { get { return pickerItems; } set { pickerItems = value; RaisePropertyChanged (); } } public PersonDisplayViewModel () { PickerItems = new ObservableCollection<string> (); for (int i = 0; i <= 4; i++) { this.PickerItems.Add (i.ToString ()); }
Now comes the fun part, writing the XAML. The key aspect of the XAML is the ListView. We begin in the traditional way, making sure to give the ListView a name,
<ListView
x:Name=“PersonList“
ItemsSource=“{Binding PersonHolders}“>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView>
<StackLayout
Orientation=“Horizontal“>
<Label
Text=“{Binding Person.Name}“
FontSize=“14“
VerticalTextAlignment=“Center“ />
So far, no problem. But we want to get the bound value for the picker and that is the entire issue that this post is about. We do not want to bind the Picker to the PersonHolders, but how do we gain access to the values we do want to bind to.
The answer is to change the BindingContext to the ListView itself. This sets up the correct relationship with the data,
ItemsSource="{Binding Path=BindingContext.PickerItems,
Source={x:Reference PersonList} }"
SelectedItem="{Binding Quantity, Mode=TwoWay}" />
That’s it. Here’s the complete XAML:
<?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:BindablePicker;assembly=BindablePicker" x:Class="BindablePicker.PersonDisplay"> <ContentPage.Content> <StackLayout Margin="50"> <ListView x:Name="PersonList" ItemsSource="{Binding PersonHolders}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <ContentView> <StackLayout Orientation="Horizontal"> <Label Text="{Binding Person.Name}" FontSize="14" VerticalTextAlignment="Center" /> <local:BindablePicker ItemsSource="{Binding Path=BindingContext.PickerItems, Source={x:Reference PersonList} }" SelectedItem="{Binding Quantity, Mode=TwoWay}" /> </StackLayout> </ContentView> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> </ContentPage>
Endless thanks to Karl for his invaluable assistance with getting this to work.
Hi,
I tried it but always When i build my xamarin.forms app. it gives error ; Value cannot be null
Why do you think ? Pls help
Hello thanks for example ,
Can you wprovide me working example, i have tried your code , there is nothing in screen , may be something i am missing something so, it would great if you provide me
Hello thanks for example ,
Can you wprovide me working example, i have tried your code , there is nothing in screen , may be something i am missing ?