【问题标题】:INotifyPropertyChanged - Changing PropertyName Causes No EffectINotifyPropertyChanged - 更改 PropertyName 没有效果
【发布时间】:2015-12-13 16:19:10
【问题描述】:

我正在尝试将我的 Winforms UI 绑定到我的 ViewModel。我能够在 UI 更改时成功更新我的 ViewModel,反之亦然。但是,我似乎无法理解 PropertyChangedEventHandler 中使用的“PropertyName”的用途是什么,因为无论我放在那里,它都将始终有效。我不知道我是否已经把事情搞混了,因为我已经阅读了很多关于架构模式的文章(MVP、MVC、MVVM 和 MVP-VM(这是我现在尝试做的))。

这是相关代码的一部分:

视图模型

public class AdditionViewModel:INotifyPropertyChanged
{
    private string augend;

    public string Augend
    {
        get { return augend; }
        set { 
                if(augend != value)
                {
                    augend = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("ugend"));
                }
            }
    }
    private string addend;

    public string Addend
    {
        get { return addend; }
        set {
                if (addend != value)
                {
                    addend = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("ddend"));
                }
            }
    }
    private string answer;

    public string Answer
    {
        get { return answer; }
        set {
                if(answer != value)
                {
                    answer = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("nswer"));
                }
            }
    }

    public AdditionClass additionClass;
    public AdditionViewModel(AdditionClass _additionClass)
    {
        additionClass = _additionClass;
    }
    public void Add()
    {
        //Some verifications first before inserting the value to the model class
        this.Augend = "1";//Testing for from code to UI binding
        additionClass.Augend = Double.Parse(Augend);
        additionClass.Addend = Double.Parse(Addend);
        //Somewhere here should implement the compute but since addition is a very simple task, no methods were called;
        Answer = additionClass.Answer.ToString();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            MessageBox.Show(e.PropertyName);
            handler(this, new PropertyChangedEventArgs(e.PropertyName));
        }
    }
}

表格:

private void Form1_Load(object sender, EventArgs e)
{
    additionPresenter = new Presenter.AdditionPresenter(new ViewModel.AdditionViewModel(new Model.AdditionClass()));
    additionViewModelBindingSource.DataSource = additionPresenter.additionViewModel;
}

private void button1_Click(object sender, EventArgs e)
{
    additionPresenter.AddButtonClick();
}

演讲者:

public AdditionPresenter(AdditionViewModel _additionViewModel)
{
    additionViewModel = _additionViewModel;
}

public void AddButtonClick()
{
    additionViewModel.Add();
}

Designer 中自动生成的代码之一(在 UI 上绑定):

// 
// textBox1
// 
this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.additionViewModelBindingSource, "Addend", true));
this.textBox1.Location = new System.Drawing.Point(24, 41);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 0;

从 ViewModel 上可以看出,我在设置器中省略了每个 PropertyName 开头的所有“A”,但应用程序仍在工作。 对不起,长代码粘贴。我似乎找不到比仅仅向您展示实现更好的解释

【问题讨论】:

  • 因为您使用BindingSource 作为表单中的“ViewModel”对象。将数据绑定更改为不使用 BindingSource => textBox1.DataBinding.Add("Text", additionViewModel, "Addend", true) 然后 NotifyPropertyChanged 事件将产生影响 - 或不会对您的情况产生影响
  • 那么是否意味着通过使用BindingSource作为控件的BindingSource,它已经启用了控件与对象的双向绑定?正如你所说,通过使用 ViewModel 作为BindingSource,会使PropertyName 很重要并影响绑定?
  • 我已经实际测试了您所说的内容,并且通过使用 ViewModel 进行数据绑定而不是 BindingSource,现在要求 PropertyName 与 @987654335 中的相同@在数据绑定。既然两者都有效,那么哪个更受欢迎?或者我应该为我的新问题发布另一个帖子。
  • 我想如果你创建另一个线程你会得到更多的答案,我希望。在我自己的意见中,我使用BindingSource 在 UI 具有网格和当前在同一视图/表单上选择的项目信息的情况下 - 我使用BindingSourceCurrent 属性。但在其他情况下,我更喜欢实现 INotifyPropertyChanged 接口的 ViewModel 实例。这让我“感觉”我可以控制。我不确定,但经过测试,BindingSource 似乎会在每次更新某些属性后循环所有 ViewModel 属性。
  • @Fabio 我编辑了帖子并提供了有关 PropertyChanged 事件中的属性名称错误为什么我仍然有双向数据绑定的详细说明? 您可以阅读使用我在答案中提供的链接的源代码。希望答案对您有所帮助:)

标签: c# winforms inotifypropertychanged


【解决方案1】:

INotifyPropertyChanged 不是数据绑定所必需的,但它可以实现双向数据绑定。
事实上,如文档中所述:INotifyPropertyChanged 接口用于通知客户端(通常是绑定客户端)属性值已更改。

在简单(单向)数据绑定中,当您更改控件的绑定属性时,会将值推送到对象的绑定属性中,不需要INotifyPropertyChanges

但是如果没有INotifyPropertyChanged,如果您使用代码更改对象的绑定属性的值,新值不会推送到控件的绑定属性中。


在 PropertyChanged 事件中有错误的属性名称为什么我仍然有双向数据绑定?

事实上这是因为使用BindingSource 作为数据绑定的来源,正如 cmets 中的Fabio 所提到的那样。

当使用BindingSource 作为数据绑定的数据源时,您的对象只需实现INotifyPropertyChanged 并引发PropertyChaned 事件(即使属性名称为空或错误)然后BindingSource(实际上它的内部 BindingList<T>) subscribes 用于 PropertyChaned 事件,当 received 事件时,它会检查您是否传递了正确的属性名称或传递了空的属性名称,它将调用 ResetBindings(),这会导致绑定到BindingSource 的控件,用于重新读取列表中的所有项目并刷新它们的显示值。 PropertyChanged 中的正确名称会导致双向数据绑定的正常行为,并且还会导致在 e.PropertyDescriptor 中使用正确的属性引发 ListChanged 事件。

【讨论】:

  • 我实际上通过 View model this.Augend = "1";//Testing for from code to UI binding 处的行测试了“从对象的绑定属性到控件的绑定属性”,它可以工作,因为单击按钮后,其中一个文本框值将是“ 1"。真正困扰我的是OnPropertyChanged(new PropertyChangedEventArgs("ugend"));“PropertyName”参数。我认为它是绑定到textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.additionViewModelBindingSource, "Addend", true)); 的那个。
  • 我测试了两件事。直接使用您的模型,它需要 null 或空字符串或属性的确切名称才能工作。使用BindingSource 它只需要使用任何名称引发事件。
  • 我个人更喜欢正确实现接口,也使用BindingSource。使用绑定源,您将获得良好的设计时支持。
  • @Lawrence 我编辑了帖子并提供了关于 PropertyChanged 事件中的属性名称错误为什么我仍然有双向数据绑定? 您可以阅读使用我在答案中提供的链接的源代码。希望答案对您有所帮助:)
  • 谢谢!这绝对是有帮助的:)。所以这意味着我仍然可以维护BindingSource 以获得良好的设计时支持,同时提供正确的PropertyName 以便通过不阅读所有项目来节省资源在列表中?
猜你喜欢
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多