11 Stimmen

Was ist das Konzept hinter INotifyPropertyChanged?

Alle Silverlight-Beispiele mit MVVM verwenden die Schnittstelle IPropertyChanged. Was ist das Konzept dahinter und warum müssen wir ein Ereignis auslösen, wenn wir einen Wert setzen?

Beispiel: -

public class UserNPC:INotifyPropertyChanged
{
    private string name;
    public string Name { 
        get { return name; } 
        set { name = value; onPropertyChanged(this, "Name"); } 
    }
    public int grade;
    public int Grade { 
        get { return grade; } 
        set { grade = value; onPropertyChanged(this, "Grade"); } 
    }

    // Declare the PropertyChanged event
    public event PropertyChangedEventHandler PropertyChanged;

    // OnPropertyChanged will raise the PropertyChanged event passing the
    // source property that is being updated.
    private void onPropertyChanged(object sender, string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Was ist der genaue Zweck von INotifyPropertyChanged?

15voto

Lernkurve Punkte 18686

Sie haben die folgenden Abhängigkeiten:

Ansicht Bindungsmodell

Das Konzept sieht folgendermaßen aus:

Wenn einige Daten in Ihrem Modell Objekt ändert, müssen Sie die PropertyChanged Veranstaltung. Warum? Weil die Verbindlich Objekt eine Methode mit dem Datenobjekt registriert hat PropertyChanged Veranstaltung.

Sie müssen also nur etwas tun, wenn sich etwas in Ihrem Modell Objekts ist es, das Ereignis auszulösen, und Sie sind fertig.

Wenn Sie das tun, wird die Verbindlich Objekt wird durch Ihr Ereignis über die Änderung informiert. Die Verbindlich Objekt wiederum lässt die Siehe Objekt wissen, dass etwas passiert ist. Die Siehe Objekt kann dann die Benutzeroberfläche bei Bedarf aktualisieren.

Code-Beispiel

Hier haben Sie ein kompilierbares Beispiel. Setzen Sie ein paar Haltepunkte, gehen Sie durch den Code mit F11 und sehen, was hinter den Kulissen passiert. Beachten Sie, dass dieses Beispiel die folgenden Abhängigkeiten hat: Ansichtsmodell. Ich habe das Binding-Objekt weggelassen.

using System;
using System.ComponentModel;

namespace INotifyPropertyChangedDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create 2 listeners.
            View1 view1 = new View1();
            View2 view2 = new View2();

            // Create 1 data object.
            Model model = new Model();

            // Connect listener with data object.
            model.PropertyChanged += new PropertyChangedEventHandler(view1.MyPropertyChangedEventHandler);
            model.PropertyChanged += new PropertyChangedEventHandler(view2.MyPropertyChangedEventHandler);

            // Let data object publish change notification.
            model.FirstName = "new name";

            // Check whether all listeners got notified.
            // ... via console.
        }

        public class Model : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;

            private string firstName;
            public string FirstName
            {
                get { return firstName; }
                set
                {
                    if (firstName != value)
                    {
                        firstName = value;
                        if (PropertyChanged != null)
                        {
                            PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
                        }
                    }
                }
            }
        }

        public class View1
        {
            public void MyPropertyChangedEventHandler(object source, PropertyChangedEventArgs arg)
            {
                Console.WriteLine("Listener 1: Changed Property: {0}", arg.PropertyName);
                string newValue = ((Model) source).FirstName;
                Console.WriteLine("Listener 1: Changed Property Value: {0}", newValue);
            }
        }

        public class View2
        {
            public void MyPropertyChangedEventHandler(object source, PropertyChangedEventArgs arg)
            {
                Console.WriteLine("Listener 2: Changed Property: {0}", arg.PropertyName);
                string newValue = ((Model)source).FirstName;
                Console.WriteLine("Listener 2: Changed Property Value: {0}", newValue);
            }
        }
    }
}

6voto

Jay Punkte 53725

MVVM in WPF & Silverlight wird durch die Bindung von UI-Elementen an das View Model implementiert. Wenn sich das Ansichtsmodell ändert, woher weiß die Benutzeroberfläche dann, dass sie sich selbst aktualisieren soll?

INotifyPropertyChanged stellt einfach ein Ereignis zur Verfügung, auf das die Benutzeroberfläche "hören" kann. Wenn also ein Steuerelement "hört", dass sich die Eigenschaft, an die es gebunden ist, geändert hat, kann es sich selbst "aktualisieren".

Nehmen wir zum Beispiel an, Sie haben eine TextBlock die einen Aktienkurs anzeigt und an die Aktie gebunden ist string Price Eigenschaft eines View-Modells. Das Ansichtsmodell wiederum nutzt einen Dienst, um die Aktienkurse alle 30 Sekunden zu aktualisieren. Alle 30 Sekunden wird also die Price Eigentumsänderungen: Vor 30 Sekunden war es "29,20 $", jetzt ist es "29,12 $" und in 30 Sekunden wird es "28,10 $" sein. Die TextBlock Bindung wird angewendet, wenn die TextBlock geladen wird, aber nicht jedes Mal, wenn die Price Änderungen. Wenn Sie jedoch die INotifyPropertyChanged und lösen das Ereignis für die Eigenschaft "Preis" in der Price Setter, dann die TextBlock sich in das Ereignis einklinken kann und dadurch "weiß", wann er zurückgehen und das Ereignis "neu lesen" muss Price Eigenschaft und aktualisieren Sie den angezeigten Text.

3voto

Gone Coding Punkte 90304

Die meisten Silverlight-Steuerelemente achten auf Änderungen an den angezeigten Daten, indem sie einfach die PropertyChanged-Ereignisse abonnieren.

Das Steuerelement macht z.B. so etwas hinter den Kulissen:

    public void Loaded()
    {
        if (myDataObject is INotifyPropertyChanged)
        {
            (myDataObject as INotifyPropertyChanged).PropertyChanged +=new PropertyChangedEventHandler(onPropertyChanged);
        }
    }

Das ist auch der Grund, warum ObservableCollection anstelle von einfachen Listen in Silverlight-Apps verwendet wird. Sie implementieren INotifyPropertyChanged, so dass Steuerelemente, die Sammlungen anzeigen, in der Lage sind, Änderungen zu sehen, die an der Liste sowie an einzelnen Elementen in einer Liste auftreten.

0voto

Ich hatte vor kurzem zum Spaß ein dreistufiges Programm erstellt und wollte sicherstellen, dass alle Teile so weit wie möglich voneinander getrennt sind.

In meiner grafischen Benutzeroberfläche konnte der Benutzer einen Namen eingeben, wie er wollte, aber meine Geschäftsklasse enthielt eine Logik, um alle Namen in Großbuchstaben zu ändern. Dies funktionierte, aber die grafische Benutzeroberfläche wird nie über diese Aktualisierung informiert, die die Geschäftsklasse vorgenommen hat.

Meine damalige Lösung war einfach... sah aber nicht gut aus. Etwas wie das Folgende

var _person = new Person();

// In some form event handler like button click
_person.Name = txtName.Text;
txt.Name.Text = _person.Name;

Auf diese Weise wurde die grafische Benutzeroberfläche aktualisiert, während sie von der Geschäftslogik getrennt blieb. Ich wollte ein Ereignis erstellen, das ausgelöst wird, wenn die Geschäftslogik den Wert gegenüber der Eingabe in der grafischen Benutzeroberfläche ändert, und die grafische Benutzeroberfläche würde auf dieses Ereignis hören.

Jetzt hätte ich also etwas wie...

var _person = new Person();

// In some form event handler like button click
_person.Name = txtName.Text;

// In the GUI class
public void OnInternalPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
    txtName.Text = _person.Name;
}

HINWEIS: Ich tue dies nicht bei allen Eigenschaftsänderungen... nur bei denen, die von dem abweichen, was der Benutzer erwartet... Ich ändere alle Kleinbuchstaben in Großbuchstaben und zeige dies dem Benutzer an.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X