.NET WinForms INotifyPropertyChanged updates all bindings when one is changed. Better way?
- by Dave Welling
In a windows forms application, a property change that triggers INotifyPropertyChanged, will result in the form reading EVERY property from my bound object, not just the property changed. (See example code below)
This seems absurdly wasteful since the interface requires the name of the changing property. It is causing a lot of clocking in my app because some of the property getters require calculations to be performed.
I'll likely need to implement some sort of logic in my getters to discard the unnecessary reads if there is no better way to do this.
Am I missing something? Is there a better way? Don't say to use a different presentation technology please -- I am doing this on Windows Mobile (although the behavior happens on the full framework as well).
Here's some toy code to demonstrate the problem. Clicking the button will result in BOTH textboxes being populated even though one property has changed.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace Example
{
public class ExView : Form
{
private Presenter _presenter = new Presenter();
public ExView()
{
this.MinimizeBox = false;
TextBox txt1 = new TextBox();
txt1.Parent = this;
txt1.Location = new Point(1, 1);
txt1.Width = this.ClientSize.Width - 10;
txt1.DataBindings.Add("Text", _presenter, "SomeText1");
TextBox txt2 = new TextBox();
txt2.Parent = this;
txt2.Location = new Point(1, 40);
txt2.Width = this.ClientSize.Width - 10;
txt2.DataBindings.Add("Text", _presenter, "SomeText2");
Button but = new Button();
but.Parent = this;
but.Location = new Point(1, 80);
but.Click +=new EventHandler(but_Click);
}
void but_Click(object sender, EventArgs e)
{
_presenter.SomeText1 = "some text 1";
}
}
public class Presenter : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _SomeText1 = string.Empty;
public string SomeText1
{
get
{
return _SomeText1;
}
set
{
_SomeText1 = value;
_SomeText2 = value; // <-- To demonstrate that both properties are read
OnPropertyChanged("SomeText1");
}
}
private string _SomeText2 = string.Empty;
public string SomeText2
{
get
{
return _SomeText2;
}
set
{
_SomeText2 = value;
OnPropertyChanged("SomeText2");
}
}
private void OnPropertyChanged(string PropertyName)
{
PropertyChangedEventHandler temp = PropertyChanged;
if (temp != null)
{
temp(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
}