2010-06-08 12 views
5

D6 prof.Delphi - Wiederherstellung der tatsächlichen Zeile in DBGrid

Früher verwendeten wir DBISAM und DBISAMTable. Das behandeln die RecNo, und es funktioniert gut mit Änderungen (Löschen, bearbeiten, etc).

Jetzt haben wir mit ElevateDB ersetzt, die RecNo nicht behandeln, und oft verwenden wir Abfragen, nicht Tabellen.

Abfrage muss erneut geöffnet werden, um die Änderungen zu sehen.

Aber wenn wir die Abfrage erneut öffnen, müssen wir auf den letzten Datensatz neu positionieren. Locate ist nicht genug, da Grid es in einer anderen Zeile anzeigt. Dies ist sehr beunruhigend, weil nach der Änderung Datensatz in eine andere Zeile bewegt, Sie es schwer zu folgen, und die Benutzer hassen dies.

Wir fanden diesen Code:

function TBaseDBGrid.GetActRow: integer; 
begin 
Result := -1 + Row; 
end; 


procedure TBasepDBGrid.SetActRow(aRow: integer); 
var 
bm : TBookMark; 
begin 
if IsDataSourceValid(DataSource) then with DataSource.DataSet do begin 
    bm := GetBookmark; 
    DisableControls; 
    try 
    MoveBy(-aRow); 
    MoveBy(aRow); 
    //GotoBookmark(bm); 
    finally 
    FreebookMark(bm); 
    EnableControls; 
    end; 
end; 
end; 

Das ursprüngliche Beispiel ist MoveBy verwendet. Dies funktioniert gut mit Abfragen, da wir nicht sehen können, dass Abfrage im Hintergrund wieder geöffnet wird, die visuelle Kontrolle wird nicht die Zeilenposition geändert.

Aber wenn wir EDBTable oder Live/Sensitive Query haben, ist die Verwendung von MoveBy gefährlich, denn wenn jemand eine neue Zeile löscht oder anfügt, können wir in einen falschen Datensatz umziehen.

Dann habe ich versucht, den BookMark zu verwenden (siehe Bemerkung). Aber diese Technik funktioniert nicht, weil es den Datensatz in einer anderen Zeile Position zeigt ...

So die Frage: Wie erzwingen Sie sowohl die Zeilenposition und Record in DBGrid?

Oder welche Art von DBGrid kann in den Datensatz/die Zeile verschoben werden, nachdem das zugrunde liegende DataSet aktualisiert wurde?

Ich suche nach benutzerfreundliche Lösung, ich verstehe sie, weil ich versucht, diese Jump-Across-DBGrid zu verwenden, und sehr schlecht zu verwenden, weil meine Augen raus, wenn versuchen, den ursprünglichen Datensatz nach dem Update zu finden ... :-(

Vielen Dank für Ihre jede Hilfe, Link, Info: dd

Antwort

8

Seit ‚MoveBy die für Sie arbeiten, verwenden sie.

Holen Sie ein 'Lesezeichen', bevor Sie das Dataset schließen. Machen Sie Ihre Arbeit, öffnen Sie den Datensatz erneut und positionieren Sie dann Ihren Datensatz mit "MoveBy's" im Raster neu. Wenn Sie fertig sind, holen Sie sich ein anderes Lesezeichen und vergleichen Sie es mit dem vorherigen mit DataSet.CompareBookmarks. Wenn das Ergebnis 0 ist, wenn nicht, dann geben Sie ein "Gehe zu Lesezeichen" für das vorherige Lesezeichen aus.

Solange kein anderer Benutzer Datensätze gelöscht/eingefügt hat, scheint Ihr Raster nicht nervös zu sein, und wenn dies nicht der Fall ist, sind Sie mindestens auf dem gleichen Datensatz.


edit: Hier einige Codebeispiel, das den ausgewählten Datensatz an der richtigen Stelle neu positionieren sollte, auch wenn es Löschungen gewesen war/Einsätze im Datensatz. Beachten Sie, dass der Code das Deaktivieren/Aktivieren von Steuerelementen und den Sonderfall auslässt, wenn weniger Datensätze zur Vereinfachung das Raster füllen.

type 
    TAccessDBGrid = class(TDBGrid); 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    BmSave, Bm: TBookmark; 
    GridRow, TotalRow: Integer; 
begin 
    GridRow := TAccessDBGrid(DBGrid1).Row; 
    TotalRow := TAccessDBGrid(DBGrid1).RowCount; 
    BmSave := DBGrid1.DataSource.DataSet.GetBookmark; 
    try 

    // close dataset, open dataset... 

    if DBGrid1.DataSource.DataSet.BookmarkValid(BmSave) then 
     DBGrid1.DataSource.DataSet.GotoBookmark(BmSave); 
    Dec(TotalRow); 
    if GridRow < TotalRow div 2 then begin 
     DBGrid1.DataSource.DataSet.MoveBy(TotalRow - GridRow); 
     DBGrid1.DataSource.DataSet.MoveBy(GridRow - TotalRow); 
    end else begin 
     if dgTitles in DBGrid1.Options then 
     Dec(GridRow); 
     DBGrid1.DataSource.DataSet.MoveBy(-GridRow); 
     DBGrid1.DataSource.DataSet.MoveBy(GridRow); 
    end; 
    Bm := DBGrid1.DataSource.DataSet.GetBookmark; 
    try 
     if (DBGrid1.DataSource.DataSet.BookmarkValid(Bm) and 
      DBGrid1.DataSource.DataSet.BookmarkValid(BmSave)) and 
      (DBGrid1.DataSource.DataSet.CompareBookmarks(Bm, BmSave) <> 0) then 
     DBGrid1.DataSource.DataSet.GotoBookmark(BmSave); 
    finally 
     DBGrid1.DataSource.DataSet.FreeBookmark(Bm); 
    end; 
    finally 
    DBGrid1.DataSource.DataSet.FreeBookmark(BmSave); 
    end; 
end; 
1

Shop der Wert (e) Ihrer einzigartigen Schlüsselfeld (en) vor dem Schließen und erneuten Öffnen der Abfrage, dann Locate auf den Datensatz nach Wiedereröffnung DisableControls/EnableControls, um Bildschirmaktualisierungen zu verhindern

+0

Hallo! Wie ich sehe nicht. GotoBookMark ist das gleiche wie hier, weil wir nach Open sind. Aber die tatsächliche Grid-Zeile ist nicht die gleiche, also Disable not prevent to Grid zeigt den Datensatz an einer anderen Position an. MoveBy ist gut, aber ich brauche Locate hier. Aber wenn ich orten verwenden, änderte sich die Grid-Reihe ... Zum Beispiel: der Mahlgrad den Datensatz 127 in der Zeile 4 gezeigt Wenn ich mit MoveBy wieder öffnen, ist es auch in Zeile 4. Wenn ich Locate verwenden/Lesezeichen, es ist in 3, 2, 5 - zufällig, wo ich den aktuellen Datensatz sehen ... :-( – durumdara

+1

User 2 Einfügen/löschen einer Zeile, und Ihre Benutzer 1 gespeichert wird Record falsch das ist, was TOndrej versucht zu helfen. Sie vermeiden –

0

Gerade einfaches Stück Code, der in meinem Kopf kam:

procedure DoRefresh(Dataset: TDataset); 
var 
    bkm: TBookmark; 
begin 
    Dataset.UpdateCursorPos; 
    bkm := Dataset.GetBookmark; 
    Dataset.DisableControls; 
    try 
    Dataset.Refresh; //refresh dataset if it's open 

    if Dataset.BookmarkValid(bkm) then 
    begin 
     Dataset.GotoBookmark(bkm); 
    end; 
    finally 
    Dataset.EnableControls; 
    Dataset.FreeBookmark(bkm); 
    end; 
end; 
+0

Hallo ich die Routinen wie folgt verwenden:.! aRow = Grid.GetRow(); Query.ReOpen; SetActRow (aRow); Also das nicht mit einem Lesezeichen Problem ist, das DBTabelle Row Problem ist ... – durumdara

+0

Welche DBGrid verwenden Sie? Standard TDBGrid hat keine Eigenschaft GetRow. Ich bezweifle, dass dies DBGrid Problem ist. s aktiver Datensatz ist der aktuelle aktive Datensatz im Datensatz. – Linas

0

Bilanz Position hängt viel von der Sortierreihenfolge von Suchresultates Sie aus dem Query/Table-Objekt bekam. Wenn Sie überhaupt nicht bestellen, ist die Reihenfolge, die Sie vom Server erhalten, implementierungsdefiniert und kann nicht garantieren, dass Datensätze in der gleichen Reihenfolge kommen, wenn die Abfrage erneut geöffnet wird. auch wenn keine Änderungen vorgenommen wurden. Zumindest in MSSQL und Firebird kommen die Ergebnisse in unterschiedlichen Aufträgen, wenn keine Order By Klausel verwendet wird.

Was Neupositionierung, denke ich, dass TOndrej Lösung der sichersten ist - der Primärschlüssel des Suchresultates mit dem Raster auf dem rechten Datensatz neu zu positionieren.