Ich habe eine Basisklasse DockedToolWindow: Form und viele Klassen, die von DockedToolWindow abgeleitet sind. Ich habe eine Containerklasse, die Ereignisse zu AndockedToolWindow-Objekten enthält und zuweist, jedoch möchte ich die Ereignisse von der Kindklasse aufrufen.
Ich habe tatsächlich eine Frage darüber, wie man diese MSDN-Site implementiert > sagt mir zu tun. Dieser Abschnitt gibt mir das Problem:
%Vor%Sicher, dieses Beispiel kompiliert und funktioniert, aber wenn ich "ShapeChanged" durch "Move" ersetze (ein Ereignis, das ich von Form abgeleitet habe), sagt es falsch, dass ich Move auf der rechten Seite ohne + = oder - = nicht haben kann. Ich habe auch die generischen ShapeEventArgs-Tags entfernt.
Irgendwelche Anlässe, warum das nicht funktioniert? Was ist der Unterschied zwischen einem in der Klasse deklarierten Ereignis und einem vererbten Ereignis?
Sie können Basisklassenereignisse nicht direkt auslösen. Das ist genau der Grund, warum du deine OnShapeChanged
Methode protected
anstatt private
machen musst.
Verwenden Sie statt dessen base.OnMove () / p>
Aus der C # -Sprachspezifikation Abschnitt 10.7 (Hervorhebung hinzugefügt):
Innerhalb des Programmtextes der Klasse oder Struktur, die die Deklaration eines Ereignisses enthält, können bestimmte Ereignisse wie Felder verwendet werden . Damit ein Ereignis verwendet werden kann, darf es nicht abstrakt oder extern sein und Event-Accessor-Deklarationen nicht explizit einschließen. Ein solches Ereignis kann in jedem Kontext verwendet werden, der ein Feld zulässt. Das Feld enthält einen Delegaten (§15), der auf die Liste der Event-Handler verweist, die dem Event hinzugefügt wurden. Wenn keine Ereignishandler hinzugefügt wurden, enthält das Feld null.
Der Grund, warum Sie das Move-Ereignis nicht wie ein Feld behandeln können, ist, dass es in einem anderen Typ definiert ist (in diesem Fall Ihre Oberklasse). Ich stimme @womps Spekulationen zu, dass die Designer diese Wahl getroffen haben, um unbeabsichtigtes Affen mit dem Ereignis zu verhindern. Es scheint offensichtlich schlecht zu sein, nicht verwandte Typen (Typen, die nicht von dem Typ abgeleitet sind, der das Ereignis deklariert) dies zu tun, aber selbst für abgeleitete Typen ist es möglicherweise nicht wünschenswert. Sie hätten wahrscheinlich eine Syntax einfügen müssen, damit die Ereignisdeklaration in Bezug auf die Verwendung im Feldstil in private
oder protected
geändert werden kann. Daher rate ich, sie einfach zu deaktivieren.
Der Unterschied ist der Umfang. Innerhalb Ihrer Klasse können Sie steuern, wie Ihre Ereignisdelegaten behandelt werden. Ihre Klasse kann jedoch nicht steuern, was die Basisklasse tut. Es könnte ein paar verrückte hinter den Kulissen Sachen mit dem Ereignis und seinen Handlern tun. Wenn Sie das Move-Ereignis einfach "neu zugewiesen" hätten, würden Sie die Multicast-Delegatenliste für das Ereignis löschen.
Ich nehme an, dass sie eine Compiler-Beschränkung auf dieses Problem setzen, weil es eine sehr unsichere Vorgehensweise ist und im Prinzip jeder Nachkommenklasse die Fähigkeit geben würde, das Ereignismodell ihres Elternteils zu zerstören.
Sie benötigen nur den Code, den Sie in der Klasse gepostet haben, in der das Ereignis selbst definiert ist. Alle abgeleiteten Klassen sollten einfach OnShapeChanged () oder OnMove () aufrufen, ohne das Kopieren usw., also sollten Sie diesen Code überhaupt nicht in Ihren Klassen schreiben (da das Move-Ereignis in der Basis definiert ist).
>Wenn Sie in der abgeleiteten Klasse irgendeine Art von Verarbeitung durchführen müssen (vielleicht müssen Sie an Ihrer Erfassungsklasse herumfummeln?), überschreiben Sie den virtuellen OnXXX-Aufruf und tun es, bevor Sie base.OnXXX () aufrufen. In dem MSDN-Artikel entspricht die Circle-Klasse Ihrer DockingToolWindow-Klasse. Dasselbe Muster sollte für Ihre abgeleiteten Klassen verfügbar sein.
Tags und Links c# events base-class