2009-08-18 5 views
4

Das Objekt FrameworkElement hat DataContextChanged Ereignis. Es gibt jedoch keine OnDataContextChanged Methode, die überschrieben werden kann.WPF - Warum gibt es keine überschreibbare "OnDataContextChanged" -Methode?

Irgendwelche Ideen warum?

+0

Warum müssen Sie es außer Kraft zu setzen? Können Sie nicht nur darauf warten, dass das DataContextChanged-Ereignis ausgelöst wird? – sisve

+0

Nun, das ist, was ich schließlich getan habe. Ich bin jedoch neugierig auf den Grund für das Fehlen dieser Methode. – Elad

Antwort

2

Wenn eine Methode virtuell ist, hat der Benutzer die Option, entweder die Basisfunktionalität durch Aufrufen der Basisklassenmethode zu erweitern oder die Basisklassenfunktionalität zu ersetzen, indem die Basisklassenmethode nicht aufgerufen wird. Bei OnEvent() - Methoden wird das Ereignis nicht ausgelöst, wenn Sie die Basisklassenmethode nicht aufrufen (dafür ist die Basisklassenmethode verantwortlich.) Wenn die Basisklasse innerhalb der OnEvent-Methode eine Art von Statusverwaltung ausführt, Dies bedeutet, dass die abgeleitete Klasse den Status des Objekts versehentlich ungültig machen kann, wenn der Benutzer einen Aufruf der Basisklassenmethode auslässt. Die Dokumentation kann angeben: "Bitte rufen Sie immer die Basisklassenmethode auf", aber es gibt keine Möglichkeit, sie 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 ausführt und die Designer der Klasse ihre Zustandsverwaltung garantieren wollen. Dies ist nicht der Fall in FrameworkElement, und es ist nicht das einzige Ereignis, das nicht dem Muster folgt, also bin ich neugierig, was die Argumentation ist.

Ich grub mich in Reflector um zu sehen, ob ich einen Grund entdecken könnte. Dort ist eine OnDataContextChanged() -Methode, aber es ist eine Abhängigkeitseigenschaft Änderung Handler und folgt nicht dem Standard-Ereignismuster. Dies ist wahrscheinlich der Grund dafür, es nicht virtuell zu schützen. Es ist nicht Standard, also wäre es verwirrend. Es ist statisch, also könnten Sie es sowieso nicht überschreiben. Da es automatisch vom Abhängigkeitseigenschaftsframework aufgerufen wird und Sie es nicht überschreiben können, glaube ich, dass wir den Grund haben, warum es privat statt statisch virtuell ist.

Sie könnten ein anderes Muster verwenden, um die normalen Ereignismuster zu entlarven:

class FrameworkElement 
{ 
    // difference: use DataContextPropertyChanged as the change callback 
    public static readonly DependencyProperty DataContextProperty = ... 

    protected virtual void OnDataContextChanged(...) 
    { 
     // raise the DataContextChanged event 
    } 

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

Meine Vermutung, warum sie dies nicht getan? Normalerweise rufen Sie OnEvent() auf, um das Ereignis auszulösen. Das Ereignis wird automatisch ausgelöst, wenn sich DataContext ändert, und es ist nicht sinnvoll, es zu einem anderen Zeitpunkt zu erhöhen.

+0

Es gibt keinen Grund, warum das statische OnDataContextChanged-Ereignis ein nicht statisches OnDataContextChanged-Ereignis nicht aufrufen konnte. Sie würden umbenennen, um die Dinge natürlich klarer zu machen. Die Bereitstellung einer überschreibbaren OnXxx-Methode ist Standard-.NET-Praxis. Zugegeben, es gibt Fallstricke, wie du es erwähnst, aber es gibt auch Abschwächungen und eine gewisse Menge von Problemen beim Entwickler, um zu wissen, was sie tun. –

+0

Das ist gültig, beantwortet aber nicht die Frage "Wann ist es für einen Benutzer sinnvoll, das Ereignis auslösen zu können?" Wenn die Methode geschützt ist, kann sie ausgelöst werden, wenn der Benutzer dies wünscht. Uns fehlen einige Informationen: Es ist möglich, dass dieses Ereignis von vielen internen WPF-Klassen auf eine Art und Weise genutzt wird, die nicht öffentlich bekannt ist, und dass der Benutzer das Verhalten in irgendeiner Weise ändern kann. – OwenP

1

Gute Frage.

Ich rate nur, aber in Reflector würde ich sagen, es ist nur Faulheit, vielleicht mit einer Prise (unbegründet?) Performance-Bedenken. FrameworkElement hat eine generische EventHandlersStore, die für die Verwaltung von Ereignisinformationen (Delegaten) für eine ganze Reihe von Ereignissen zuständig ist. Die Hinzufügen und Entfernen Logik in den CLR-Ereignissen (wie DataContextChanged) einfach Anruf in die EventHandlersStore mit dem entsprechenden Schlüssel.

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

Also, kurz gesagt, sehe ich keinen technischen Grund, eine überschreibbare OnDataContextChanged Methode nicht zu enthalten. Sieht für mich wie eine Abkürzung in der Umsetzung aus.

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

+0

Ehrlich gesagt fragte ich mich einfach, ob es eine Logik dahinter gibt. Es ergab auch keinen Sinn für mich. Die Registrierung bei den Veranstaltungen ist genauso gut für meine Bedürfnisse. Vielen Dank für die tolle Antwort! – Elad

0

Silverlight Hinweis:

Bei der Silverlight Beta 4 gibt es keine DataContextChanged Veranstaltung (auch seine nicht öffentlich zumindest).

Die Microsoft Connect bug report wurde als "Fixed" markiert, aber ohne Angabe dessen, was das eigentlich bedeutet.

In der Zwischenzeit benötigen Sie eine Problemumgehung wie this one from CodeProject - die sehr einfach ist und sollte leicht zu wechseln, wenn Microsoft das Ereignis tatsächlich öffentlich macht.

0

Abhängigkeitseigenschaften verfügen normalerweise nicht über entsprechende virtuelle Methoden zum Auslösen des Ereignisses, da erwartet wird, dass die Änderungsereignisse vom Abhängigkeiteneigenschaftssystem selbst verwaltet werden.

Was Sie jedoch außer Kraft setzen kann, wird DependencyObject.OnPropertyChanged wie so jede Abhängigkeitseigenschaft Wechsel zu handhaben:

class MyClass : FrameworkElement { 

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

} 
+1

Bälle! Ich habe es wieder getan und auf eine wirklich alte Frage geantwortet, die auf der Titelseite aufgetaucht ist. Grrr .... – Josh

Verwandte Themen