AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

FireMonkey ohne LiveBinding?

Ein Thema von stahli · begonnen am 15. Nov 2012 · letzter Beitrag vom 19. Nov 2012
Antwort Antwort
Seite 2 von 3     12 3      
DanielJ

Registriert seit: 8. Sep 2008
Ort: Hamburg
35 Beiträge
 
Delphi XE Professional
 
#11

AW: FireMonkey ohne LiveBinding?

  Alt 16. Nov 2012, 15:25
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?)...
Wie währe es mit ein paar netten Daten-Objekten die du an deine Grid-Spalten hängen kannst. Bei Änderungen an einer Spalte erzählst du dem Angehängten Objekt davon. Das entscheidet dann ob, wo und wie das Gespeichert werden kann/muss.
Alles andere ist doch, mit oder ohne Livebindings, für mehr als eine Schnelle Datenansicht eh Murks!
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#12

AW: FireMonkey ohne LiveBinding?

  Alt 16. Nov 2012, 19:03
@stahli

Im Anhang ein (schnell mal hingekritzelter) Ansatz wie das funktionieren könnte.
Schummelst Du???
So etwas kritzelt man doch nicht mal schnell...

Danke auf jeden Fall!
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...
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (16. Nov 2012 um 19:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#13

AW: FireMonkey ohne LiveBinding?

  Alt 16. Nov 2012, 19:11
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:
procedure TMain_View.Delete_ButtonClick( Sender : TObject );
begin
  ViewModel.Delete;
  LoadFromModel;
end;
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).
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.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (16. Nov 2012 um 19:14 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#14

AW: FireMonkey ohne LiveBinding?

  Alt 16. Nov 2012, 19:17
Wirklich schnell gekritzelt?
Ich hätte vermutet, Du hättest das in einer Schublade gehabt...
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#15

AW: FireMonkey ohne LiveBinding?

  Alt 18. Nov 2012, 17:21
Jetzt wollte ich mal einen Navigator von Hand nutzen...
So verweigert er aber direkt seine Arbeit.

Delphi-Quellcode:
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;
Die Hilfe bezieht sich z.T. auf den VCL-Navigator. Das hilft auch nicht wirklich weiter.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#16

AW: FireMonkey ohne LiveBinding?

  Alt 19. Nov 2012, 01:28
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 hier beschrieben - dem TRectangle "Body".Parent wird einfach ein Control aus dem Mainform zugewiesen).

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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (19. Nov 2012 um 09:43 Uhr)
  Mit Zitat antworten Zitat
Darlo

Registriert seit: 28. Jul 2008
Ort: München
1.196 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#17

AW: FireMonkey ohne LiveBinding?

  Alt 19. Nov 2012, 09:03
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:
   if frmContent.gridVertraege.Cells[6, frmContent.gridVertraege.Selected] <> 'then
      frmDatabase.dbVertragInsert(frmContent.gridVertraege.Cells[6, frmContent.gridVertraege.Selected]);
So kann ich auch in mehrere Tabellen mit einem Eingabedialog schreiben.
Ist eben Tipparbeit und Maskenbau.
Philip
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#18

AW: FireMonkey ohne LiveBinding?

  Alt 19. Nov 2012, 09:17
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.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Darlo

Registriert seit: 28. Jul 2008
Ort: München
1.196 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#19

AW: FireMonkey ohne LiveBinding?

  Alt 19. Nov 2012, 10:01
Vom Konzept her ist das MischMasch.
Also passend zu Firemonkey
Philip
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#20

AW: FireMonkey ohne LiveBinding?

  Alt 19. Nov 2012, 10:16
@ 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.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (19. Nov 2012 um 11:13 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz