5

D6 教授

以前は DBISAM と DBISAMTable を使用していました。それはRecNoを処理し、変更(削除、編集など)でうまく機能しています。

現在、RecNo を処理しない ElevateDB に置き換え、多くの場合、テーブルではなくクエリを使用しています。

変更を確認するには、クエリを再度開く必要があります。

ただし、クエリを再度開く場合は、最後のレコードに位置を変更する必要があります。グリッドは別の行に表示されるため、見つけるだけでは不十分です。変更レコードが別の行に移動した後、それを追跡するのが難しく、ユーザーはこれを嫌うため、これは非常に厄介なことです。

次のコードが見つかりました。

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;

元の例は moveby を使用しています。バックグラウンドでクエリが再度開かれたことを確認できないため、これはクエリでうまく機能し、ビジュアル コントロールは行の位置を変更しません。

しかし、EDBTable、または Live/Sensitive Query がある場合、MoveBy を使用するのは危険です。誰かが新しい行を削除または追加すると、間違ったレコードに再配置される可能性があるからです。

次に、BookMark を使用しようとしました (備考を参照)。しかし、別の行の位置にレコードを表示するため、この手法は機能しません...

質問: DBGrid で行の位置とレコードの両方を強制する方法は?

または、基になる DataSet が更新された後、どの種類の DBGrid をレコード/行に再配置できますか?

私はユーザーフレンドリーなソリューションを探しています。私はこのジャンプアクロスDBGridを使用しようとしたため、それらを理解していますが、更新後に元のレコードを見つけようとすると目が離せなくなるため、使用するのは非常に悪いです... :-(

あなたのすべての助け、リンク、情報をありがとう: dd

4

4 に答える 4

10

'MoveBy's が機能しているので、それらを使用してください。

データセットを閉じる前に「ブックマーク」を取得します。作業を行い、データセットを再度開いてから、「MoveBy」を使用してグリッド上のレコードを再配置します。完了したら、別のブックマークを取得し、DataSet.CompareBookmarks を使用して前のブックマークと比較します。結果が 0 の場合は問題ありません。そうでない場合は、前のブックマークに対して「GotoBookmark」を発行します。

このようにして、別のユーザーがレコードを削除/挿入していない限り、グリッドが不安定に見えることはありません。そうでない場合は、少なくとも同じレコードにいることになります。


編集:データセットに削除/挿入があった場合でも、選択したレコードを正しい場所に再配置するコード サンプルを次に示します。コードでは、無効化/有効化のコントロールが省略されていることに注意してください。また、単純化のために、グリッドを埋めるレコードが少ない特殊なケースも省略されています。

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;
于 2010-06-08T10:06:05.910 に答える
1

クエリを閉じて再度開く前に一意のキー フィールドの値を保存し、再度開いたLocate後にレコードに保存します。DisableControls/EnableControls画面の更新を防止します。

于 2010-06-08T08:30:57.907 に答える
0

レコードの位置は、Query/Tableオブジェクトから取得した結果セットの並べ替え順序に大きく依存します。まったく注文しない場合、サーバーから取得する順序は実装で定義されているため、変更が行われていなくても、クエリを再度開いたときにレコードが同じ順序になることを保証できません。少なくともMSSQLとFirebirdでは、Order By句が使用されていない場合、結果の順序が異なります。

再配置に関しては、TOndrejソリューションが最も安全なソリューションだと思います。結果セットの主キーを使用して、グリッドを適切なレコードに再配置します。

于 2010-06-08T18:39:14.897 に答える
0

私の頭に浮かんだ単純なコード:

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;
于 2010-06-08T09:00:54.650 に答える