==========================================================================
====================================================================== 
当底层数据集为空时显示一条空记录 
procedure <Form>.<cxGrid>Enter(Sender: TObject); 
var 
View: TcxGridDBTableView; 
begin 
View := TcxGridDBTableView((Sender as TcxGrid).FocusedView); 
if View.DataController.DataSet.IsEmpty then 
begin 
View.DataController.DataSet.Append; 
View.Controller.EditingController.ShowEdit; 
end; 
end; 
======================================================================= 
在当前View插入记录 
使用FocusedView属性得到当前焦点View,用View.DataController得到对应的Data Controller, 
之后使用Data Controller的方法来操作数据: 
- Append 
- Insert 
- Post 
- Cancel 
- DeleteFocused 
- DeleteSelection 
示例: 
var 
ARecIndex: Integer; 
… 
View.DataController.Append; 
ARecIndex := View.DataController.FocusedRecordIndex; 
View.DataController.Values[ARecIndex, SomeItemIndex] := SomeValue; 
View.DataController.Post; 
另外一种方法是使用View.DataController.DataSource.DataSet得到底层数据集后,再用数据集的 
方法来操作数据。 
======================================================================== 
激活内置编辑控件 
1) <aView>.Controller.EditingController.ShowEdit(<aColumn>); 
2) <aView>.Controller.EditingController.StartEditShowingTimer(<aColumn>); 
3) <aView>.Controller.EditingItem := <aColumn>; 
4) <aColumn>.Editing := True; 
隐藏内置编辑控件 
<aView>.Controller.EditingController.HideEdit(True); 
=========================================================================== 
移除一个分组列 
<aColumn>.GroupIndex := -1; 
<aColumn>.Visible := True; 
=========================================================================== 
保存修改到数据库 
procedure <aForm>.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
if (<aGrid>.FocusedView <> nil) and (<aGrid>.FocusedView.DataController.EditState <> []) then 
<aGrid>.FocusedView.DataController.Post; 
end; 
============================================================================ 
设置内置右键菜单 
内置右键菜单包括二个菜单: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; 
=========================================================================== 
得到选中记录的值 
1) View.DataController.DataModeController.GridMode = 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 = 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; 
============================================================= 
在GridMode禁用内置的右键Footer菜单 
uses cxGridStdPopupMenu; 
procedure cxGridPopupMenuOnPopup(...) 
begin 
if (ASenderMenu is TcxGridStdFooterMenu) and 
<GridView>.DataController.DataModeController.GridMode then 
AllowPopup := False; 
end; 
============================================================== 
主从表任何时候只能展开一个组 
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; 
================================================================= 
动态创建层次(Level)和视图(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;
====================================================================== 
获得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; 
=========================================================================== 
访问过滤之后的记录 
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; 
============================================================================ 
获得单元的Font 
cxGrid1DBTableView1.ViewInfo.RecordsViewInfo.Items[1].GetCellViewInfoByItem( 
cxGrid1DBTableView1Company).EditViewInfo.Font; 
============================================================================ 
根据Level名称找到Level对象 
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; 
============================================================================ 
指定Filter Builder打开/保存过滤文件的默认路径 
uses 
..., cxFilterControlDialog; 
procedure TForm.GridView1FilterControlDialogShow( 
Sender: TObject); 
begin 
TfmFilterControlDialog(Sender).OpenDialog.InitialDir := 'D:\' 
end; 
============================================================================ 
保存/恢复带汇总行的布局 
<TableView>.StoreToIniFile('c:\Grid.ini', True, [gsoUseSummary]); 
<GridView>.RestoreFromIniFile(<inifilename>,True,False {or True, optional},[gsoUseSummary]); 
============================================================================ 
取消过滤时移到第一行 
uses 
cxCustomData; 
procedure TYour_Form.AViewDataControllerFilterChanged(Sender: TObject); 
var 
Filter: TcxDataFilterCriteria; 
begin 
with Sender as TcxDataFilterCriteria do 
if IsEmpty then 
DataController.FocusedRowIndex := 0; 
end; 
============================================================================= 
排序后移到第一行 
可以设置DataController.Options.FocusTopRowAfterSorting := True,也可以使用如下的代码: 
uses 
cxCustomData; 
procedure TYour_Form.Your_ViewDataControllerSortingChanged(Sender: TObject); 
begin 
TcxCustomDataController(Sender).FocusedRowIndex := 0; 
end; 
============================================================================== 
判断当前行是否第一行或最后一行 
可以使用DataController的IsBOF, IsEOF方法,或者: 
<AView>.Controller.Controller.FocusedRow.IsFirst 
<AView>.Controller.Controller.FocusedRow.IsLast 
============================================================================== 
根据指定值查找记录 
DataController提供了好几个方法来得到指定值对应的RecordIndex 
对于Bound View可以使用FindRecordIndexByKeyValue方法 
=============================================================================== 
编辑和显示Blob字段 
该字段的Properties设置为BlobEdit,并将BlobPaintStyle 属性设为 bpsText 
=============================================================================== 
得到可见行数 
<View>.ViewInfo.VisibleRecordCount 
=============================================================================== 
保存后的行设置为当前行 
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. 
================================================================================= 
删除记录并获得焦点 
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;