.NET WinForms INotifyPropertyChanged aktualisiert alle Bindungen, wenn man sich verändert. Der bessere Weg?
In einer windows forms-Anwendung, eine Eigenschaft zu ändern, löst die INotifyPropertyChanged, wird das Ergebnis in form der Lektüre JEDE Immobilie, die von meiner gebundenes Objekt, nicht nur die Eigenschaft verändert. (Siehe Beispiel-code unten)
Scheint dies absurd verschwenderisch, da die Schnittstelle erfordert den Namen der Eigenschaft ändern. Es verursacht eine Menge von Taktung in meiner app, weil einige der property get-Berechnungen erfordern, um durchgeführt werden.
Ich werde wahrscheinlich benötigen, um zu implementieren eine Art von Logik in meinem Getter um die unnötige verwerfen liest, wenn es keinen besseren Weg, dies zu tun.
Bin ich etwas fehlt? Gibt es einen besseren Weg? Sagen Sie nicht, verwenden Sie eine andere Präsentationstechnik bitte -- ich mache das auf Windows Mobile (obwohl das Verhalten geschieht auf der kompletten framework).
Hier ein paar Spielzeug-code um das problem zu demonstrieren. Ein Klick auf die Schaltfläche Ergebnis in BEIDE Textfelder werden gefüllt-auch wenn eine Eigenschaft geändert hat.
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));
}
}
}
}
InformationsquelleAutor der Frage Dave Welling | 2010-05-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der Grund, warum alle Eigenschaften ausgelesen werden, wenn das event gefeuert wird, ruht in der PushData-Methode aufgerufen, die das binding-Objekt, wenn die ProperyChanged-Ereignis ausgelöst wird. Wenn man sich den stacktrace, werden Sie feststellen, dass die PropValueChanged Methode des internen Objekts BindToObject ist aufgerufen, das wiederum ruft die Oncurrentchanged Veranstaltung auf der BindingManager. Die binding-Mechanismus merkt sich das aktuelle Element ändert, aber es nicht tun, eine feinere Unterscheidung. Die "Täter" PushData-Methode ruft die get-Methode auf Ihre Eigenschaften (werfen Sie einen Blick auf den code, der mit dem Reflektor). Also es gibt keine Möglichkeit um ihn herum. That being said, als Faustregel gilt, dass in den get-und set-Accessoren ist es nicht ratsam, schwere Verarbeitung, mit separaten get-und set-Methoden für diese (wenn möglich)
Werfen Sie auch einen Blick auf diese Artikel, und dieser Kommentar insbesondere (http://www.codeproject.com/Messages/2514032/How-Binding-watches-control-properties-i-e-how-doe.aspx), die genau erklärt, wie das propertychanged-event gefeuert wird, obwohl es nicht Ihre Adresse getter problem: http://www.codeproject.com/KB/database/databinding_tutorial.aspx?msg=2514032
Einer Idee zu erkunden, ist die Verzögerung der getter aufgerufen wird. Dies können Sie erreichen, indem Sie das Spiel mit der ControlUpdateMode Eigenschaft der Bindung. Wenn dieser Wert auf " Nie " gesetzt, wird das entsprechende Steuerelement wird nicht aktualisiert, wenn es eine Veränderung. Allerdings, wenn Sie wechseln Sie den Wert wieder auf OnPropertyChanged, PushData-Methode aufgerufen werden, so dass der Getter zugegriffen werden. Also in eurem Beispiel dieser code wird temporär verhindern, dass die textbox 2 aktualisieren:
InformationsquelleAutor der Antwort anchandra
Teste ich das erstellen von Unterklassen so verbindlich ist wie dieser und die Verwaltung von OnPropertyChanged, vielleicht hilft Sie.
Nun das problem, dass ich finde ist, dass das Steuerelement überschreibt den Wert des verknüpften Objekts,
also habe ich geändert, um
dann das erste mal propertychanges heißt ich deaktivieren controlupdate. und die Steuerung wird korrekt aktualisiert, auf den ersten Lauf.
InformationsquelleAutor der Antwort pedro