![]() |
FireMonkey ohne LiveBinding?
LiveBinding ist aus meiner Sicht ein schlechter Ansatz und vor allem derzeit viel zu Fehlerbehaftet.
Selbst die Emba-Demos funktionieren nicht. Aus meiner Sicht ist das nicht produktiv einsetzbar. (Würde mich gern vom Gegenteil überzeugen lassen.) DSharp unterstützt (noch) keine Grids. FireMonkey möchte ich gerne nutzen, jedenfalls mal intensiver anschauen. Besonders reizt mich das TMSFMGrid. Die Daten muss man dann eben von Hand (z.B. aus einem SQLDataSet) zuweisen. Das habe ich im Grunde auch schon fertig. Die Zellen kann man entsprechend von Hand (oder abhängig vom Feldtyp) formatieren und kann mit dem Grid danach normal arbeiten. Wie löst man dann aber am besten das Zurückschreiben der Zellendaten in die Datenbank? Es könnten ja Zeilen gelöscht oder hinzu gefügt worden sein. Während der Arbeit im Grid gibt es ja dann keinen Bezug zur Datenbank. Entsprechend gibt es keinen angebundenen Navigator und keine Statusänderung in der DB. Wie ist der beste Ansatz? |
AW: FireMonkey ohne LiveBinding?
Eine ehrliche (sehr persönliche) Meinung?
Auf das zurückgreifen was ausgereift ist ... |
AW: FireMonkey ohne LiveBinding?
Zitat:
|
AW: FireMonkey ohne LiveBinding?
Turbo Pascal
tut mir leid, ich konnte ncht andes Nja, aktuell meint er wol die (alte) VCL oder doch C++, bzw C# :gruebel: |
AW: FireMonkey ohne LiveBinding?
Bummi meint (wie ich ihn kenne) die VCL und klassische DB-Komponenten.
Das ist ja auch nicht falsch. Aktuell habe ich aber kein Terminprojekt zu realisieren :? und somit Zeit für neues... Also Meinungen zum Daten schaufeln sind noch willkommen... |
AW: FireMonkey ohne LiveBinding?
Zitat:
DSharp unterstützt den VirtualTreeview (vielfach als Grid benutzt), das TStringGrid (brrr, wer benutzt das freiwillig?), DevExpress Quantum Grid und TreeList, TMS AdvGrid |
AW: FireMonkey ohne LiveBinding?
Sorry, dann hatte ich das noch nicht erkannt.
Habe bisher nur oberflächlich etwas gelesen. Aber für FM-Grids (insbes. TMSFMGrid) geht es noch nicht - oder? |
AW: FireMonkey ohne LiveBinding?
Ich nutze das TMS Grid genau aus diesem Grund nicht. Visual LiveBindings sind mir noch ein bisschen suspekt da ich mich damit noch nicht ausführlich genug beschäftigt habe und die Demos die ich gesehen habe noch nicht umfangreich genug waren.
Damit ich unter FM weiß wann was wo und wie mit einem Grid geschieht, mache ich das aktuell mit dem StringGrid *freu* händisch. Sobald ich das Thema jedoch überblicke, werde ich sofort überall auf das TMS Grid umstellen. |
AW: FireMonkey ohne LiveBinding?
@Darlo
![]() Kannst Du mal 2-3 Sätze schreiben, wie Du die Daten zurück in die Datenbank bringst, insbesondere wenn - das Grid keine komplette Tabelle darstellt sondern z.B. einen Join oder eine View - Zeilen gelöscht wurden (wie kann der User das?) - Zeilen hinzugefügt wurden (wie und wann wird eine neue Id zugewiesen?)... |
AW: FireMonkey ohne LiveBinding?
Liste der Anhänge anzeigen (Anzahl: 1)
@stahli
Im Anhang ein (schnell mal hingekritzelter) Ansatz wie das funktionieren könnte. |
AW: FireMonkey ohne LiveBinding?
Zitat:
Alles andere ist doch, mit oder ohne Livebindings, für mehr als eine Schnelle Datenansicht eh Murks! |
AW: FireMonkey ohne LiveBinding?
Zitat:
So etwas kritzelt man doch nicht mal schnell... Danke auf jeden Fall! :thumb: Das ist ganz schön komplex, bzw. ist ja einiges zu beachten. Das TMSFMGrid ist allerdings etwas anders aufgebaut (Details muss ich mir noch anschauen.) Löschen und Hinzufügen von Zeilen kann Deine Lösung ja aber so auch nicht. Ich hatte angedacht, die CDS-Felder als fixe Objekte an die Zellen zu binden. Dafür müsste man natürlich alle Felder und alle Zeilen bei der Dateninitialisierung füllen. Evtl. wäre auch eine Überlegung, nur die Werte in die Zellen zu übernehmen und gar keine Bindung zur DB zu halten (oder wie DanielJ anregt, Datenobjekte als Schnittstelle an die Zeilen zu binden). Das Rückschreiben (der neuen/geänderten/gelöschten Zeilen) müsste dann natürlich explizit und über SQL-Statements ausgelöst werden. Da der User ja (bei entsprechenden Einstellungen) das TMSFMGrid ja beliebig sortieren und ggf. gruppieren kann, weiß ich nicht recht, ob Dein Ansatz dafür tauglich ist... |
AW: FireMonkey ohne LiveBinding?
Das meinte ich auch mit mal so eben hingekritzelt und keine bis ins allerfeinste ausgeklügelte Lösung, sondern ein Ansatz, wie man es lösen kann.
Löschen, anfügen ist auch kein Problem das zu erweitern (anfügen ist etwas mehr Aufwand). Löschen: Im ViewModel einfach eine procedure Delete rein. In der procedure zur entsprechenden Zeile im DataSet gehen und den Datensatz löschen. In der View ruft man dass dann wie folgt auf:
Delphi-Quellcode:
Für das Anfügen müsste man ein Flag im ViewModel setzen, dass man aktuell beim Anfügen ist (weil ja jetzt eine Zeile mehr als im DataSet vorhanden ist).
procedure TMain_View.Delete_ButtonClick( Sender : TObject );
begin ViewModel.Delete; LoadFromModel; end; Aber viel mehr ist das auch nicht, die Basics sind da. Und beim Post im ViewModel muss man dann eben die Daten per Append an das DataSet anhängen. |
AW: FireMonkey ohne LiveBinding?
Wirklich schnell gekritzelt? :thumb:
Ich hätte vermutet, Du hättest das in einer Schublade gehabt... |
AW: FireMonkey ohne LiveBinding?
Jetzt wollte ich mal einen Navigator von Hand nutzen...
So verweigert er aber direkt seine Arbeit. :-(
Delphi-Quellcode:
Die Hilfe bezieht sich z.T. auf den VCL-Navigator. Das hilft auch nicht wirklich weiter.
procedure TBindNavigatorController.EnableButtons(AButtons: TNavigateButtons; ADataSourceEnabled: Boolean;
ASetEnabled: TProc<TNavigateButton, Boolean>); var FUpState: TState; FDnState: TState; FCanModifyState: TState; FStateSelected: TState; ... function UpEnable: Boolean; begin if FUpState = stUnknown then if ADataSourceEnabled and Selected and not Self.BOF then FUpState := stEnable else FUpState := stDisable; Result := FUpState = stEnable; end; ... function TBindNavigatorController.GetBOF: Boolean; begin if Assigned(FScopeNavigator) then // NIX OHNE Scope Result := FScopeNavigator.BOF else Result := True; end; |
AW: FireMonkey ohne LiveBinding?
Ich habe mal noch etwas herumgespielt und das TMSFMGrid nun von Hand befüllt.
Das Grid habe ich auf einem eigenen Formular, das ich dann zur Laufzeit in das Hauptformular einbette (wie ![]() Zum Ausblenden einer Spalte setze ich deren Breite einfach auf 0. Benötigt wird sie aber, da darin die ID verwaltet wird. Das Grid hält dann Kopien der Daten und bei Änderungen werden diese per SQL in die Datenbank geschrieben. Ändert sich durch eine Editierung die Reihenfolge der Datensätze, wird der Focus auf die aktuelle Zelle automatisch korrigiert. Das hat so den Vorteil, dass man alle Steuerungen ganz gut kontrollieren kann. Natürlich ist damit etwas mehr Schreibarbeit verbunden. Extrem große Tabellen sollte man dann nicht vollständig in das Gitter füllen. Im Moment habe ich mich an die ersten Regelungen heran getastet und halte den Aufwand des Ansatzes für akzeptabel. Das Grid kann ja Userbasiert sortiert und gruppiert werden. Anhand der ID in der ersten Spalte kann immer eine Verbindung zur Datenbank hergestellt werden. Selbst Joins lassen sich darstellen und (da das händisch passiert) sinnvoll in die DB zurück speichern. Löschen und Einfügen von Datensätzen habe ich noch nicht fertig, das wird sich aber lösen lassen. Schade, dass der Navigator nicht frei (ohne angebundene Datenmange) verwendbar ist. Eine direkte Bindung an das Gitter habe ich nicht regeln können (wird wohl nicht gehen). Falls hier mal jemand eine Anregung entnehmen mag:
Delphi-Quellcode:
unit frmPersonsGrid;
interface uses System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.TMSBaseControl, FMX.TMSGridCell, FMX.TMSGridOptions, FMX.TMSGridData, FMX.TMSCustomGrid, FMX.TMSGrid, FMX.Objects, Data.Bind.EngExt, FMX.Bind.DBEngExt, FMX.TMSGridDataBinding, System.Bindings.Outputs, FMX.Bind.Editors, FMX.Layouts, FMX.Bind.Navigator, Data.Bind.Components, Data.Bind.Grid, Data.Bind.DBScope, Data.Bind.Controls; type TFormPersonsGrid = class(TForm) TMSFMXGridPersons: TTMSFMXGrid; Body: TRectangle; BindNavigatorPersons: TBindNavigator; Button1: TButton; procedure TMSFMXGridPersonsGetCellReadOnly(Sender: TObject; ACol, ARow: Integer; var AReadOnly: Boolean); procedure TMSFMXGridPersonsCellCheckBoxClick(Sender: TObject; ACol, ARow: Integer; Cell: TFmxObject); procedure TMSFMXGridPersonsCellEditDone(Sender: TObject; ACol, ARow: Integer; CellEditor: TFmxObject); procedure TMSFMXGridPersonsGetCellProperties(Sender: TObject; ACol, ARow: Integer; Cell: TFmxObject); procedure TMSFMXGridPersonsGetCellData(Sender: TObject; ACol, ARow: Integer; var CellString: string); private FillFlag: Boolean; public procedure FillGridData(Id: Integer = 0); procedure SaveGridData; end; var FormPersonsGrid: TFormPersonsGrid; implementation {$R *.fmx} uses dFlyMagicM, Data.SqlExpr; { TFormPersonsGrid } procedure TFormPersonsGrid.FillGridData(Id: Integer = 0); var DS: TSQLDataSet; Grid: TTMSFMXGrid; C: Integer; R: Integer; begin FillFlag := True; DS := DataModuleFlyMagicM.PERSONS; Grid := TMSFMXGridPersons; DS.Close; DS.Open; Grid.ColumnCount := 4 + 1; Grid.RowCount := DS.RecordCount + 1; Grid.ColumnWidths[1] := 0; Grid.AddCheckBoxColumn(2); for C := 1 to DS.Fields.Count do begin Grid.Cells[C, 0] := DS.Fields[C - 1].FieldName; end; for R := 1 to Grid.RowCount do begin if DS.FieldByName('Id').AsInteger = Id then Grid.FocusedCell := Grid.SingleCell(Grid.FocusedCell.Col, R); for C := 1 to DS.Fields.Count do begin Grid.Cells[C, R] := DS.Fields[C - 1].AsString; end; DS.Next; end; DS.Close; FillFlag := False; end; procedure TFormPersonsGrid.SaveGridData; begin end; procedure TFormPersonsGrid.TMSFMXGridPersonsCellCheckBoxClick(Sender: TObject; ACol, ARow: Integer; Cell: TFmxObject); var B: Boolean; DS: TSQLDataSet; Grid: TTMSFMXGrid; Id: Integer; FieldName: string; Value: string; begin if FillFlag then Exit; if (ARow > 0) and (ACol = 2) then begin if Cell is TTMSFMXCheckGridCell then begin B := (Cell as TTMSFMXCheckGridCell).CheckBox.IsChecked; DS := DataModuleFlyMagicM.PersonsUpdate; Grid := TMSFMXGridPersons; Id := StrToIntDef(Grid.Cells[1, ARow], 0); FieldName := Grid.Cells[ACol, 0]; Grid.FocusedCell := Grid.SingleCell(ACol, ARow); if B then Value := '1' else Value := '0'; DS.Close; DS.CommandText := 'UPDATE Persons SET ' + FieldName + ' = :Value WHERE Id = :Id'; DS.ParamByName('Id').AsInteger := Id; DS.ParamByName('Value').AsString := Value; DS.ExecSQL(); DS.Close; FillGridData(Id); end; end; end; procedure TFormPersonsGrid.TMSFMXGridPersonsCellEditDone(Sender: TObject; ACol, ARow: Integer; CellEditor: TFmxObject); var DS: TSQLDataSet; Grid: TTMSFMXGrid; Id: Integer; FieldName: string; Value: string; begin DS := DataModuleFlyMagicM.PersonsUpdate; Grid := TMSFMXGridPersons; Id := StrToIntDef(Grid.Cells[1, ARow], 0); FieldName := Grid.Cells[ACol, 0]; Value := Grid.Cells[ACol, ARow]; DS.Close; DS.CommandText := 'UPDATE Persons SET ' + FieldName + ' = :Value WHERE Id = :Id'; DS.ParamByName('Id').AsInteger := Id; DS.ParamByName('Value').AsString := Value; DS.ExecSQL(); DS.Close; FillGridData(Id); end; procedure TFormPersonsGrid.TMSFMXGridPersonsGetCellData(Sender: TObject; ACol, ARow: Integer; var CellString: string); var C: TFmxObject; begin if (ARow > 0) and (ACol = 2) then begin C := TMSFMXGridPersons.CellControls[ACol, ARow]; if C is TTMSFMXCheckGridCell then (C as TTMSFMXCheckGridCell).CheckBox.IsChecked := (CellString = '1'); CellString := ''; end; end; procedure TFormPersonsGrid.TMSFMXGridPersonsGetCellProperties(Sender: TObject; ACol, ARow: Integer; Cell: TFmxObject); begin if Cell is TTMSFMXCheckGridCell then (Cell as TTMSFMXCheckGridCell).CheckBox.IsChecked := (TMSFMXGridPersons.Cells[ACol, ARow] = '1'); end; procedure TFormPersonsGrid.TMSFMXGridPersonsGetCellReadOnly(Sender: TObject; ACol, ARow: Integer; var AReadOnly: Boolean); begin AReadOnly := (ACol in [1, 2]); end; end. |
AW: FireMonkey ohne LiveBinding?
Hallo Strahli,
sorry das ich erst jetzt antworte, aber die letzten Tage hatte endlich mal wieder die Familie den Vorrang. Löschen und Einfügen mache ich über einen Dialog. Ebenso wie Du habe ich die ID in einer Zelle mit width := 0.
Delphi-Quellcode:
So kann ich auch in mehrere Tabellen mit einem Eingabedialog schreiben.
if frmContent.gridVertraege.Cells[6, frmContent.gridVertraege.Selected] <> '' then
frmDatabase.dbVertragInsert(frmContent.gridVertraege.Cells[6, frmContent.gridVertraege.Selected]); Ist eben Tipparbeit und Maskenbau. |
AW: FireMonkey ohne LiveBinding?
Also ich bin generell kein Freund von der Datenhaltung in Elementen zur Visualisierung.
Wenn ich die Zeile weiß, die gemeint ist, dann weiß ich auch was gemeint ist, denn ich habe diese Zeile gefüllt. Dadurch wird es völlig egal, was dort dargestellt wird und welchen Typ die ID hat. Vom Konzept her ist das MischMasch. |
AW: FireMonkey ohne LiveBinding?
Zitat:
|
AW: FireMonkey ohne LiveBinding?
@ Sir
Ja, das sehe ich im Grunde auch so. Allerdings hat das Konzept auch Vorteile. Man kann alle möglichen Datenbestände optimal darstellen (wenn man die Grid-Features erst mal vernünftig verstanden hat) und ist nicht auf die Bindung einer einzelnen SQL-Datenabfrage beschränkt. Auch braucht man (wenn man bei dbExpress bleiben will) kein ClientDataSet und keinen Provider als Vermittler. Durch die Auslagerung des Grids und seiner kompletten Befüllung und Ereignisbehandlungen in eine eigene Formularunit lässt sich das Ganze sehr gut handeln. Man hat zwar doch wieder einigen Gluecode aber da man jedes Grid in einer eigenen Unit abwickeln und die ja auch duplizieren kann, ist mir das Ganze gar nicht so unsympatisch. In Abwägung aller Optionen keine schlechte Lösung. |
AW: FireMonkey ohne LiveBinding?
Zitat:
Die LiveBindings sind mit der heißen Nadel gestrickt (die sollten wohl einfach nur fertig werden) Bei dem verzapften Code kräuseln sich einem die Fußnägel |
AW: FireMonkey ohne LiveBinding?
Zitat:
|
AW: FireMonkey ohne LiveBinding?
Derjenige, der die LB-Grundlagen und Parser erstellt hat, ist wohl auch nicht mehr verfügbar. Das kam in einem Nebensatz in einer der CR7 Sessions zum Ausdruck.
|
AW: FireMonkey ohne LiveBinding?
Man könnte ja mal ein prominentes Mitglied unserer Gemeinschaft fragen... :zwinker:
So ein Profi bin ich ja nicht, aber das Stück, das ich mir mal angesehen hatte (Bindung zu einer CheckBox), das sah alles andere als durchdacht aus. So hätte ich das auch noch hin gekriegt - aber nicht kommerziell angeboten. Das Ergebnis sieht man ja. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:48 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