1
votes

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" });
2
You should bind your Label to the same property of your VM that SelectedItem is bound to, not directly to the Picker - Jason
I have updated my question with new information. I think I'm missing to implement INotifyPropertyChanged on this one, but I have no idea if it is the AVPUListe that needs to be handled or if it is the char and string from the AVPU class? - Jelboen
SelectedItem needs to be a property on your VM of type AVPU - Jason
I think I do get that, but how is that possible? new AVPU signals that it comes from a new class, that I can't seem to reach in the ViewModel. Is it possible to create the list another way that is reachable through binding? Or maybe it's just me that doesn't get how to reach it. Other bindings works just fine. - Jelboen

2 Answers

0
votes

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

1
votes

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" ... />