Jakob Busk Sørensen
Jakob Busk Sørensen

Reputation: 6081

INotifyPropertyChanged wont pass through View Model

I am making a WinForms program, with an architectural pattern quite similar to MVVM. The main difference is that class I am using as model, also acts as a user control. I know this might not be the most awesome setup, but it is what I have to work with.

The problem is, that when the property in the model is changed, the change isn't reflected in the view...

I am suspecting that I haven't implemented INotifyPropertyChanged correctly, but I can't really see anything wrong. I hope you guys can...

Model

public partial class ModelAndUserControl : UserControl, INotifyPropertyChanged
{
    private decimal _price;

    public ModelAndUserControl()
    {
        InitializeComponent();
    }

    // Implement INotifyPropertyChanged        
    public event PropertyChangedEventHandler PropertyChanged;
    public void InvokePropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, e);
        }
    }

    // Changes in this property, should be reflected in the view
    public decimal Price
    {
        get { return _price; }
        set
        {
            _price = value;
            InvokePropertyChanged(new PropertyChangedEventArgs("Price");
        }
    }
}

View-Model

public class MyViewModel
{
    private readonly MyView view;
    private ModelAndUserControl model;

    public MyViewModel(MyView view, ModelAndUserControl model) 
    {
        this.view = view;
        this.model = model;
    }

    // Debugging reveals that the value of the formatted 
    // string, changes correctly when the model property changes.
    // But the change isn't reflected in the view.
    public string FormattedPrice
    {
        get { return string.format("{0:n0} EUR", model.Price); }
    }
}

View

public partial class MyView : UserControl
{
    private MyViewModel viewModel;

    public MyView() 
    {
        InitializeComponent(ModelAndUserConrol model);

        // Create an instance of the view model
        viewModel = new MyViewModel(this, model);

        // Create the data binding to the price
        txtPrice.DataBindings.Add("Text", viewModel, nameof(viewModel.FormattedPrice));
    }
}

Upvotes: 0

Views: 615

Answers (1)

Mats391
Mats391

Reputation: 1209

You need to raise PropertyChanged on the view model you bind to or the binding wont know when to update. To raise PropertyChanged on your FormattedPrice property when the model changes you can do something like this.

public class MyViewModel : INotifyPropertyChanged
{
    private readonly MyView view;
    private ModelAndUserControl model;

    public MyViewModel(MyView view, ModelAndUserControl model) 
    {
        this.view = view;
        this.model = model;
        this.model.PropertyChanged += Model_PropertyChanged;
    }

    // Debugging reveals that the value of the formatted 
    // string, changes correctly when the model property changes.
    // But the change isn't reflected in the view.
    public string FormattedPrice
    {
        get { return string.format("{0:n0} EUR", model.Price); }
    }

    private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch(e.PropertyName){
            case "Price":
                InvokePropertyChanged("FormattedPrice");
                break;
            default:
                break;
        }
    }

    // Implement INotifyPropertyChanged        
    public event PropertyChangedEventHandler PropertyChanged;
    public void InvokePropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, e);
        }
    }
}

Upvotes: 2

Related Questions