![]() |
[XE2] Live Bindings
Hallo zusammen,
gibt es irgendwo eine halbwegs sinnvolle Dokumentation der Live-Bindings? Die Dokumentation im docwiki von Embarcadero ist - vorsichtig ausgedrückt - arg übersichtlich. Zu TBindList beschränkt sich die Doku auf einen Satz "TBindList and TBindGridList are used to populate a list or grid.". Da wäre ich persönlich nie drauf gekommen. :roll: In sämtlichen Samples (die ich dank docwiki und anschließendem SVN Update des Samples Ordner gefunden habe) wird das immer in Verbindung mit TBindScopeDB genutzt. Da ich nun aber keine Datasets verwende, wollte ich schauen ob ich da nicht auch TBindScope verwenden kann. Die Hilfe hilft nicht wirklich weiter, statt dessen wird statt gar keinem Text lieber mal die Beschreibung von TComponent angezeigt. Bleibt also der Blick in den Source-Code. Und damit komme ich zur eigentlichen Frage: Hab ich was übersehen oder kann ich via Live-Binding keine TObjectList<T> an VCL-Controls binden? |
AW: [XE2] Live Bindings
|
AW: [XE2] Live Bindings
Der Post von Stevie (Delphi Sorcery) bezieht sich auf das DSharp-Databinding. Ich versuche mich nur gerade zwischen Live-Bindings (Vorteil: "offiziell", Expression-Engine) und DSharp (Vorteil: näher an dem was ich eigentlich suche) zu entscheiden ;)
Ich muss aber beim Live-Binding doch den Scope angeben. Und da finde ich nicht wirklich was an Doku. Also beispielsweise: Welche Interfaces muss die Listenklasse erfüllen etc. |
AW: [XE2] Live Bindings
Bezüglich der Expression Engine - DSharp Bindings werden in Zukunft (soom (tm)) eine Integration mit
![]() |
AW: [XE2] Live Bindings
Nice. Dann wäre das ja auch geklärt 8-)
|
AW: [XE2] Live Bindings
Hab gerade eine erste Version commited - designtime Unterstützung gibt's noch keine.
Daher muss man vorerst noch einiges im Code machen. In zukünftigen Versionen wird man es ähnlich wie bei den LiveBindings im Designer einstellen können. Hier ein kurzer Beispiel Code:
Delphi-Quellcode:
uses
DSharp.Core.DataConversion.Expressions, DSharp.DelphiWebScript.Expression; procedure TForm1.FormCreate(Sender: TObject); var bind: TBinding; conv: TExpressionConverter; expr: TDelphiWebScriptExpression; begin conv := TExpressionConverter.Create; expr := TDelphiWebScriptExpression.Create; expr.Text := 'UpperCase(Edit1.Text)'; expr.BindObject(Edit1); conv.TargetToSourceExpression := expr; bind := TBinding.Create(Label1, 'Caption', Edit1, 'Text', bmOneWayToSource, conv); end; |
AW: [XE2] Live Bindings
Stevie, wie löst du das Dependency-Tacking?
Ich meine, wenn mein Ausdruck von 3 Properties eines Objektes und 2 weiteren eines anderen abhängt, müsste sie ja dann neu evaluiert werden, wenn sich mind. eine davon ändert. (In deinem Fall der Text von einer TextBox) Und das auch noch mit einer Verzögerung von X Millisekunden. Sodass du nur ein Refresh machst, wenn sich 10 Eigenschaften ändern. Databinding ohne autom. nur das zu aktualisieren, was auch geändert werden muss, bringt glaube ich für komplexe Systeme nicht viel bis gar nix. Die Perf-Kosten immer alles zu aktualisieren, oder der Verwaltungsaufwand um zu entscheiden was wann aktualisiert werden muss, würde ja den Aufwand eines Projektes mind. auf die Ebene bringen, die man ohne DataBinding hätte. In Delphi sollte man sich ja in die Published-Properties klinken können, wenn ich mich nicht irre. Die Frage ist nur, ob du alle lesenden Zugriffe bemerkst. Mir fällt da gerade was ein, aber da würde ich dich dann im jeweiligen DataBinding-Thread zu nerven. ;-) |
AW: [XE2] Live Bindings
Für das Aktualisieren der Bindings ist das INotifyPropertyChanged interface zuständig. Wenn ein an das Binding angeschlossenes Object (Source oder Target) dieses interface implementiert klinkt sich das Binding dort ein. Bei allen allen Änderungen musst du das Aktualisieren manuell antriggern. Für die ScriptExpressions gibt es bisher garkeinen Automatismus - das wäre auch extrem schwierig, weil ich eigentlich ja nur ein Delphi Object in das Script bekannt mache. Damit kannst du im Script eigentlich nahezu alles anstellen, was du willst (und soweit die RTTI reicht, über die es dort angesprochen wird - mehr Infos dazu wird Eric Grange wissen). D.h. woher soll die Delphi Seite wissen, ob und wann es was triggern muss, da es ja nix vom Inhalt des Scripts kennt. Wenn man lustig sein will, kann man die Script Expressions auch für seine komplette Business Logik nutzen.
Verzögerte Aktualisierung ist nicht unterstützt - halte ich auch bisher nicht für notwendig. Bindings sind für den Transport von Informationen aus der GUI in andere Layer. Da sollten keine großartigen Berechnungen durchgeführt werden. Und falls das doch notwendig ist, gibt es immer noch die Möglichkeit, den UpdateTrigger des Bindings auf LostFocus oder Explicit zu setzen. In dem Beispiel, was ich oben gepostet habe, triggert also das Binding immer, wenn ich im Edit etwas ändere. Ob die Script expression etwas komplett anderes in das Label schreibt, was überhaupt nix mit dem Edit1.Text zu tun hat, ist dann eine andere Sache und es wird auch nicht getriggert, wenn sich irgendwas im Script verwendetes ändert. |
AW: [XE2] Live Bindings
Hauptsächlich wird das ja denke ich auch für die Formatierungen oder simple Wertableitungen verwendet werden.
|
AW: [XE2] Live Bindings
Zitat:
|
AW: [XE2] Live Bindings
Zitat:
Delphi-Quellcode:
deklariert sein, TInterfacedObject z.B. gibt einen RTTI- Fehler.
class(TInterfacedPersistent, INotifyPropertyChanged)
|
AW: [XE2] Live Bindings
Zitat:
|
AW: [XE2] Live Bindings
Zitat:
BTW, bist Du schon mit dem StringGrid-DataBinding einen Schritt weiter? |
AW: [XE2] Live Bindings
Zitat:
Zitat:
|
AW: [XE2] Live Bindings
Zitat:
|
AW: [XE2] Live Bindings
Zitat:
|
AW: [XE2] Live Bindings
Zitat:
Delphi-Quellcode:
procedure Test(i: IInterface);
begin end; var o: TInterfacedObject; begin o := TInterfacedObject.Create; Test(o); // Objekt wurde freigegeben, da RefCount auf Null gesunken ist end; |
AW: [XE2] Live Bindings
Vielleicht sollte man den Aufruf korrekt durchführen?
Delphi-Quellcode:
procedure Test(i: IInterface);
begin end; var o: TInterfacedObject; begin o := TInterfacedObject.Create; Test(o as IInterface); //<- RefCount wird automatisch erhöht //Objekt "lebt" noch! end; |
AW: [XE2] Live Bindings
Das mag zwar das korrekte Ergebnis liefern, ist aber extremst unintuitiv.
|
AW: [XE2] Live Bindings
Eine korrekte Programmierung ist "extremst unintuitiv" und eine falsche Handhabung führt zur Schlußfolgerung "Ich dachte, das sei allgemein bekannt, dass man Objekte und referenzgezählte Interfaces nicht vermischen sollte. Das ist der Preis der non GC Sprache."
:gruebel: Ich habe den Eindruck, daß einige Leute gar nicht mehr ohne "Compiler-Magie" leben können und wenn diese mal versagt, kommt gleich das große Gezetere und der Hinweis darauf, wie toll das andere Sprachen hinbekommen... :lol: |
AW: [XE2] Live Bindings
Zitat:
![]() Zitat:
|
AW: [XE2] Live Bindings
Stevie,
ich fasse das einmal zusammen:
Zitat:
Zitat:
Vielen Dank für diese eindrucksvolle Demonstration Deiner Fachkenntnisse und deiner Überheblichkeit. :thumb: :lol: |
AW: [XE2] Live Bindings
So, jetzt entspannen wir uns alle erst mal.
Ich finde es durchaus unintuitiv (von mir aus auch nervig und fehlerträchtig, wenn die Wörter besser passen sollten) wenn ein Objekt einer Klasse explizit in ein Interface gecastet werden muss, obwohl die Klasse ansich das Interface bereits bestätigt hat. Der korrekte Weg ist es sicher, aber gefallen muss es mir deshalb ja noch nicht ;) Und die Menge der Threads und Blog-Posts zu diesem Thema zeigt imho durchaus, dass es unintuitiv ist. |
AW: [XE2] Live Bindings
Der erste, der in diesem Thread "überheblich" daher kam (was ich im übrigens nicht so aufgefasst habe, ich bin da relativ unempfindlich), warst du mit folgender Aussage:
Zitat:
Außerdem war mein Beispiel das Minimalste, um zu zeigen, was passiert, wenn man Objektreferenz und Interface Referenz vermischt - und ich bin davon ausgegangen, dass man das auf ein komplexeres Szenario (Objekt wird außerhalb dieser Routine weiterverwendet) abstrahieren kann. Eventuell überzeugt dich ![]() ![]() ![]() Falls das Erklären dieses fundierten Sachverhalts als Überheblichkeit missinterpretiert werden konnte, entschuldige ich mich dafür. |
AW: [XE2] Live Bindings
Ich hab da mal eine mehr praxisorientierte Frage: Wie führe ich eigene Methoden und Konverter sinnvoll ein und wie konfiguriere ich diese, dass sie in der Topologie Vorrang haben?
Beispielsweise habe ich ein Edit an eine Property eines anderen Controls gebunden. Wird er Inhalt des Edits gelöscht und ein Notify ausgeführt, so knallt es natürlich mit einem EConversionError, weil ja folgendes passiert:
Delphi-Quellcode:
Ich könnte das natürlich ganz oben beim Notifier individuell abfangen, nur brauche ich dann keine LiveBindings mehr ;)
StrToInt('')
|
AW: [XE2] Live Bindings
DSharp hat durch einige Hilfsmethoden für TValue Konvertierungen für nahezu alle Standard Typen.
Bei den LiveBindings würde ich an dieser Stelle StrToIntDef benutzen. |
AW: [XE2] Live Bindings
Spassvogel ;) D# ist ja bestimmt toll, aber mir geht es um XE2 (wie ja im Titel auch steht). Dass ich StrToIntDef benutzen sollte ist mir auch klar. Nur nicht wie ich das in das Binding reinbekomme. Und wie ich es in der Topologie steuere damit die richtige Methode verwendet wird.
|
AW: [XE2] Live Bindings
Also wenn ich über ne TBindExpression nen Edit und ne SpinEdit verbinde, brauch ich garnix konvertieren, wenn das Edit leer ist, wird 0 ins SpinEdit geschrieben (XE2 Update 1).
P.S. Für dich dürfte System.Bindings.Outputs.RegisterBasicOutputConvert ers interessant zum Anschauen sein. Dort werden die ganzen Default Converter gebaut. |
AW: [XE2] Live Bindings
Ich habe ein TLabel.Top an TSpinEdit.Value gebunden. Wenn ich den Spinedit-Inhalt dann mit Entf komplett lösche, gibt es intern eine Exception. Die wird natürlich nur angezeigt wenn ich debugge... Funktional ist alles in Ordnung, das Top hat dann 0. Jetz tstell ich mir mal vor ich teste eine Anwendung wo ALLES nur noch über Livebindings läüft - das wird dann richtig eklig.
Code:
Und meine weitere Frage war ja, wie ich eigene Methoden da reinbekomme. [edit]Ich gucks mal an. Auf die embwiki kann ich ja wahrscheinlich noch etwas warten[/edit]
7c812afb kernel32.RaiseException + 0x52
System.SysUtils.ConvertErrorFmt($40FAB0,(...)) System.SysUtils.StrToInt(???) Vcl.Samples.Spin.TSpinEdit.GetValue System.Rtti.RawInvoke(???,???) System.Rtti.Invoke($66BFA0,((($66AAEC, Pointer($67A878) as IValueData, 112, 51824, 27249264, $19FCA70, TClass($19FCA70), 112, -13712, 27249264, 5,86978591229431e-38, 1,34629252168586e-316, 0,00000000009933e-4933, 27249264, 2724,9264, 27249264, 27249264, ($19FCA70, nil), $19FCA70))),???,$4010A0,False) System.Rtti.TRttiInstanceProperty.DoGetValue(???) System.Rtti.TRttiProperty.GetValue(???) |
AW: [XE2] Live Bindings
etwas OT:
Zitat:
EDIT: Aber Dein genanntes Problem dürfte sich auf das SpinEdit beschränken - oder? Sonst hört sich das Binding ja ganz gut an. Vielleicht solltest Du für den ernsthaften Einsatz ein NullabelSpinEdit ableiten, das diesen Fehler intern vermeidet. |
AW: [XE2] Live Bindings
Also ich finde die Bindings auch sehr interessant. Fragt sich wie dann mit DB-Bindings und Performance aussieht. Ich habe mal das Notify nahezu komplett debugged - da werden ja für ein Binding gefühlte 10.000 Zeilen Sourcecode durchlaufen bis er beim RTTI ankommt.
|
AW: [XE2] Live Bindings
Na ja, je komfortabler und flexibler ein Framework zu benutzen ist, um so mehr muss dieses ja auch selbst durchführen und berücksichtigen. Das sieht man ja auch schon an der Benutzung der RTTI.
Und wenn man ein Observer-Pattern o.ä. selbst realisiert erzeugt das ja auch einigen Code, der abgearbeitet werden muss. Ich wäre da bezüglich der Perfomance nicht so pessimistisch. Aber Du kannst ja mal dynamisch 100 Controls erzeugen und verbinden... (und vor allem Dein D7 im Profil ersetzen ;-)) EDIT: Da stellt sich mir noch die Frage, wie Controls bei LiveBinding reagieren, die sich in geschlossenen Formularen oder ausgeblendeten TabSheets o.ä. befinden. Befassen dies sich mit der Werteaktualisierung? In meiner Lösung werden die Controls nur auf invalidate gesetzt und holen sich die neuen Werte, wenn sie neu gezeichnet werden. Das heißt, nicht sichtbare Controls kümmern sich nicht um neue Daten. |
AW: [XE2] Live Bindings
Zitat:
|
AW: [XE2] Live Bindings
Das Problem hat überhaupt nix mit Bindings zu tun sondern mit dem schrottigen TSpinEdit (nicht umsonst befindet sich diese Komponente unter Samples). Schau dir GetValue an und du weißt, warum dort ne Exception kommt, wenn der Text leer ist. Nur der Author selber weiß wahrscheinlich, warum er dort nicht StrToIntDef benutzt hat (vielleicht gabs das damals noch nicht). Dieser Fehler würde auch kommen, wenn du im OnChange ganz einfach
Delphi-Quellcode:
geschrieben hättest.
Label1.Top := SpinEdit1.Value
Nachtrag: Die Exception wird sogar geraised, wenn du einfach den Text im SpinEdit löschst und dann mit Pfeil hoch oder runter änderst. (GetValue wird getriggert) |
AW: [XE2] Live Bindings
Ich hab das
![]() |
AW: [XE2] Live Bindings
Zitat:
|
AW: [XE2] Live Bindings
Hab mal nen
![]() |
AW: [XE2] Live Bindings
... wobei es da vielleicht doch logischer wäre, auf einen Leerstring zu prüfen und dann MinValue zuzuweisen. Wenn jedoch "Müller" eingegeben wird, macht eine "ordentliche" Exception ja schon Sinn...
(soll aber zu dem Thema dann auch wieder reichen) |
AW: [XE2] Live Bindings
Zitat:
|
AW: [XE2] Live Bindings
Ich hab jetzt mal einen simplen Performancetest mit Bindung eines Label an ein Edit gemacht. Erwartungsgemäß ist das LiveBinding ca. 60 mal langsamer als eine direkte Zuweisung der Eigenschaften. Keine schlechte Leistung, wenn man bedenkt wieviel Code dafür durchlaufen wird.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 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 by Thomas Breitkreuz