Jelboen
Jelboen

Reputation: 39

Xamarin Forms Picker Binding to Label Binding

I managed to Bind a Picker to the values in a list I needed. On the same page as the picker I want a Label to display what I picked from the picker. I have a Display text in the picker, And an "id", which is a single char.

Here is the XAML:

<Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Source={x:Reference AVPUPicker}, Path=SelectedItem}" FontAttributes="Bold" FontSize="10" TextColor="LightBlue" Padding="0,0,0,0"/>
            <Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Source={x:Reference AVPUPicker}, Path=ItemDisplayBinding}" FontAttributes="Bold" FontSize="16" TextColor="LightBlue" Padding="0,0,0,0"/>
            <Picker x:Name="AVPUPicker" Title="Vælg tilstand" SelectedItem="{Binding KarakterId}" ItemDisplayBinding="{Binding ForklarendeTekst}" ItemsSource="{Binding AVPUListe}" IsVisible="True"/>

Data binding on the Picker is working as intended. I have tested both "KarakterId" and "ForklarendeTekst", and it does show the right values when Picker is activated. So data seems to be loaded in the picker. I'm using x:Reference, Path to get to the property on the picker. However this is where it fails. I do get an output for the two X:Ref bindings in the label:

EWSMonitor.Models.AVPU 

Xamarin.Forms.Binding 

If I removed the binding on SelectedItem property, And manually type in some text value, the binding on the Label works. So the Picker works, And the the reference to the property seem to work, when manually typing something in, but when bounded, it breaks. What do I miss?

Update:

I think I'm missing the INotifyOnChange part on my List. But how can I accomplish that? I'm creating the list in my ViewModel: public IList<AVPU> AVPUListe { get; } which references to the class AVPU I have created in my Model folder:

public class AVPU
    {
        public char KarakterId { get; set; }
        public string ForklarendeTekst { get; set; }

}

I then add my selections to the AVPUListe:

AVPUListe = new ObservableCollection<AVPU>();
            AVPUListe.Add(new AVPU { KarakterId = 'A', ForklarendeTekst = "Alert - Vågen" });
            AVPUListe.Add(new AVPU { KarakterId = 'V', ForklarendeTekst = "Verbal - Tiltale" });
            AVPUListe.Add(new AVPU { KarakterId = 'P', ForklarendeTekst = "Pain - Smertestimuli" });
            AVPUListe.Add(new AVPU { KarakterId = 'U', ForklarendeTekst = "Unresponsive - Ukontaktbar" });

Upvotes: 1

Views: 876

Answers (2)

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10346

As jason's reply, you need to binding Picker's SelectedItem by ViewModel, I do one simple sample that you can take a look:

 <Label
            Padding="0,0,0,0"
            FontAttributes="Bold"
            FontSize="10"
            HorizontalTextAlignment="Center"
            Text="{Binding Source={x:Reference AVPUPicker}, Path=SelectedItem.KarakterId}"
            TextColor="LightBlue"
            VerticalTextAlignment="Center" />
        <Label
            Padding="0,0,0,0"
            FontAttributes="Bold"
            FontSize="16"
            HorizontalTextAlignment="Center"
            Text="{Binding Source={x:Reference AVPUPicker}, Path=SelectedItem.ForklarendeTekst}"
            TextColor="LightBlue"
            VerticalTextAlignment="Center" />
        <Picker
            x:Name="AVPUPicker"
            Title="Vælg tilstand"
            IsVisible="True"
            ItemDisplayBinding="{Binding ForklarendeTekst}"
            ItemsSource="{Binding AVPUListe}"
            SelectedItem="{Binding selecteditem}" />

SelectedItem need to implement INotifyPropertyChanged to notify data change when you change picker selected index.

 public class avpuviewmodel:ViewModelBase
{
    public ObservableCollection<AVPU> AVPUListe { get; set; }
    private AVPU _selecteditem;
    public AVPU selecteditem
    {
        get { return _selecteditem; }
        set
        {
            _selecteditem = value;
            RaisePropertyChanged("selecteditem");
        }
    }
    public avpuviewmodel()
    {
            AVPUListe = new ObservableCollection<AVPU>();
            AVPUListe.Add(new AVPU { KarakterId = 'A', ForklarendeTekst = "Alert - Vågen" });
            AVPUListe.Add(new AVPU { KarakterId = 'V', ForklarendeTekst = "Verbal - Tiltale" });
            AVPUListe.Add(new AVPU { KarakterId = 'P', ForklarendeTekst = "Pain - Smertestimuli" });
            AVPUListe.Add(new AVPU { KarakterId = 'U', ForklarendeTekst = "Unresponsive - Ukontaktbar" });
        selecteditem = AVPUListe[0];          
    }
}
public class AVPU
{
    public char KarakterId { get; set; }
    public string ForklarendeTekst { get; set; }

}

 public class ViewModelBase : INotifyPropertyChanged
{   
    public event PropertyChangedEventHandler PropertyChanged;       
    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Finally, binding viewmodel to current contentpage.

 public partial class Page3 : ContentPage
{
    public Page3()
    {
        InitializeComponent();
        this.BindingContext = new avpuviewmodel();
    }          
}

enter image description here

Upvotes: 1

Jason
Jason

Reputation: 89082

your VM needs to have a property to bind to SelectedItem

ObservableCollection<AVPU> AVPUListe { get; set; }

AVPU Selected { get; set; }

then your Picker would be

<Picker SelectedItem="{Binding Selected}" ... />

and your Label

<Label Text="{Binding Selected.ForklarendeTekst" ... />

Upvotes: 1

Related Questions