我正在尝试将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”,但该应用程序仍在工作.
很长的代码粘贴很抱歉.我似乎找不到比向您展示实现更好的解释了
解决方法:
INotifyPropertyChanged
对于数据绑定不是必需的,但是它启用双向数据绑定.
实际上,如文档中所述:INotifyPropertyChanged接口用于通知客户端(通常是绑定客户端)属性值已更改.
在简单(单向)数据绑定中,当您更改控件的bound属性时,将值推入对象的bound属性中,并且不需要INotifyPropertyChanges.
但是如果没有INotifyPropertyChanged,则如果使用代码更改对象的bound属性的值,则新值不会压入控件的bound属性.
PropertyChanged事件中的属性名称错误,为什么我仍然具有双向数据绑定?
实际上,这是因为使用BindingSource作为数据绑定的源,正如Fabio在评论中提到的那样.
当使用BindingSource作为数据绑定的数据源时,对象就足以实现INotifyPropertyChanged并引发PropertyChaned事件(即使属性名称为空或错误),然后引发BindingSource(实际上是其内部BindingList< T>)subscribes for PropertyChaned事件当事件received发生时,它将检查您是否未传递正确的属性名称或是否传递了空属性名称,它将调用ResetBindings()
,这将导致绑定到BindingSource的控件重新读取列表中的所有项目并刷新其显示内容价值观.
PropertyChanged中正确的名称会导致双向数据绑定的正常行为,还会导致e.PropertyDescriptor中具有正确属性的引发ListChanged
事件.