【问题标题】:INotifyPropertyChanged wont pass through View ModelINotifyPropertyChanged 不会通过视图模型
【发布时间】:2017-05-02 05:45:12
【问题描述】:

我正在制作一个 WinForms 程序,其架构模式与MVVM 非常相似。主要区别在于我用作模型的类也充当用户控件。我知道这可能不是最棒的设置,但这是我必须使用的。

问题是,当模型中的属性发生变化时,变化并没有反映在视图中......

我怀疑我没有正确实现INotifyPropertyChanged,但我真的看不出有什么问题。我希望你们能...

型号

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");
        }
    }
}

视图模型

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); }
    }
}

查看

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));
    }
}

【问题讨论】:

  • 您通知Price 已更改,但FormattedPrice 未更改
  • 其实他们两个都变了。但我的理解是,如果基础属性(在本例中为 Price)发生更改,那么基础通知将涵盖所有“派生”属性?
  • 不,您的数据绑定只监听 FormattedPrice 的变化。您要么必须通过在您的视图模型中订阅并将其提升为 FormattedPrice 来冒泡 PropertyChangedEvent,或者从 FormattedPrice 开始,订阅 Price 并在视图中进行格式化。
  • 我不希望直接绑定到模型,因为这会导致一些其他问题。更具体地说,如果我将模型更改为新实例,我必须重做所有数据绑定。我想通过绑定到视图模型来避免这种情况。
  • 类似this

标签: c# winforms mvvm inotifypropertychanged


【解决方案1】:

您需要在绑定到的视图模型上引发PropertyChanged,否则绑定将不知道何时更新。要在模型更改时在 FormattedPrice 属性上提高 PropertyChanged,您可以执行以下操作。

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);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    相关资源
    最近更新 更多