Good code samples for cxGrid

Activate built-in editing controls
1) <aView>.Controller.EditingController.ShowEdit(<aColumn>);
2) <aView>.Controller.EditingController.StartEditShowingTimer(<aColumn>);
3) <aView>.Controller.EditingItem := <aColumn>;
4) <aColumn>.Editing := True;
Hide built-in editing controls
<aView>.Controller.EditingController.HideEdit(True);
Remove a grouping column
<aColumn>.GroupIndex := -1;
<aColumn>.Visible := True;
Save changes to the database
procedure <aForm>.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if (<aGrid>.FocusedView <> nil) and (<aGrid>.FocusedView.DataController.EditState <> []) then
<aGrid>.FocusedView.DataController.Post;
end;
Set built-in right-click menu
The built-in right-click menu includes two menus: cxGridStdHeaderMenu, TcxGridStdFooterMenu
uses cxGridStdPopupMenu;
procedure TForm1.cxGridPopupMenu1Popup(ASenderMenu: TComponent;
AHitTest: TcxCustomGridHitTest; X, Y: Integer; var AllowPopup: Boolean);
begin
if ASenderMenu is TcxGridStdHeaderMenu then
TcxGridStdHeaderMenu(ASenderMenu).OnPopup := StdHeaderMenuPopup;
end;
procedure TForm1.StdHeaderMenuPopup(Sender: TObject);
var
I: Integer;
begin
with TcxGridStdHeaderMenu(Sender).Items do
for I := 0 to Count – 1 do
if Items[I].Caption = ‘Group By Box’ then
begin
Items[I].Enabled := False;
System.Break;
end
end;
Get the value of the selected record
1) View.DataController.DataModeController.GridMode = when false
RecIdx := View.Controller.SelectedRecords[i].RecordIndex;
ColIdx := View.DataController.GetItemByFieldName(AFieldName).Index;
OutputVal := View.DataController.Values[RecIdx, ColIdx];
//RecID := View.DataController.GetRecordId(RecIdx);
//OutputVal := ADataSet.Lookup(View.DataController.KeyFieldNames, RecID, AFieldName);
2) View.DataController.DataModeController.GridMode = when true
Bkm := View.DataController.GetSelectedBookmark(ASelectedRecordIndex);
if ADataSet.BookmarkValid(TBookmark(Bkm)) then
begin
ADataSet.Bookmark := TBookmark(Bkm);
OutputVal := ADataSet.FieldByName(AFieldName).Value;
end;
View.BeginUpdate;
View.DataController.BeginLocate;
try
// make changes here…
finally
View.DataController.EndLocate;
View.EndUpdate;
end;
Disable the built-in right-click Footer menu in GridMode
uses cxGridStdPopupMenu;
procedure cxGridPopupMenuOnPopup(…)
begin
if (ASenderMenu is TcxGridStdFooterMenu) and
<GridView>.DataController.DataModeController.GridMode then
AllowPopup := False;
end;
The master-slave table can only expand one group at any time
procedure TForm1.ADetailDataControllerCollapsing(
ADataController: TcxCustomDataController; ARecordIndex: Integer;
var AAllow: Boolean);
var
I: Integer;
C: Integer;
begin
AAllow := False;
C := 0;
for I := 0 to ADataController.RecordCount – 1 do
begin
if ADataController.GetDetailExpanding(I) then
Inc(C);
if C > 1 then
AAllow := True;
end;
end;
procedure TForm1.ADetailDataControllerExpanding(
ADataController: TcxCustomDataController; ARecordIndex: Integer;
var AAllow: Boolean);
begin
ADataController.CollapseDetails;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
cxGrid1DBTableView1.DataController.OnDetailExpanding := ADetailDataControllerExpanding;
cxGrid1DBTableView1.DataController.OnDetailCollapsing := ADetailDataControllerCollapsing;
end;
Dynamically create levels (Level) and views (View)
var
Grid: TcxGrid;
Level: TcxGridLevel;
View: TcxGridDBTableView;
begin
// Creates a Grid instance
Grid := TcxGrid.Create(SomeOwner);
Grid.Parent := SomeParent;
// Creates a Level
Level := Grid.Levels.Add;
Level.Name := ‘SomeLevelName’;
// Creates a View
View := Grid.CreateView(TcxGridDBTableView) as TcxGridDBTableView;
View.Name := ‘SomeViewName’;
// … and binds it to the Level
Level.GridView := View;
// Hooks up the View to the data
View.DataController.DataSource := SomeDataSource;
// … and creates all columns
View.DataController.CreateAllItems;
end;
Get the record corresponding to the total row of Group Footer
procedure TForm1.cxGrid1DBTableView1CustomDrawFooterCell(
Sender: TcxGridTableView; ACanvas: TcxCanvas;
AViewInfo: TcxGridColumnHeaderViewInfo; var ADone: Boolean);
var
ALevel, ADataGroupIndex: Integer;
AGridRecord, AGroupRecord: TcxCustomGridRecord;
begin
if AViewInfo is TcxGridRowFooterCellViewInfo and // Row footer
(TcxGridDBColumn(AViewInfo.Column).DataBinding.FieldName = ‘Area’) then // Area column
begin
AGridRecord := TcxGridRowFooterCellViewInfo(AViewInfo).GridRecord;
ALevel := TcxGridRowFooterCellViewInfo(AViewInfo).Container.GroupLevel;
ADataGroupIndex := Sender.DataController.Groups.DataGroupIndexByRowIndex[AGridRecord.Index];
if ADataGroupIndex <> -1 then
begin
AGroupRecord := AGridRecord;
while AGroupRecord.Level <> ALevel do
AGroupRecord := AGroupRecord.ParentRecord;
AViewInfo.Text := AGroupRecord.DisplayTexts[0];
end;
end;
end;
Access filtered records
var
I: Integer;
begin
Memo1.Lines.Clear;
with cxGrid1DBTableView1.DataController do
for I := 0 to FilteredRecordCount – 1 do
Memo1.Lines.Add(DisplayTexts[FilteredRecordIndex[I], 0]);
end;
Get the Font of the unit
cxGrid1DBTableView1.ViewInfo.RecordsViewInfo.Items[1].GetCellViewInfoByItem(
cxGrid1DBTableView1Company).EditViewInfo.Font;
Find the Level object based on the Level name
function GetLevelByName(AGrid: TcxGrid; ALevelName: string): TcxGridLevel;
function LoopThroughLevels(ALevel: TcxGridLevel; ALevelName: string): TcxGridLevel;
var
I: Integer;
begin
Result := nil;
for I := 0 to ALevel.Count – 1 do
begin
if ALevel[I].Name = ALevelName then
begin
Result := ALevel[I];
Exit;
end;
if ALevel[I].Count > 0 then
begin
Result := LoopThroughLevels(ALevel[I], ALevelName);
if Result <> nil then
Exit;
end;
end;
end;
var
I: Integer;
begin
Result := nil;
for I := 0 to AGrid.Levels.Count – 1 do
begin
if AGrid.Levels[I].Name = ALevelName then
begin
Result := AGrid.Levels[I];
Exit;
end;
if AGrid.Levels[I].Count > 0 then
begin
Result := LoopThroughLevels(AGrid.Levels[I], ALevelName);
if Result <> nil then
Exit;
end;
end;
end;
Specify the default path for Filter Builder to open/save the filter file
uses
…, cxFilterControlDialog;
procedure TForm.GridView1FilterControlDialogShow(
Sender: TObject);
begin
TfmFilterControlDialog(Sender).OpenDialog.InitialDir := ‘D:/’
end;
Save/restore layout with summary rows
<TableView>.StoreToIniFile(‘c:/Grid.ini’, True, [gsoUseSummary]);
<GridView>.RestoreFromIniFile(<inifilename>,True,False {or True, optional},[gsoUseSummary]);
Move to the first line when unfiltering
uses
cxCustomData;
procedure TYour_Form.AViewDataControllerFilterChanged(Sender: TObject);
var
Filter: TcxDataFilterCriteria;
begin
with Sender as TcxDataFilterCriteria do
if IsEmpty then
DataController.FocusedRowIndex := 0;
end;
Move to the first row after sorting
You can set DataController.Options.FocusTopRowAfterSorting := True, or you can use the following code:
uses
cxCustomData;
procedure TYour_Form.Your_ViewDataControllerSortingChanged(Sender: TObject);
begin
TcxCustomDataController(Sender).FocusedRowIndex := 0;
end;
Determine whether the current line is the first or last line
You can use the IsBOF, IsEOF methods of DataController, or:
<AView>.Controller.Controller.FocusedRow.IsFirst
<AView>.Controller.Controller.FocusedRow.IsLast
Find records based on specified value
DataController provides several methods to get the RecordIndex corresponding to the specified value
For Bound View you can use the FindRecordIndexByKeyValue method
Edit and display the Blob field
The Properties of this field is set to BlobEdit, and the BlobPaintStyle property is set to bpsText
Get the number of visible rows
<View>.ViewInfo.VisibleRecordCount
Set the saved row as the current row
const
CM_SETFOCUSEDRECORD = WM_USER + 1002;
type
TForm1 = class(TForm)
cxGrid1DBTableView1: TcxGridDBTableView;
cxGrid1Level1: TcxGridLevel;
cxGrid1: TcxGrid;
dxMemData1: TdxMemData;
dxMemData1Field1: TStringField;
dxMemData1Field2: TIntegerField;
DataSource1: TDataSource;
cxGrid1DBTableView1RecId: TcxGridDBColumn;
cxGrid1DBTableView1Field1: TcxGridDBColumn;
cxGrid1DBTableView1Field2: TcxGridDBColumn;
Timer1: TTimer;
CheckBox1: TCheckBox;
procedure Timer1Timer(Sender: TObject);
procedure dxMemData1AfterPost(DataSet: TDataSet);
procedure CheckBox1Click(Sender: TObject);
private
procedure CMSetFocusedRecord(var Msg: TMessage); message CM_SETFOCUSEDRECORD;
public
{ Public declarations }
end;
var
Form1: TForm1;
FocusedIdx: Integer;
implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject);
begin
dxMemData1.AppendRecord([”, IntToStr(Random(1000)), Random(1000)]);
end;
procedure TForm1.dxMemData1AfterPost(DataSet: TDataSet);
begin
PostMessage(Handle, CM_SETFOCUSEDRECORD, Integer(cxGrid1DBTableView1), MakeLParam(cxGrid1DBTableView1.Controller.FocusedRowIndex, cxGrid1DBTableView1.Controller.TopRowIndex));
end;
procedure TForm1.CMSetFocusedRecord(var Msg: TMessage);
begin
TcxGridDBTableView(msg.WParam).Controller.FocusedRowIndex := Msg.LParamLo;
TcxGridDBTableView(msg.WParam).Controller.TopRowIndex := Msg.LParamHi;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
Timer1.Enabled := TCheckBox(Sender).Checked;
end;
end.
Delete record and get focus
procedure TForm1.BtnDeleteClick(Sender: TObject);
var
FocusedRow, TopRow: Integer;
View: TcxGridTableView;
DataController: TcxGridDataController;
begin
View := cxGrid1.FocusedView as TcxGridTableView;
DataController := View.DataController;
// Remember the top row (the vertical scrollbar position)
TopRow := View.Controller.TopRowIndex;
// Remember the focused row(!) index
FocusedRow := DataController.FocusedRowIndex;
DataController.DeleteFocused;
// After deletion the same row must be focused,
// although it will correspond to a different data record
DataController.FocusedRowIndex := FocusedRow;
// Restore the top row
View.Controller.TopRowIndex := TopRow;
end;