CXGrid的使用技巧

CXGrid的使用技巧

========================================================================== 

在主从TableView中根据主TableView得到对应的从TableView 
var 
ADetailDC: TcxGridDataController; 
AView: TcxCustomGridTableView; 
begin 
with cxGrid1DBTableView1.DataController do 
ADetailDC := TcxGridDataController(GetDetailDataController(FocusedRecordIndex, 0)); 
AView := ADetailDC.GridView; 
end; 

============================================================================== 

定位在第一行并显示内置编辑器 

cxDBVerticalGrid1.FocusedRow := cxDBVerticalGrid1.Rows[0]; 
cxDBVerticalGrid1.ShowEdit; 

============================================================================== 

隐藏 "<No data to display>" 字符串 

该文本存储在scxGridNoDataInfoText资源字符串,可以将该资源字符串的内容设为空 
来隐藏该文本。 

uses cxClasses, cxGridStrs; 
... 
cxSetResourceString(@scxGridNoDataInfoText, ''); 

//如果"<No data to display>" 字符串已经显示,需要调用: 
<View>.LayoutChanged; 

============================================================ 

删除应用过滤后的行 

var 
I: Integer; 
begin 
with <GridView> do 
for I := 0 to ViewData.RecordCount - 1 do 
begin 
ViewData.Records[0].Focused := True; 
DataController.DataSet.Delete; 
end; 

============================================================= 

根据单元的值设置样式 

procedure <aForm>.<aColumn>StylesGetContentStyle( 
Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord; 
AItem: TcxCustomGridTableItem; out AStyle: TcxStyle); 
begin 
if ARecord.Values[AItem.Index] = aSomeValue then 
AStyle := <aSomeStyle>; 
end; 

procedure <aForm>.<aView>StylesGetContentStyle( 
Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord; 
AItem: TcxCustomGridTableItem; out AStyle: TcxStyle); 
var 
AColumn: TcxCustomGridTableItem; 
begin 
AColumn := (Sender as TcxGridDBTableView).GetColumnByFieldName('Email'); 
if VarToStr(ARecord.Values[AColumn.Index]) = '' then 
AStyle := cxStyleNullEmail; 
end; 

============================================================================== 

TcxCustomGridTableView.FindItemByName, TcxGridDBTableView.GetColumnByFieldName or 
TcxGridDBDataController.GetItemByFieldName 

with cxGrid1DBBandedTableView1.DataController do 
AValue := Values[FocusedRecordIndex, GetItemByFieldName('SomeFieldName').Index]; 

=================================================================== 

动态生成BandedView 

var 
AView: TcxCustomGridView; 
begin 
AView := <cxGrid>.CreateView(TcxGridDBBandedTableView); 
TcxGridDBBandedTableView(AView).DataController.DataSource := <DataSource>; 
TcxGridDBBandedTableView(AView).Bands.Add; 
with TcxGridDBBandedTableView(AView).Bands.Add do 
begin 
Visible := False; 
FixedKind := fkLeft; 
end; 
TcxGridDBBandedTableView(AView).DataController.CreateAllItems; 
<cxGridLevel>.GridView := AView;   

====================================================================== 

当底层数据集为空时显示一条空记录 

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;

posted @ 2014-04-18 13:15  麦麦提敏  阅读(1435)  评论(0编辑  收藏  举报