Mam dataset którego treść wizualizauję w kontrolce TJvDbgrid z pakietu JediComponents.
Potrzebuję wykonać na nim pewną akcję (np. podsumowanie wybranej kolumny), wymagającą chwilowej zmiany pozycji kursora w datacecie, a następnie przywrócić stan datasetu i grida do stanu sprzed akcji, tak aby na ekranie nic się nie zmieniło.
Czyli muszę ustawić w datasecie kursor w pozycji sprzed akcji oraz zadbać aby pozycjonowanie wierszy w gridzie nie uległo zmianie, a w szczególności
pozycja wiersza kursora. Na przykładowym zrzucie ekranu jest to trzeci wiersz od dołu.
W tym celu na podstawie znalezionego w necie przykładu zrobiłem sobie procedurę:
type
THDataset = class(TDataset) // a nice "hack" so we can access protected members
end;
procedure datasetUserAction(Sender: TObject; aDataset: TDataset; aAction: Tnotifyevent);
var
tb: TBookmark;
gridRow: integer;
recNo: integer;
begin
// zapamiętanie stanu datsetu
aDataset.DisableControls;
tb := aDataset.GetBookmark;
recNo := aDataset.recNo;
gridRow := THDataset(aDataset).ActiveRecord;
try
// wykonanie akcji na datasetcie
aAction(Sender);
finally
// przywrócenie datasetu do stanu sprzed akcji
THDataset(aDataset).InternalGotoBookmark(tb);
if THDataset(aDataset).ActiveRecord <> gridRow then
aDataset.MoveBy(gridRow - THDataset(aDataset).ActiveRecord);
aDataset.Resync([rmExact]);
aDataset.freebookmark(tb);
aDataset.EnableControls;
end;
if aDataset.recNo <> recNo then
raise Exception.Create('Zmiana bieżącego rekoru w datasetcie');
end;
Procedura prawidłowo działa mi od lat.
Ale ...
Wszytsko jest ok jeśli aDataset jest typu Tclientdataset.
Problem pojawia się dla typu TFDMemTable. Kursor skacze po datasecie w dziwny sposób a grid nie trzyma na ekranie stałej pozycji bieżącego wiersza.
Sam sposób działania procedury, a dokładniej metod .InternalGotoBookmark oraz .Resync, nie jest dla mnie jasny, ale dla TclinetDataset było ok, więc nie zastanawiałem się nad tym.
Wydaje mi się że kluczowe są różnice w działaniu metody Tdataset.InternalGotoBookmark(tb) oraz w obsłudze wewnętrznego bufora datasetu zawierającego wiersze widoczne w oknie grida.
Co ciekawe, procedura w ogóle nic nie wie o gridzie. Podejrzewam, że interakcja z gridem odbywa się przez wewnętrzny bufor dataseta, którego jednym z elementów jest property activerecord
Czy ktoś podpowie jakiś sposób modyfikacji procedury dla typu TFDMemtable albo podsunie jakiś inny sposób rozwiązania problemu ?
