How to binding multiple labels at the same object

BrunoBarcellosBrunoBarcellos USMember
edited November 2016 in Xamarin.Forms

As simple as the title says, I want to bind one object to a couple of labels. Something like:
Xaml :
<StackLayout x:Name="person_xaml"> <Label Text="{Binding name}" /> <Label Text="{Binding age}" /> <Label Text="{Binding height}" /> <Label Text="{Binding weight}" /> ... </StackLayout>
Cs :
Person p = new Person(); person_xaml.BindingContext = p; //or person_xaml.ItemsSource
then I'd need just to handle p, just like it would work with a ListView using ItemsSource
Thanks

Tagged:

Answers

  • StefaanAvonds.3725StefaanAvonds.3725 USMember ✭✭✭

    @BrunoBarcellos

    I'm doing something familiar in an application of mine. What I do is set the BindingContext of the page to my ViewModel and in there I have a public class. In XAML the only thing I need to do is:
    <Label Text={Binding Detail.Name}" />

    So your XAML would look like this:

    And your CS:
    public class MyPage : ContentPage, INotifyPropertyChanged
    {
    private Person _myPerson;

                public Person MyPerson
                {
                    get { return _myPerson; }
                    set
                    {
                        _myPerson = value;
                        OnPropertyChanged();
                    }
                }
    
                public MyPage()
                {
                    BindingContext = this;
                    MyPerson = new Person();
                }
    
                public event PropertyChangedEventHandler PropertyChanged;
                protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
                {
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    

    Side note: I haven't tested this code, but that should do the trick.

  • StefaanAvonds.3725StefaanAvonds.3725 USMember ✭✭✭

    Forgot the XAML :smile:

    <StackLayout>
        <Label Text="{Binding MyPerson.name}" />
        <Label Text="{Binding MyPerson.age}" />
        <Label Text="{Binding MyPerson.height}" />
        <Label Text="{Binding MyPerson.weight}" />
        ...
    </StackLayout>
    
  • BrunoBarcellosBrunoBarcellos USMember
    edited November 2016

    @StefaanAvonds.3725
    Couldn't make it work still, since it doesn't let me declare a PropertyChanged because ContentPage already implements that, it seems.
    I'm not managing to make it works with MVVM.
    So I beleive I have to Implement INotifyPropertyChange at PersonViewModel, right? How should I proceed?
    That's more close to what I have:

    Page Xaml :
    <StackLayout> <Label Text="{Binding PersonVM.myPerson.name}" /> <Label Text="{Binding PersonVM.myPerson.age}" /> <Label Text="{Binding PersonVM.myPerson.height}" /> <Label Text="{Binding PersonVM.myPerson.weight}" /> ... </StackLayout>

    Page cs :
    private PersonViewModel PersonVM; public Page () { InitializeComponent(); PersonVM = new PersonViewModel(); **client.GetPersonAsync(); }

    PersonViewModel cs :

    public Person myPerson; public PersonViewModel () { myPerson = new Person(); **client.GetPersonCompleted += GetPerson; } public GetPerson(object sender, GetPersonArgs... event) { myPerson = event.Result; }

    I can use a ListView for a single person and it would work, but it seems a wrong approach. I wan't to make it simple so maybe I should just do it instead of using the proper way.

    PS : Just to clarify something in my head, when I use {Binding PersonVM} in xaml it automatically knows its the name of a variable in my xaml.cs and binds it?

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    The INotifyPropertyChanged interface that was described above is supposed to be for the ViewModel.

    Your myPerson is not a property, and does not fire PropertyChanged events.

  • BrunoBarcellosBrunoBarcellos USMember
    edited November 2016

    @AdamMeaney said:
    The INotifyPropertyChanged interface that was described above is supposed to be for the ViewModel.

    Your myPerson is not a property, and does not fire PropertyChanged events.

    Yeah, but I Still don't know how to proceed to Implement that at the ViewModel
    How do I trigger the PropertyChanged properly ?
    public class PersonViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public Person myPerson; public PersonViewModel () { myPerson = new Person(); **client.GetPersonCompleted += GetPerson; } public GetPerson(object sender, GetPersonArgs... event) { myPerson = event.Result; // notify here ? how ? } }

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭
    edited November 2016
    public class PersonViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        private Person myPerson;
        public Person MyPerson
        {
            get
            {
                return myPerson;
            }
            set
            {
                myPerson = value;
                NotifyPropertyChanged();
            }
        }
    
        public void GetPerson(object sender, EventArgs e)
        {
            MyPerson = e.Result;
        }
    }
    

    Obviously I recommend putting the INotifyChanged implementation and the NotifyPropertyChanged method in a base class.

  • BrunoBarcellosBrunoBarcellos USMember
    edited November 2016

    @AdamMeaney , I tried the same approach at first after Stefeen replied, but not luck, the labels stays empty, but If I get using something like label_x = PersonVM.MyPeson.name it works. Something is going on that is not letting the ViewModel notify properly.
    What is weird because I'm using ObservableCollection on another VIewModel and it works perfectly.
    If you don't mind giving a look again and see if something is missing to make it work I'd be glad.

    *Also I'm receiving a warning that has to do with RunTime, and since [CallerMemberName] uses Runtime.CompilerServices something may is related. But if it is the problem shoudn't the ObservableCollection have problems too ?

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    Personally, I would keep the ViewModel as I described. I would say bind the Binding Context of the StackLayout to the MyPerson property. This way when you change it, it updates Binding Context down the line and just use <Label Text="{Binding Name}" /> as my Bindings.

Sign In or Register to comment.