6 Stimmen

WPF - Warum gibt es keine überschreibbare Methode "OnDataContextChanged"?

Das FrameworkElement-Objekt hat das DataContextChanged-Ereignis. Es gibt jedoch keine OnDataContextChanged-Methode, die überschrieben werden kann.

Irgendwelche Ideen warum?

3voto

OwenP Punkte 24128

Wenn eine Methode virtuell ist, hat der Benutzer die Möglichkeit, entweder die Grundfunktionalität zu ergänzen, indem er die Methode der Basisklasse aufruft, oder die Grundfunktionalität zu ersetzen, indem er es versäumt, die Methode der Basisklasse aufzurufen. Bei OnEvent() Methoden wird das Ereignis nicht ausgelöst, wenn Sie die Methode der Basisklasse nicht aufrufen (das ist die Verantwortung der Methode der Basisklasse). Wenn die Basisklasse im OnEvent-Methoden irgendwelche Arten von Zustandsverwaltung durchführt, bedeutet dies, dass die abgeleitete Klasse den Zustand des Objekts versehentlich ungültig machen kann, wenn der Benutzer sich entscheidet, den Aufruf der Methode der Basisklasse zu unterlassen. Die Dokumentation kann "Bitte rufen Sie immer die Methode der Basisklasse auf" spezifizieren, aber es gibt keine Möglichkeit, dies durchzusetzen.

Wenn ich ein Ereignis sehe, das keine virtuelle OnEvent()-Methode hat, gehe ich normalerweise davon aus, dass die Methode irgendeine Art von interner Zustandsverwaltung durchführt und die Designer der Klasse garantieren möchten, dass ihre Zustandsverwaltung durchgeführt wird. Dies ist nicht der Fall bei FrameworkElement, und es ist nicht das einzige Ereignis, das nicht dem Muster folgt, also bin ich neugierig, was der Grund dafür ist.

Ich habe in Reflector herumgegraben, um zu sehen, ob ich einen Grund entdecken konnte. Es gibt eine OnDataContextChanged()-Methode, aber es ist ein Handler für die Änderung von Abhängigkeitseigenschaften und folgt nicht dem standardmäßigen Ereignismuster. Dies ist wahrscheinlich der Grund, warum es nicht als protected virtual gemacht wurde. Es ist nicht standardmäßig, also wäre es verwirrend. Es ist statisch, also könnten Sie es sowieso nicht überschreiben. Da es automatisch vom Abhängigkeitseigenschaften-Framework aufgerufen wird und Sie es nicht überschreiben können, glaube ich, dass wir den Grund haben, warum es privat anstatt statisch virtual ist.

Sie könnten ein anderes Muster verwenden, um das normale Ereignismuster freizulegen:

class FrameworkElement
{
    // Unterschied: Verwenden von DataContextPropertyChanged als Änderungsrückruf
    public static readonly DependencyProperty DataContextProperty = ...

    protected virtual void OnDataContextChanged(...)
    {
        // löst das DataContextChanged-Ereignis aus
    }

    private static void DataContextPropertyChanged(...)
    {
        ((FrameworkElement)d).OnDataContextChanged(...);
    }
}

Mein Vermutung, warum sie das nicht gemacht haben? Normalerweise rufen Sie OnEvent() auf, um das Ereignis auszulösen. Das Ereignis wird automatisch ausgelöst, wenn sich DataContext ändert, und es ergibt keinen Sinn, es zu einem anderen Zeitpunkt auszulösen.

1voto

Kent Boogaart Punkte 170094

Gute Frage.

Ich rate nur, aber wenn ich in Reflector schaue, würde ich sagen, es ist nur Faulheit, vielleicht mit einer Prise (unbegründeter?) Leistungsbedenken. FrameworkElement hat einen generischen EventHandlersStore, der dafür verantwortlich ist, Ereignisinformationen (Delegaten) für eine Vielzahl von Ereignissen zu pflegen. Die Hinzufügen- und Entfernen-Logik in den CLR-Ereignissen (wie z.B. DataContextChanged) ruft einfach in den EventHandlersStore mit dem entsprechenden Schlüssel.

Es gibt eine generische RaiseDependencyPropertyChanged-Methode, die aufgerufen wird, um verschiedene Arten von Ereignissen auszulösen. Es gibt auch eine private OnDataContextChanged-Methode, die die RaiseDependencyPropertyChanged-Methode aufruft. Allerdings ist es statisch und als Teil der d-Prop-Metadaten registriert.

Also, kurz gesagt, sehe ich keinen technischen Grund, warum man keine übersteuerbare OnDataContextChanged-Methode einbeziehen sollte. Sieht für mich nur nach einer Abkürzung in der Implementierung aus.

Ist das rein akademisch, oder versuchen Sie hier etwas zu erreichen?

0voto

Simon_Weaver Punkte 129442

Silverlight-Hinweis:

Bei Silverlight Beta 4 gibt es kein DataContextChanged-Ereignis (zumindest ist es nicht öffentlich).

Der Microsoft Connect-Bug-Bericht wurde als 'behoben' markiert, aber ohne Hinweis darauf, was das tatsächlich bedeutet.

In der Zwischenzeit benötigen Sie einen Workaround wie diesen von CodeProject - der sehr einfach ist und leicht ausgetauscht werden kann, falls Microsoft das Ereignis tatsächlich öffentlich macht.

0voto

Josh Punkte 66190

Abhängigkeits Eigenschaften haben normalerweise keine entsprechenden virtuellen Methoden zum Auslösen des Ereignisses, weil erwartet wird, dass die Änderungsereignisse vom Abhängigkeits-Eigenschaften-System selbst verwaltet werden.

Was Sie jedoch überschreiben können, um Änderungen an einer Abhängigkeitseigenschaft zu behandeln, ist DependencyObject.OnPropertyChanged, wie folgt:

class MyClass : FrameworkElement {

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {
        base.OnPropertyChanged(e);
        if (e.Property == FrameworkElement.DataContextProperty) {
            // do something with e.NewValue/e.OldValue
        }
    }

}

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