Wie zu verwenden INotifyPropertyChanged richtig in WPF/XAML

Habe ich ein benutzerdefiniertes Objekt, das ich bin versucht, auf ein Steuerelement binden. Auf, das benutzerdefinierte Objekt habe ich implementiert die INotifyPropertyChanged-Schnittstelle. Ich habe erfolgreich gebunden zu meinem Objekt und eine Eigenschaft auf das Objekt.

Was ich nicht herausfinden kann, ist, wie gehen von dort aus. Ich hab schon 2 Tage jetzt und ich kann immer noch nicht bekommen es funktioniert.

Meine Vermutung war, dass, wenn ich ändern würde, die Eigenschaft an das Steuerelement gebunden werden, dass der Wert in der Eigenschaft würde dann zeigen, bis in der Steuerung. Doch egal, wie sehr ich die Eigenschaft ändern, die Benutzeroberfläche ist nie aktualisiert, neben der anfänglichen Wert.

Habe ich INotifyPropertyChanged implementiert, die in dieser Weise:
Eine Basis-Klasse, die INotifyPropertyChanged implementiert

Also meine Basis Klasse ist das denn:

[Serializable]
public abstract class BindableObject : INotifyPropertyChanged
{
    #region Data

    private static readonly Dictionary<string, PropertyChangedEventArgs> eventArgCache;
    private const string ERROR_MSG = "{0} is not a public property of {1}";

    #endregion //Data

    #region Constructors

    static BindableObject()
    {
        eventArgCache = new Dictionary<string, PropertyChangedEventArgs>();
    }

    protected BindableObject()
    {
    }

    #endregion //Constructors

    #region Public Members

    ///<summary>
    ///Raised when a public property of this object is set.
    ///</summary>
    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    ///<summary>
    ///Returns an instance of PropertyChangedEventArgs for 
    ///the specified property name.
    ///</summary>
    ///<param name="propertyName">
    ///The name of the property to create event args for.
    ///</param>  
    public static PropertyChangedEventArgs
        GetPropertyChangedEventArgs(string propertyName)
    {
        if (String.IsNullOrEmpty(propertyName))
            throw new ArgumentException(
                "propertyName cannot be null or empty.");

        PropertyChangedEventArgs args;

        //Get the event args from the cache, creating them
        //and adding to the cache if necessary.
        lock (typeof(BindableObject))
        {
            bool isCached = eventArgCache.ContainsKey(propertyName);
            if (!isCached)
            {
                eventArgCache.Add(
                    propertyName,
                    new PropertyChangedEventArgs(propertyName));
            }

            args = eventArgCache[propertyName];
        }

        return args;
    }

    #endregion //Public Members

    #region Protected Members

    ///<summary>
    ///Derived classes can override this method to
    ///execute logic after a property is set. The 
    ///base implementation does nothing.
    ///</summary>
    ///<param name="propertyName">
    ///The property which was changed.
    ///</param>
    protected virtual void AfterPropertyChanged(string propertyName)
    {
    }

    ///<summary>
    ///Attempts to raise the PropertyChanged event, and 
    ///invokes the virtual AfterPropertyChanged method, 
    ///regardless of whether the event was raised or not.
    ///</summary>
    ///<param name="propertyName">
    ///The property which was changed.
    ///</param>
    protected void RaisePropertyChanged(string propertyName)
    {
        this.VerifyProperty(propertyName);

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            //Get the cached event args.
            PropertyChangedEventArgs args =
                GetPropertyChangedEventArgs(propertyName);

            //Raise the PropertyChanged event.
            handler(this, args);
        }

        this.AfterPropertyChanged(propertyName);
    }

    #endregion //Protected Members

    #region Private Helpers

    [Conditional("DEBUG")]
    private void VerifyProperty(string propertyName)
    {
        Type type = this.GetType();

        //Look for a public property with the specified name.
        PropertyInfo propInfo = type.GetProperty(propertyName);

        if (propInfo == null)
        {
            //The property could not be found,
            //so alert the developer of the problem.

            string msg = string.Format(
                ERROR_MSG,
                propertyName,
                type.FullName);

            Debug.Fail(msg);
        }
    }

    #endregion //Private Helpers
}

Ich Erben von dieser Klasse und in meiner abgeleiteten Klasse ich mache das auf meinem Grundstück:

    public virtual string Name
    {
        get
        {
            return m_strName;
        }
        set
        {
            m_strName = value;
            RaisePropertyChanged("Name");
        }
    }

Meiner XAML-Code sieht so aus (gekürzte version):

<Window x:Class="PSSPECApplication.Windows.Project"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:System="clr-namespace:System;assembly=mscorlib"
    DataContext="{Binding SizingProject, RelativeSource={RelativeSource Self}}">
        <StackPanel VerticalAlignment="Center">
            <TextBox Name="txtProjectName" Text="{Binding Name}" />
        </StackPanel>

Können Sie sehen, dass das Fenster Daten-Kontext ist eine Eigenschaft, die man als SizingProject. SizingProject ist der abgeleitete Typ (abgeleitet von BindableObject) und hat die Eigenschaft Name in es und Löst das PropertyChanged-Ereignis-handler.

In mein Fenster Konstruktor ich Auffüllen SizingProject und der Name-Eigenschaft gesetzt ist.

Um dies zu testen habe ich auch eine Taste auf dem Fenster, das ein Ereignis auslöst, setzt die Eigenschaft Name auf etwas anderes als das, was es ist ursprünglich. Aber wenn die name-Eigenschaft geändert wird, wird nichts jemals passiert. Ich habe zurückverfolgt BindableObject und das PropertyChanged-Ereignis wird immer auf null gesetzt, so dass keine hf ist immer gesetzt und ausgeführt. Warum ist das so?

Ich dachte, dass durch die Implementierung von INotifyPropertyChanged und verwenden, geben Sie eine bindende Kräfte WPF zu setzen, dass event-handler automatisch und dann das richtige Verhalten passiert? Für mich, ich sehe nie dieses Verhalten.


Ich herausgefunden, das Problem. Was ich tun musste, war zu erstellen, die eine DependencyProperty für meine Immobilie SizingProject. Nachdem ich wusste, dass alles geklappt hat.

        public static readonly DependencyProperty SizingProjectProperty =
        DependencyProperty.Register("SizingProject", typeof(Sizing.Project), typeof(Project), new UIPropertyMetadata());

    public Sizing.Project SizingProject
    {
        get
        {
            return (Sizing.Project)GetValue(Project.SizingProjectProperty);
        }
        set
        {
            SetValue(Project.SizingProjectProperty, value);
        }
    }
Sind Sie immer keine verbindlichen Fehler in der Ausgabe-Fenster?
Ich hatte auf diese Lösung zu Gunsten von dieses statt. pochet.net/blog/2010/07/02/...

InformationsquelleAutor Ristogod | 2010-08-17

Schreibe einen Kommentar