Jak pracovat se záznamy v mřížce TcxGrid od Developer Express

7. 2. 2020, Vladimír Klaus, přečteno 114x

Delphi

Komponenta TcxGrid do Developer Express je neuvěřitelně mocná, ale také velmi složitá. Používám ji v podstatě ve všech svých Delphi aplikacích už velice dlouho. Přesto, že na řadu věcí jsou návody, tento jednoduchý a zároveň komplexní mi chyběl, tak jsem ho sestavil a trochu okomentoval.

Jak pracovat se záznamy v mřížce TcxGrid od Developer Express, obr. 1

Doporučuji přečíst všechny body a až podle konkrétní situace se rozhodnout pro nejvhodnější postup, případně přístupy kombinovat.

Článek bude postupně doplňován a aktualizován dle využití dalších komponent a situací, na které při programování narazím.

Většina operací níže uvedených je založena na fokusování dané řádky a dále na tom, že mřížka je synchronizována s daty. Tedy, že fokusování řádky znamená, že se i v DB tabulce nastaví aktuální záznam odpovídající mřížce, a pak bude možné s ním "datově" pracovat. Aby toto fungovalo, musí být splněno:

//nastavení synchronizace mřížky a databáze
DataController.DataModeController.SyncMode=true;

//A hlavně se NESMÍ použít toto, protože pak fokusování nefunguje!!!
//--- TableFirmy.DisableControls;

Pokud jste zvyklí, že se mřížka během operací neaktualizuje (a tudíž probíhají operace velmi rychle), můžete zde zvolit jinou metodu:

// --- Vypnutí a zapnutí interakce mřížky ---
FirmyGridView.BeginUpdate(lsimImmediate);
FirmyGridView.EndUpdate(lsimImmediate);

1. Všechny záznamy z DataSetu

Pokud potřebujete přistupovat ke všem záznamům, je zbytečné to řešit přes mřížku (nemusí aktuálně zobrazovat všechny záznamy).

while not TableFirmy.Eof do begin
  TableFirmy.Next;
end;

Ale pochopitelně je možné, že nevíte, odkud jsou data zobrazená v mřížce nebo zkrátka neexistuje přímý přístup, pak je možné se odkázat na datový zdroj takto:

FirmyGridView.DataController.DataSet
FirmyGridView.DataController.DataSource.DataSet

2. Označené/vybrané záznamy v mřížce

Tímto "fokusováním" se vlastně přesunu na záznam přímo v Datasetu a mohu s ním normálně pracovat, jako by to s mřížkou nijak nesouviselo.

PocetOznacenych:=FirmyGridView.Controller.SelectedRecordCount;
for i:=0 to PocetOznacenych-1 do begin
  FirmyGridView.Controller.SelectedRecords[i].Focused:=true;
end;

3. Všechny zobrazené záznamy z mřížky (respektuje se i filtr)

Je to podobné, jako u předchozího případu - je třeba postupně jeden po druhém zobrazený záznam "fokusovat". Jen se to bohužel dělá jinak.

Přesto, že se pracuje s filtrovanými záznamy, tak filtr vůbec nemusí být aplikován. A tato metoda si korektně poradí i s tím, když je v mřížce použito seskupení.

PocetZobrazenych:=FirmyGridView.DataController.FilteredRecordCount;
for i:=0 to PocetZobrazenych-1 do begin
  ARecIndex:=FirmyGridView.DataController.FilteredRecordIndex[i];
  FirmyGridView.DataController.FocusedRecordIndex:=ARecIndex;
end;

Určitě se vyhněte tomuto přístupu, protože to sice funguje, ale při použití seskupení už ne - přistupuje se opravdu k zobrazeným záznamům, ne k těm, co mohou být schovány v zabalené skupině!

// Nepoužívat!!!
//--- FirmyGridView.ViewData.Records[ARecIndex].Focused:=true;

4. Aktuální záznam

Aktuální záznam může být fokusovaný, ale nemusí být vybraný. Proto se to tímto trikem zajistí a pak se už může pokračovat podle bodu 1. Samozřejmě musíte hlídat, zda v té mřížce vůbec něco je zobrazeno.

if FirmyGridView.Controller.SelectedRecordCount=0
  then FirmyGridView.Controller.FocusedRecord.Selected:=true

5. Odstraňování záznamů

Zcela specifickou kapitolou je pak odstraňování záznamů, protože se tím může měnit počet záznamů a může tak lehce dojít k odkazování na již neexistující. Zde je proto naopak velmi důležité použít DisableControls a pak totiž i FilteredRecordCount zachová původní hodnotu (před počátkem mazání) a je tedy bezpečné se na dané záznamy odkazovat.

Také se při odstraňování může hodit zachovat zobrazení, k čemuž mohou pomoci tyto informace.

//co je v mřížce jako první záznam
TopRow:=FirmyViewSimple.Controller.TopRowIndex;
//co je fokusováno
FocusedRow:=FirmyViewSimple.DataController.FocusedRowIndex;

Také bývá potřeba nastavit správný klíč...

//nastavím klíč k hledáni - důležité, jinak nefunguje GetRecordId
OldKeyFieldNames:=DataController.KeyFieldNames;
DataController.KeyFieldNames:='Id';

...tedy především v situaci, že využijete:

var AKey: Variant;
AKey:=DataController.GetRecordId(i)
AKey:=DataController.GetRecordId(DataController.FilteredRecordIndex[i])

Řada dalších specifik se pak pojí s TcxGridServerModeTableView...