Shahid Od
Shahid Od

Reputation: 123

Implementing INotifyPropertyChanged in my project Xamarin

so I have a model class that I called "Objets" and I want to creat a ViewModel so that I can track the changes that happen in one of my Model class arguments which is "nbr_objet". what should I do ? this what I've done so far and please correct me.

Model Class :


public class Objets
    {
    public string Designation { get; set; }
    public string Description { get; set; }
    public float Prix { get; set; }
    public int nbr_objet { get; set; }
    public Objets(string Designation, string Description, float Prix, int nbr_objet)
    {
        this.Designation = Designation;
        this.Description = Description;
        this.Prix = Prix;
        this.nbr_objet= nbr_objet;
    }
    }

ModelViewBase where I have the problem obviously


class ViewModelBase : INotifyPropertyChanged
    {
    public Objets ObjetVM { get; set; }
    public int nbr_objet 
    {
        get { return ObjetVM.nbr_objet; }
        set
        {
            ObjetVM.nbr_objet = value;
            OnPropertyChanged(nameof(ObjetVM.nbr_objet));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyname)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
    }
}

And this is my MainPage.xaml.cs where I creat multiple "Objets"


    public MenuPage()
    {
        InitializeComponent();
        this.BindingContext = new ViewModelBase();
    }

Upvotes: 2

Views: 1672

Answers (3)

Mathias Kirkegaard
Mathias Kirkegaard

Reputation: 481

When you change the property "nbr_objet" you raise that your property inside the ObjetVM has changed, but this is not your bindingContext - your bindingContext is the ViewModelBase.

So rather rewrite it:

private int nbr_object;

public int Nbr_objet_property
{
    get { return nbr_objet; }
    set
    {
        nbr_objet = value;
        OnPropertyChanged(nameof(Nbr_objet_property));
    }
}

And then everytime you cahnge "Nbr_objet_property" it should update whatever you binded it to.

Also, "ObjetVM" is no a viewModel since it does not implement the INotifyPropertyChanged logic.

Hope it makes sense? :)

Upvotes: 0

Leon Lu
Leon Lu

Reputation: 9274

Here is running screenshot.

enter image description here

You can achieve it like following format in your model.

 public  class MyObjets : INotifyPropertyChanged
{
   // public string Designation { get; set; }
  //  public string Description { get; set; }
 //   public float Prix { get; set; }
 //   public int nbr_objet { get; set; }


    int _nbr_objet;
    public int Nbr_objet
    {
        get
        {
            return _nbr_objet;
        }

        set
        {
            if (_nbr_objet != value)
            {
                _nbr_objet = value;
                OnPropertyChanged("Nbr_objet");

            }
        }

    }

    float _prix;
    public float Prix
    {
        get
        {
            return _prix;
        }

        set
        {
            if (_prix != value)
            {
                _prix = value;
                OnPropertyChanged("Prix");

            }
        }

    }

    string _designation;
    public string Designation
    {
        get
        {
            return _designation;
        }

        set
        {
            if (_designation != value)
            {
                _designation = value;
                OnPropertyChanged("Designation");

            }
        }

    }

    string _description;
    public string Description
    {
        get
        {
            return _description;
        }

        set
        {
            if (_description != value)
            {
                _description = value;
                OnPropertyChanged("Description");

            }
        }

    }


    public MyObjets(string Designation, string Description, float Prix, int nbr_objet)
    {
        this._designation = Designation;
        this._description = Description;
        this._prix = Prix;
        this._nbr_objet = nbr_objet;
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }
 }

Then Here is Layout.

   <StackLayout>
    <!-- Place new controls here -->
    <Label Text="{Binding Designation}" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Label Text="{Binding Description}" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Label Text="{Binding Prix}" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
    <Label Text="{Binding Nbr_objet}" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />
  </StackLayout>

Here is layout backend code.

  public MainPage()
    {
        InitializeComponent();
        BindingContext = new MyObjets("xxxx","cccc",1.22f,11);
    }

Here is my demo about MVVM with Listview, you can refer to it as well. https://github.com/851265601/MVVMListview

If the reply is helpful, please do not forget to mark it as answer.

======================Update========================

You want to achieve the result like following GIF? enter image description here

Here is your model

  public  class MyObjets 
{
    public string Designation { get; set; }
    public string Description { get; set; }
    public float Prix { get; set; }
    public int nbr_objet { get; set; }

    public MyObjets(string Designation, string Description, float Prix, int nbr_objet)
    {
        this.Designation = Designation;
        this.Description = Description;
        this.Prix = Prix;
        this.nbr_objet = nbr_objet;
    }

}

Here is ViewModelBase

 public class ViewModelBase: INotifyPropertyChanged
{
    public ViewModelBase()
    {

        ObjetVM = new MyObjets("ccc","xxx",1.2f,123);
    }
public MyObjets ObjetVM { get; set; }
    public int nbr_objet
    {
        get { return ObjetVM.nbr_objet; }
        set
        {
            ObjetVM.nbr_objet = value;
            OnPropertyChanged(nameof(ObjetVM.nbr_objet));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyname)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
}

}

Here layout forground code.

 <StackLayout>

    <Label Text="{Binding nbr_objet}" 
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />

    <Button Text="change the value" Clicked="Button_Clicked"></Button>
</StackLayout>

here is layout background code.

   public partial class MainPage : ContentPage
{
    ViewModelBase viewModelBase;
    public MainPage()
    {
        InitializeComponent();


        viewModelBase =  new ViewModelBase();
        BindingContext = viewModelBase;
    }

    private void Button_Clicked(object sender, EventArgs e)
    {
        viewModelBase.nbr_objet = 111;
    }
}

Upvotes: 2

user1934587390
user1934587390

Reputation: 461

You need to implement INotifyPropertyChanged on any object you want to track changes on. Right now you are only tracking changes on the viewmodel, so you also need to add INotifyPropertyChanged on the Objets class, too, as well as each property within the class with the getters/setters with OnPropertyChanged like you did in the viewmodel.

public class Objets: INotifyPropertyChanged

Upvotes: 0

Related Questions