![]() |
Delphi-Version: 10.4 Sydney
Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Hallo zusammen,
um es gleich vorweg zunehmen, ich kenne mich mit TAction, Events, etc. aus und weiss damit umzugehen. Weil ich mal wieder darüber gestolpert bin: Was ich nicht verstehe ist warum die Events in Controls nicht nur via Benutzereingaben gefeuert werden ? Z.B. eine Checkbox in FMX feuert auch den OnChange Event wenn man Checkbox.IsChecked ändert. Das kann zu üblen Seiteneffekten führen, und ich würde das Feuern per Code eigentlich generell immer abschalten. Das heisst: Control --> geändert durch Eingabe --> Events sollen feuern (OK) Control --> geändert per Runtime Code --> Events sollen NICHT feuern (das tun sie aber doch) Änderungen per Code sollten doch zur Konfiguration der Controls nutzbar sein, ohne gleich alle möglichen Seiteneffekte zu triggern. Was ich gerne wissen möchte ist, ob hinter diesem aktuellen Verhalten vielleicht ein größeres Konzept oder Pattern steht, und warum das direkte Feuern per Code womöglich doch Sinn machen könnte ? Vielleicht in einem M(V/P)M Konzept könnte das Feuern Sinn machen, obwohl ich das auch nicht unbedingt sehen kann. Auch hier sehe ich sinnvollerweise zwei Schichten: 1. die Änderung via Code und 2. das Triggern von Events wenn modified, bei Bedarf. Warum wurde das Framework so designed dass dieses direkte Feuern per Code kommt ? |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Ich denke mal, das wurde so implementiert, weil es auch in der VCL so ist. Dort ist es so, weil es eine Windows Control ist, welche sich so verhält. Und um es dem eingefleischten Delphi-Entwickler leichter zu machen, wurde das Verhalten so übernommen.
...:cat:... |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Ja schon, könnte sein.
Aber gibt es dafür nicht irgendein übergeordnetes Konzept oder Design-Pattern ? |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Die FMX Checkbox ist ein denkbar schlechtes Beispiel, denn genau die ist bei den angesprochenen Events genau richtig:
- OnClick - wenn der Nutzer drauf klickt - OnChange - wenn sich der Wert ändert, egal ob durch UI Interaktion oder Code - OnExecute einer zugewiesenen TAction hängt sich an das OnClick Dahingehend ist die VCL Checkbox eine Katastrophe, denn dort sind Anklicken und Wert ändern miteinander verwurschtelt und beides Triggert OnClick |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
In der VCL wird beim
Delphi-Quellcode:
sogar ein OnClick ausgelöst. (das arbeitet dort wie ein OnChange, was es nicht gibt)
MyCheckBox.Checked := True;
Da wir eh alle Komponenten immer abgeleitet haben, konnen wir hier an zentraler Stelle ein CheckedNoClick einbauen, wo bei Zuweisung kurz das Event abgehängt wird. |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Zitat:
Aber macht es überhaupt Sinn das Triggern durch den Code ? Ist das jetzt Gut oder Schlecht das es triggert ? Zitat:
hier z.B.
Delphi-Quellcode:
Weil ich dann immer diese doppelten Properties habe denke ich, sollte ich nicht so ändern:
//1.
Checkbox.IsChecked := xxx; // Standard, immer OnChange Checkbox.IsChecked_Quiet := xxx; // Neu: immer Silent
Delphi-Quellcode:
Wohlgemerkt das ist jetzt nur ein Beispeil (Checkbox), das zieht sich aber durch alle Komponenten.
//2.
Checkbox.IsChecked := xxx; // Geändert, immer Silent Checkbox.IsChecked_Notify := xxx; // Neu: immer OnChange (wie altes Verhalten) Macht es Sinn das für alle Komponenten anzupassen, so dass das Verhalten wie 2. ist ? |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Zitat:
Delphi-Quellcode:
, von dem z.B.
TButtonControl
Delphi-Quellcode:
,
TButton
Delphi-Quellcode:
und
TCheckBox
Delphi-Quellcode:
abgeleitet sind, hat ein protected Property
TRadioButton
Delphi-Quellcode:
, mit dem man das verhindern kann.
ClicksDisabled
|
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Zitat:
Deshalb möchte ich ja generell diese Events per code abschalten, was spräche dagegen ? Umgekehrt, wenn ich was triggern möchte dann muss ich das bewusst tun. |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Als ich mal Controls erstellt habe, hatte ich die Properties normal mit Gettern (_get_Xyz) und Settern (_set_Xyz) incl. Benachrichtigungen erstellt und zusätzlich eine Methode SetXyz(Value...) bereitgestellt für stille Änderungen und Initialisierungen.
|
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Hey, das war doch nur ein Beispiel aus einem uralten Programm, welches noch Altlasten von vor 25 mitschleppt
und was auch über Tastatur bedienbar sein soll und, wo man von Userseite bei der Leertaste denoch das OnClick haben will, trots Delphi XE, DevExpress und ein paar Win10 im Win2000-Look. :stupid: Vielleicht vermutlich eventuell komm ich dieses ja mal dazu unser Programm auf 10.x zu migrieren. 73 EXE/DLL/BPL, 475 inkl. Fremdkomponenten und 557 eigene PAS ... da braucht es einfache zentrale Lösungen. Vor paar Jahren hatte ich schonmal von D7 auf XE und ein Vorgänger von TurboPascal zu Delphi. Und natürlich muß sich das Programm für die alten Hasen noch genauso mit Tastatur bedienen lassen, wie damals im DOS. Auch neue Eingabefelder sollten den "eingeschleiften" Workflow nicht verändern, aber dennoch sollen zugleich auch aktuellere Gestaltungsmittel Einzug finden usw. |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Ja also, dann liege ich ja nicht falsch wenn ich das stille Senden grundsätzlich Abschalten würde.
Ich sehe auch keinen echten Grund wo ich das unbedingt brauchen würde. So hätte man zumindest ein konsistentes System, und müsste sich darüber gar keine Gedanken mehr machen. .. und versehentliche Seiteneffekte fallen weg .. |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Zitat:
Bei einer TCheckBox werden damit ja sowohl der OnChange- als auch der OnClick-Event verhindert. Einfach das OnClick abhängen reicht aber auch nicht immer. Bei letzterem kann es sich ja auch um das OnExecute einer TAction handeln. Dann würde das temporäre entfernen des Events gar nichts bringen, da der ActionLink immer noch vorhanden ist. |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Jupp, ich hab hier auch gern ein Konsistentes Verhalten, egal ob Benutzer oder das Programm was ändert.
Ausnahme: * beim Laden von Daten, wo sich zwar der inhalt des Controls ändert, aber die Daten sich eigentlich nicht geändert haben * und bei wechselseitigen Synchronisierungen, wo das OnChange eine Reaktion auslöst, was aber keine Endlosschleife erzeugen soll |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Zitat:
Delphi-Quellcode:
erwarten, das schaltet die Events aber auch nicht ab.
Checkbox.BeginUpdate;
try Checkbox.IsChecked := xxx; finally Checkbox.EndUpdate; end; |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Nein, dies schaltet nur vorübergehend das Aktualisieren ab (Zugriff und Auslesen der Daten durch Oberflächenelemente) und im EndUpdate wird dann alles gemacht, was zwischendurch übersprungen wurde.
|
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Ich hatte die Lösung von DevExpress nicht sehr geliebt (setzt ich schomn ein paar Jahre nicht mehr aktiv ein).
Die haben ja eine Art Zwischenschicht bei den Controls eingebaut wenn ich mich recht erinnere, über die alle möglichen Properties gesteuert werden können. Mittlerweile sehe ich das gar nicht mehr als so umständlich an. Ein neues Property in allen Control, über das in konsistenter Weise das Control bedient wird. Also sowas wie
Delphi-Quellcode:
Das würde ermöglichen das alte System und das neue System parallel zu betreiben,
Checkbox.Conf.IsChecked := xxx;
und damit einen schrittweisen Umstieg auf ein neues Konzept ermöglichen, ohne viel Kopfzerbrechen :stupid: Womöglich auch eine gute Basis um damit ein MVVM System neu anzudenken ... |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Teilweise hab ich inzwischen ein paar neue Property, welche blos den Zugriff etwas umbiegen, nur noch ClassHelper drangehängt.
Es gibt noch ein paar wenige Oberflächen, wo die Basiskomponenten verwendet werden ... teilweise mit Absicht, aber so ist Dieses dann auch dort verfügbar. Zitat:
* TdxEdit ist nur ein Container und drin ist erst das TInnerEdit * theoretisch könnten so auch in den Grids und Trees somit beim Colum-Editor die "selben" InnerEdits verwendet werden * und wenn man nun eine Erweiterung für das InnerEdit machen täte, würden überall in Edits, Grids, TreeViews, ComboBoxen usw. diese drin sein * praktisch ist das nicht so und an vielen Stellen nervt es nur noch * auch dass viele der Komponenten tausendfach abgeleitet und in hunderten Subkomponenten verteilt sind, aber an anderen Stellen für viele Komponenden der selbe Code mehrmals als ungleiche Kopie drin steckt |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
ClassHelper reichen bei mir nicht immer (oder immer seltener).
Ich benutze oft Interposer um die Funktionalität der Basiskomponenten zu ergänzen. Ich denke das man eine ganze Menge der "Unschönheiten" von Label, Button, Tree, Grid, etc. kapseln kann, und in ein einheitliches Konzept giessen. Ganz neben bei erschlägt man damit auch noch Bugfixes und Workarounds auf den verschiedenen Platformen. Ein einheitliches Interface, auf notwendigste glattgebügelt und einheitliches UI und Verhalten, so das ein solches "Interface" womöglich sogar einheitlich abgeleitet werden kann und damit von Label bis Grid über Planner abdecken könnte. (Thema warum heisst es Caption statt Text, etc.) Das Ganze funktioniert von FMX über VCL bis LCL, alles vereinheitlicht und kompatibel (wäre schon, der Teufel liegt aber im Detail). Ok, ich habe mit das TMS FNC noch nicht näher genauer angesehen, aber ich denke das die das auch so ähnlich machen. Nur benutzen die dann immer eigene "FNC"-Komponenten, das möchte ich aber nicht. Ich schau mal wie weit man kommt :stupid: |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Zitat:
Überall wo es Caption heißt, gibt es protected auch das Text und Beides geht auf's Selbe. Fazit: Du kannst in der VCL fast alle Komponenten ab TWinControl nach TEdit casten, um den "Text" zu ändern oder auszulesen.
Delphi-Quellcode:
geht bei Label, TStaticText, ComboBox, GroupBox, TForm usw. und natürlich TEdit (alles was WM_SETTEXT benutzt)
TEdit(xxx).Text := 'abc';
Viel mehr nervt mich dass Caption ein TCaption ist und da das mit der Vererbung bei ClassHalper so garnicht funktioniert, fehlt dort dann der ganze StringsHelper dran. |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Ok, dann wenn Dir das Caption-Beispiel nicht gefällt, dann eben "Top, Left" statt "Position.X/Y" ...
Du weisst was ich meine. Was Du beschreibst ist nur ein Teil von dem wo ich mir eine saubere Lösung vorstelle, durch ein erweitertes API. Ich denke aber das ursprüngliche Thema ist damit erledigt, da gibt es wohl keinen "großen Wurf" hinter dem Event-System der VCL/FMX. |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Achso, das zwischen VCL und FMX .... nicht nur Dinge die in einem der Beiden schon inkonsequent sind. :lol:
Joar, man wollte da bissl alten Mist der VCL "aufräumen", aber das leider nicht konsequent und vor allem nicht einheitlich, mal alles nochmal gut überdacht. Noch "besser" als Top/Left (VCL) statt Position.X/Y (FMX) finde ich Position.X und Position.Y aber Width und Height, beides im FMX. :wall: |
AW: Design Konzept/Pattern hinter TAction, Events, Controls mit Seiteneffekten ?
Auf CodingBott stelle ich übrigens die VCL TActionList und TAction vor:
![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz