Ich habe einige Geschäftsobjekte in Delphi mit einem benutzerdefinierten Schema der Datenbankpersistenz geschrieben, das endlich für meine Bedürfnisse funktioniert. Ok, großartig. Jetzt ist es Zeit für GUI-Implementierungen. Und hier beginnt die Probleme.
Wie binden Sie mein Objekt korrekt an die GUI?
Ich kann Data-Aware-Steuerelemente nicht verwenden, da ich alle Datenzugriffskomponenten in der ORM-Schicht isoliert habe, also schreibe ich einige "Object Aware" -Steuerelemente mithilfe der RTTI-Einheit (ich arbeite mit Delphi 2010), aber ich habe die Ich fühle mich in die falsche Richtung ...
Einige Vorschläge, wie Sie dies nur mithilfe der VCL-Steuerelemente beheben können?
Sie haben mehrere Muster, um ORM mit der Benutzeroberfläche zu verbinden.
Siehe zum Beispiel das Muster Model GUI Mediator . Kurz gesagt, Sie schreiben einen Beobachter, der den ORM-Inhalt in den UI-Komponenten widerspiegelt und umgekehrt. Dies wurde zum Beispiel im tiOpf-Framework für Delphi implementiert Link hat Videos).
Ein anderer Ansatz besteht darin, Ihre Daten zur Laufzeit zuzuordnen: Sie gestalten Ihr Formular wie gewohnt, dann füllen Sie den Inhalt im OnShow
-Ereignis, dann das " Speichern " oder "" OK "- Schaltfläche wird validiert und dann den Inhalt in den ORM-Datensatz speichern. Dies wird in der Hauptbeispielanwendung unseres Frameworks gemacht. Einfach zu codieren in diesem einfachen Beispiel, könnte aber zu Spaghetti-Code führen, wenn Sie viele Felder und Validierungen haben.
Der letzte Ansatz besteht darin, dass Ihr ORM das Formular erstellt.
In unserem Framework können Sie einige UI-Eigenschaften für jede Tabelle in einer dedizierten Struktur definieren. Dann erstellt eine einzelne Einheit ein Formular mit allen editierbaren Feldern Ihres ORM-Objekts. Verknüpfungen zu anderen Datensätzen werden als Kombinationsfeld angezeigt, boolesch als Kontrollkästchen, als Radioboxen usw. Dann wird die Filterung (z. B. trimmen eines Textfelds aus Leerzeichen auf der linken oder rechten Seite) und die Validierung (z. B. sicherstellen, dass ein Feldwert eindeutig oder eine gültige IP-Adresse ist) behandelt nicht im UI-Teil, sondern in der Geschäftslogik selbst, dh im ORM .
IMHO ist es notwendig, eine echte Multi-Tier-Architektur zu halten. Das heißt, die Benutzeroberfläche muss sich hauptsächlich auf die Geschäftslogik verlassen. Zum Beispiel muss die Datenvalidierung Teil des ORM sein, nicht der Benutzeroberfläche. Wenn Sie beispielsweise einen Web-Client zu Ihrer Delphi-Client-Anwendung hinzufügen, müssen Sie die Validierung nicht erneut codieren: Sie wird für beide Clients getrennt von den UI-Implementierungsdetails verwendet.
Was Sie tun könnten (obwohl ich keine Codebeispiele habe), ist eine Kombination aus
Klassenhelfer haben den Nachteil, dass sie nicht offiziell unterstützt werden und Sie können der Klasse, der Sie helfen, keine Felder hinzufügen.
Interceptor-Klassen sind einfach untergeordnete Klassen mit demselben Namen wie ihr Vorgänger:
%Vor%Sie können Interceptor-Klassen in ihre eigene Einheit einfügen und diese verwenden, wo immer Sie wollen. Stellen Sie nur sicher, dass diese Einheiten NACH der Standardeinheit enthalten sind, sodass Ihr Nachkomme zur Laufzeit verwendet wird.
Vorteil der Interceptor-Klassen:
Pseudo-Beispiel der Interceptor-Kontrolle mit Bindungsschnittstelle / Kommandoschnittstelle:
%Vor%Die Implementierung könnte wie folgt aussehen:
%Vor%Mein derzeitiger Kunde hat in der Vergangenheit (vor meiner Ankunft) eigene Mapper-Klassen erstellt. Ihre Datenobjekte haben Felder (die Objekte sind), und Sie können diese Felder einem Steuerelement zuordnen. Ich erweiterte das Framework mit einem MVC-ähnlichen Ansatz:
%Vor%Pro Steuerelement wird eine einfache "Mapping" -Klasse erstellt:
%Vor%Es gibt keine Raketenwissenschaft, und vielleicht gibt es bessere Lösungen (das hat in D6 und niedriger funktioniert :-)), aber es funktioniert gut genug für den Kunden.
Übrigens: es wird auch ein Datenobjektgenerator verwendet. Wenn sich also ein Feld in der Datenbank ändert (z. B. tarra.tarid wird in tareID geändert), erhalten wir einen Compilerfehler, weil "tarid" nicht mehr existiert. Dies funktioniert viel besser als "feste Zeichenfolge" Mapping (Laufzeitfehler).
Es gibt derzeit keine Möglichkeit, dies nur mit VCL-Steuerelementen zu tun. Ich weiß, dass Lazarus eine Reihe von RTTI-basierten datensensitiven Steuerelementen hat; Vielleicht möchten Sie sich einige Grundideen ansehen. Aber es ist schwieriger, als Sie vielleicht zuerst denken. Im Gegensatz zu einem Dataset verfügt ein Objekt beispielsweise nicht über einen integrierten Signalmechanismus, wenn sich die Werte seiner Elemente ändern. Dies bedeutet, dass, wenn Ihre Datenbindungssteuerelemente das Objekt nicht vollständig besitzen und kein anderer Zugriff darauf besteht, es möglich ist, dass ein anderer Code einen Wert ändert, und diese Änderung dann nicht in der Benutzeroberfläche angezeigt wird.
Ich habe in den letzten Jahren verschiedene Dinge aus dem Delphi-Team gehört, die das Objektmodell oder das RTTI-Modell erweitert haben, um eine bessere Datenbindung zu ermöglichen, aber was auch immer das ist, ist noch ein paar Jahre.
Schauen Sie sich EverClassy Dataset im Ссылка an. Es kann Ihre Bedürfnisse erfüllen. EverClassy Dataset ist ein Delphi-Dataset, das von Objekten anstelle von Datensätzen aus einem Datenbanksystem befüllt wird.
Mit dieser Komponente haben Sie die Möglichkeit, Ihre Domain-Objekte mit Dataware-Komponenten zu interagieren, was Ihnen große Möglichkeiten beim Erstellen Ihrer GUI geben wird.
Tags und Links user-interface delphi oop