Forum General

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Track changes in properties of models in view model

LeloLelo Member ✭✭✭
public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged; // once per view model I can accept

    public Person CurrentPerson { get; set; } // <---

    public DateTime Date { get; set; }
    public string Title { get; set; }

}

public class Person /* : INotifyPropertyChanged */
{
    // public event PropertyChangedEventHandler PropertyChanged; :(

    public Account Account { get; set; } // <--

    public string Name { get; set; }
    public int Age { get; set; }
}
public class Account /* : INotifyPropertyChanged */
{
    // public event PropertyChangedEventHandler PropertyChanged; :(
    public double Money { get; set; }
}

I am looking for a way to have reactive/obervable tracking of values in a view model . Right now if a Page is binded to the ViewModel - changes made to current person's name, or the person's money in his Account will not update the state of the application/trigger ui update.
Does anyone know if there some way to get notify changes made inside Person and Account as well in a nice way?

Answers

  • Adeel984Adeel984 Member ✭✭✭
    edited April 2020

    Kindly replace below code with your viewModel now it should update your UI.
    `
    public class ViewModel : INotifyPropertyChanged
    {
    private Person currentPerson;
    private DateTime date;
    private string title;

            public ViewModel()
            {
            }
    
            public event PropertyChangedEventHandler PropertyChanged; // once per view model I can accept
    
            public Person CurrentPerson
            {
                get => currentPerson;
                set { currentPerson = value; NotifyPropertyChanged(); }
            }
            public DateTime Date
            {
                get => date;
                set { date = value; NotifyPropertyChanged(); }
            }
            public string Title
            {
                get => title;
                set { title = value; NotifyPropertyChanged(); }
            }
    
            protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
           {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
    
    
        public class Person /* : INotifyPropertyChanged */
        {
            // public event PropertyChangedEventHandler PropertyChanged; :(
    
            public Account Account { get; set; } // <--
    
            public string Name { get; set; }
            public int Age { get; set; }
        }
        public class Account /* : INotifyPropertyChanged */
        {
            // public event PropertyChangedEventHandler PropertyChanged; :(
            public double Money { get; set; }
        }
    
    
    }
    

    `

  • LeloLelo Member ✭✭✭
    edited April 2020

    But will the properties of Account and Person be tracked and will the Page update if Name is changed? I am looking for a way to have changes to their properties update the ui without having to implement property changed explicitly for each Model eg Car, Account...
    Or am I wrong - should a change of Name in the examples above trigger ui change - because the Person object is calling NotifyPropertyChanged()?
    This should maybe have been posted in discussion!

  • Adeel984Adeel984 Member ✭✭✭

    If you've view Binding like Text={Binding CurrentPerson.Name} the view should get changed.

  • LeloLelo Member ✭✭✭
    edited May 2020

    Taking the following example:

    public class ViewModel : INotifyPropertyChanged
    {
    
        #region INotifyPropertyChanged // https://github.com/xamarin/xamarin-forms-samples/blob/master/WorkingWithGestures/TapGesture/WorkingWithGestures/TapViewModel.cs
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    
        static List<string> Names { get; set; } = new List<string>() { "Joe", "Bill", "John" };
    
        string _displayName = Names.First();
        public string DisplayName { get => _displayName; set { _displayName = value; OnPropertyChanged(nameof(DisplayName)); } }
    
        public void NextName()
        {
            DisplayName = Names.SkipWhile(name => name != DisplayName).Skip(1).FirstOrDefault();
            if(DisplayName == null)
            {
                DisplayName = Names.First();
            }
        }
    
    
        public ViewModel()
        {
    
        }
    }
    

    The label in MainPage is updated whenever NextName() is called.

    Now replacing list of names with list of Person instead:

    public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public Person(string name)
            {
                Name = name;
            }
        }
    
    public void NextName()
            {
                /*
                DisplayName = People.SkipWhile(person => person.Name != DisplayName).Skip(1).FirstOrDefault().Name;
                if(DisplayName == null)
                {
                    DisplayName = People.First().Name;
                }
                */
                People.First().Name = "Joe->Jonas"; // <--- does not change display name
            }
    

    And if DisplayName would be DisplayPerson. Changing the Name of the DisplayPerson does not change the label.

    public void NextName()
            {
                DisplayPerson.Name = "newName";
            }
    

    So all levels of nested objects inside the viewmodel need their own notifpropertychanged if they needs tracking:(

Sign In or Register to comment.