DBGrid Einfrieren

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Strathmore
Beiträge: 17
Registriert: So 7. Jan 2007, 00:09
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

DBGrid Einfrieren

Beitrag von Strathmore »

Werte Lazarusbenutzer,

habe eine SQLQuery offen, die mit der Datasource verbunden ist, diese wiederrum mit DBGrid. Alles fein. Die DBGrid zeigt mir die Datensätze. Nun will ich aber in der SQLQuery einen Insert machen und diesen, bis zur Entscheidung des Benutzers über das Speichern oder Abbrechen, in der DBGrid nicht anzeigen. Habe schon Datasource.Enabled:=False probiert, bringt aber nicht das gewünschte Ergebnis. Weiss jemand Rat?

Lazarus: 0.9.28.2, FPC: 2.2.4

Vielen Dank im Voraus.

Socke
Lazarusforum e. V.
Beiträge: 3177
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: DBGrid Einfrieren

Beitrag von Socke »

Du führst den Insert erst aus, wenn der Benutzer darüber entschieden hat.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

mr.mc.mauser
Beiträge: 33
Registriert: Di 8. Jun 2010, 19:38

Re: DBGrid Einfrieren

Beitrag von mr.mc.mauser »

Hallo,

ich mache das So:
ich benutze zusätzlich noch den DB Navigator,
da gibt es den Post Button, und diesen Fange ich ab, dann kommt die abfrage "Soll ich speichern Ja oder nein"

Code: Alles auswählen

procedure TForm1.DBNavigatorClick(Sender: TObject; Button: TDBNavButtonType);
begin
	//Button gedrückt
	case Button of
		nbPost: begin
			case MessageDlg('In DB Geschrieben werden ?',
				mtConfirmation, [mbOK, mbCancel], 0) of
				// wenn OK dann Schreiben
				mrOk: begin
					// Der eigentliche Shreibvorgang, weiss ja nicht wie du schreibst :)
				end;
				// wenn Abbruch dann nix
				mrCancel: begin
					SysUtils.Abort;
				end;
			end;
		end;
	end;
end;
Gruß
Robert

Strathmore
Beiträge: 17
Registriert: So 7. Jan 2007, 00:09
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: DBGrid Einfrieren

Beitrag von Strathmore »

Socke hat geschrieben:Du führst den Insert erst aus, wenn der Benutzer darüber entschieden hat.
Die Idee hatte ich ja schon selbst, ist aber mit einigen Änderungen verbunden. Wenn es nicht einfacher geht, muss ich dann wohl diesen Weg einschlagen ...

Strathmore
Beiträge: 17
Registriert: So 7. Jan 2007, 00:09
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: DBGrid Einfrieren

Beitrag von Strathmore »

@mr.mc.mauser: sehr schöner Stück Code, zeigt aber die Lösung auf meine Frage nicht. Trotzdem vielen Dank.

MmVisual
Beiträge: 1579
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: DBGrid Einfrieren

Beitrag von MmVisual »

Query1.DisableControls;
: : :
Query1.EnableControls;
EleLa - Elektronik Lagerverwaltung - www.elela.de

am2
Lazarusforum e. V.
Beiträge: 116
Registriert: Di 21. Dez 2010, 09:59
OS, Lazarus, FPC: Win (L 0.9.26 beta FPC 2.2.2)
CPU-Target: 32 Bit

Re: DBGrid Einfrieren

Beitrag von am2 »

Vielleicht fasst Du das Problem ja ungünstig an. Wenn Du das wirklich so brauchst, wie Du sagst, dann wird es eine wartungsaufwändige Bastellösung. Falls Du nur sichergehen willst, dass kein Datensatz in der DB landet, der nicht tatsächlich autorisiert ist, dann kannst Du das sicher anders lösen:

1.: AutoCommit abschalten
2.: DBNavigator an die Datenquelle hängen. Notfalls im BeforePost oder so eine Abfrage unterbringen
2. alternativ: Einen Knopf für Insert, einen für Post. In ButtonInsertClick : Datenquelle.Insert, in ButtonPostClick: Messagedialog und je nach Ergebnis .Post oder .Cancel

Falls Du unbedingt basteln willst:
- Möglichkeit A) Erzeuge eine Schattentabelle (In Datenbank), die nur für die neuen Datensätze da ist. Sobald der Datensatz bestätigt wird, wird er in die echte Tabelle kopiert
- Möglichkeit B) Erzeuge nicht- DB- Felder und fülle den Inhalt erst danach in die DB um

Vielleicht hilft es Dir irgendwie. Ich mache das seit Jahren (Delphi + Oracle) auf die ganz oben beschriebene Weise. Etwas komplizierter wird es, wenn an einem Datensatz automatisch Detaildatensätze drangehängt werden müssen. Aber das scheint hier ja nicht der Fall zu sein.

Strathmore
Beiträge: 17
Registriert: So 7. Jan 2007, 00:09
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: DBGrid Einfrieren

Beitrag von Strathmore »

MmVisual hat geschrieben:Query1.DisableControls;
: : :
Query1.EnableControls;
Habe ich gleich ausprobiert, hat irgendwie nicht funktioniert.

Strathmore
Beiträge: 17
Registriert: So 7. Jan 2007, 00:09
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: DBGrid Einfrieren

Beitrag von Strathmore »

@am2: Bastellösung ist nicht gut. Kostet zuviel Zeit. Daher will ich ja eine saubere Lösung implementieren.
Kurze Beschreibung:
Button für Insert,
Button für Edit,
Button für Speichern,
Button für Abbruch,
Button zum Löschen.
DBGrid als reines Navigationselement, nicht editierbar. Über die DataSource verknüpft mit SQLQuery1, die nur PK Felder und einige wenige nicht-PK Felder enthält.
Unter dem DBGrid diverse Eingabefelder im Formular. SQLQuery2, die alle Felder EINES Datensatzes enthält, versorgt die Eingabefelder mit Werten und kümmert sich um die Speicherung. Eingabefelder und SQLQuery2 sind NICHT über eine DataSource verknüpft, erst mit Betätigen des Speichern Buttons werden Werte aktualisiert, beim Abbruch werden einfach die alten wieder angezeigt. Wird SQLQuery1 navigiert, lädt SQLQuery2 den richtigen Datensatz nach. Soweit alles schick.
Jetzt das Schönheitsproblem beim Betätigen des Buttons Insert: (pseudocode)

Code: Alles auswählen

SQLQuery1.Insert;
SQLQuery1.PK := <neuer Wert>;
DatensatzNachladen;  //mit SQLQuery2 -> findet nichts, daher werden alle Eingabefelder dann geleert
DatensatzDarstellen;  //Leeren der Eingabefelder, da in SQLQuery2 nichts
Eingabefeld_PK := SQLQuery1.PK //damit der PK schon im Eingabefeld steht
-> Warten auf weitere Benutereingaben und Entscheidung ob Speichern oder Abbrechen ...
... Währenddessen wird aber der SQLQuery1.PK im DBGrid schon angezeigt, obwohl der Benutzer noch nicht gespeichert hat, und das ärgert mich.
Daher erneut meine Frage: Kann man für die Entscheidungszeit die Aktualisierung der DBGrid irgendwie unterbinden?

shokwave
Beiträge: 475
Registriert: Do 15. Nov 2007, 16:58
OS, Lazarus, FPC: Win11/Ubuntu Budgie (L 3.0 FPC 3.2.2)
CPU-Target: i386, x64
Wohnort: Gera

Re: DBGrid Einfrieren

Beitrag von shokwave »

Kann man für die Entscheidungszeit die Aktualisierung der DBGrid irgendwie unterbinden?
Ich hab NULL Ahnung von SQL. Ich würde wohl einfach die Frage vor dem Insert stellen. Pseudocode:

Code: Alles auswählen

if MessageDlg('Willste wirklich?', mtFrage, [mbJo, mbNö], 0)=mrJo then
begin
  SQLQuery1.Insert;
  SQLQuery1.PK := <neuer Wert>;
  DatensatzNachladen; //mit SQLQuery2 -> findet nichts, daher werden alle Eingabefelder dann geleert
  DatensatzDarstellen; //Leeren der Eingabefelder, da in SQLQuery2 nichts
  Eingabefeld_PK := SQLQuery1.PK; 
end;
mfg Ingo

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: DBGrid Einfrieren

Beitrag von Christian »

Enable/Disablecontrols ist das einzige was das so macht wie du willst und funktioniert. Du musst allerdings beachten das es die Controls wirklich einfriert also ein Scrollen oder sonstewas ist dann auch nicht mehr möglich.

Wenn das doch möglich sein soll brauchst du eine 2. Connection oder Transaction die solange nicht COmmitted wird bis der Nutzer entscheidet das gespeichert wird.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

am2
Lazarusforum e. V.
Beiträge: 116
Registriert: Di 21. Dez 2010, 09:59
OS, Lazarus, FPC: Win (L 0.9.26 beta FPC 2.2.2)
CPU-Target: 32 Bit

Re: DBGrid Einfrieren

Beitrag von am2 »

Strathmore hat geschrieben:@am2: Bastellösung ist nicht gut. Kostet zuviel Zeit. Daher will ich ja eine saubere Lösung implementieren.
Kurze Beschreibung:
Button für Insert,
Button für Edit,
Button für Speichern,
Button für Abbruch,
Button zum Löschen.
DBGrid als reines Navigationselement, nicht editierbar. Über die DataSource verknüpft mit SQLQuery1, die nur PK Felder und einige wenige nicht-PK Felder enthält.
Unter dem DBGrid diverse Eingabefelder im Formular. SQLQuery2, die alle Felder EINES Datensatzes enthält, versorgt die Eingabefelder mit Werten und kümmert sich um die Speicherung. Eingabefelder und SQLQuery2 sind NICHT über eine DataSource verknüpft, erst mit Betätigen des Speichern Buttons werden Werte aktualisiert, beim Abbruch werden einfach die alten wieder angezeigt. Wird SQLQuery1 navigiert, lädt SQLQuery2 den richtigen Datensatz nach. Soweit alles schick.
Jetzt das Schönheitsproblem beim Betätigen des Buttons Insert: (pseudocode)
SQLQuery1.Insert;
SQLQuery1.PK := <neuer Wert>;
DatensatzNachladen; //mit SQLQuery2 -> findet nichts, daher werden alle Eingabefelder dann geleert
DatensatzDarstellen; //Leeren der Eingabefelder, da in SQLQuery2 nichts
Eingabefeld_PK := SQLQuery1.PK //damit der PK schon im Eingabefeld steht
-> Warten auf weitere Benutereingaben und Entscheidung ob Speichern oder Abbrechen ...
... Währenddessen wird aber der SQLQuery1.PK im DBGrid schon angezeigt, obwohl der Benutzer noch nicht gespeichert hat, und das ärgert mich.
Daher erneut meine Frage: Kann man für die Entscheidungszeit die Aktualisierung der DBGrid irgendwie unterbinden?
Ich bin mir nicht sicher, ob ich Dich richtig verstanden habe. Aber für mich stellt es sich so dar, als ob Du
- eine Datenquelle hast, die Dir einen überblick liefert
- eine weitere Datenquelle hast, die Dir alle relevanten Daten eines Datensatzes zur Verfügung stellt
- unabhängige Steuerelemente hast, die die eigentliche Dateneingabe abwickeln und je nach Entscheidung abbrechen/speichern entweder die Daten aus den unabhängigen Steuerelementen in die Datenquelle einspeist, oder die alten Daten wieder aus der DB holt

Ich persönlich habe vor ziemlich genau 6 Jahren mal mit dieser Herangehensweise kämpfen müssen, weil ich ein solches Projekt übernehmen mußte. (Allerdings enthielt das so ca. 10 Datenquellen, die auch noch voneinander abhängig waren) - nie wieder :) Das Programm ist mittlerweile im Bit- und Byte- Himmel, aber ich war dort immer mit Flickerei beschäftigt.

Wenn Du aber definitiv so arbeiten willst/mußt, dann würde ich vorschlagen, dass Du erst insertierst beim Speichern. Wenn Du den Knopf "Insert" drückst, leerst Du die Felder (bzw. initialisierst sie mit geeigneten Werten). Wenn Dann abbrechen kommt, dann zeigst Du wieder die aktuellen an, beim Speichern insertierst Du und speicherst.
Du könntest - wenn Du willst - auf diese Weise auch leicht realisieren, dass der Datensatz, auf dem Du gerade stehst, als "Muster" genommen wird, indem Du bei Druck auf Insert eben nichts weiter mit den "unabhängigen" Eingabefeldern tust.
Was Du in jedem Fall tun müsstest, ist, Dir zu merken, dass Du im Insert- Modus bist, damit der Abbruch/Speichern- Knopf das richtige machen kann.

Also PseudeCode:

Code: Alles auswählen

procedure InsertClick;
begin 
  Modus:=IchMacheInsert; 
  if IchWillDatensatzLeermachen then LeermachenSteuerelemente;
end;
 
procedure EditClick;
begin
  Modus:=IchMachEsMitEdit;
  KopiereInhalteAusDatenquelleInSteuerelemente;
end;
 
procedure SpeichernClick;
begin
  case Modus of IchMacheInsert 
    IchMacheInsert: Datenquelle2.Insert;
    IchMachEsMitEdit: Datenquelle2.Edit;
  else
    WasZuTun:=false;
    LustigeFehlermeldungGenerieren;
  end;
  if WasZuTun then begin
    KopiereInhalteAusSteuerelementenInDatenelemente;
    Datenquelle2.Post;
  end;
  Modus:=IchHabeFertig;
end;
Falls ich Dich richtig verstanden habe ...

Strathmore
Beiträge: 17
Registriert: So 7. Jan 2007, 00:09
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Re: DBGrid Einfrieren

Beitrag von Strathmore »

@am: Du hast mich richtig verstanden. Ziemlich ähnlich wie Du es beschreibst, habe ich es gestern Abend dann auch implementiert. Insert gibt es erst beim Speichern Button. Dann bleibt auch die DBGrid ruhig.

Vielen herzlichen Dank!

Antworten