关于cxgrid使用的方法

来源:互联网 发布:淘宝怎么继续延长收货 编辑:程序博客网 时间:2024/04/30 04:55

cxGrid控件功能很强大,有许多方法及属性,其中有一个属性gridmode

当你设置gridmode=true时,会提高查询速度,为false时则反之,为什么如此,在网上有相关的贴子

详见:详见:http://topic.csdn.net/t/20041025/08/3487114.html 

************************************************

Specifies whether a lookup grid is in GridMode. 

property GridMode: Boolean; 

Description 
You can use the GridMode property to speed up working with large lookup datasets (datasets displayed in the dropdown). 
When Grid Mode is not set, a lookup editor loads all records into memory upon connecting to a dataset.  For large lookup datasets, this can result in lowering performance. 
Setting the GridMode property to True enables caching of edit values and display texts.  If required edit value and display text are not present in the cache, they are obtained from the lookup dataset and stored in the cache for future use.  This considerably increases the performance, when the lookup combobox is used as an in-place editor in a Grid control. 

Grid Mode imposes some restrictions on working with the editor and lookup dataset: 


Grid Mode imposes some restrictions on working with the editor and lookup dataset: 

?the edit box of the lookup editor displays a value (TField.AsString) rather than display text of the field addressed by the ListFieldItem property.

?similarly, an incremental search is performed against field values rather than display texts. 

?you must not navigate the lookup dataset programmatically as this can conflict with the Locate method used by the editor itself. 

The default value of the GridMode property is False.

********************************************

 

当设置gridmode=true时,则在cxGrid上设置的filtering,sorting,footer中的合计信息均无效(几天前做一个模块时发现的)。

我要实现的功能如下:

1.在cxgrid上显示一些信息(连接数据集很容易实现)

2.每列要有filter的功能(每一列的filtering=true)

3.要有一个合计列(footer,合计的记录数,数量,金额等)

4.可以选择部分信息,然后统计更新某一列或几列的值

其它的还有许多,主要的功能是想把对于Excel操作的相关操作用程序来实现,要达到信息共享,方便统计查询等但最主要的用程序不能增加工作量(与Excel相比)

 

在實現過程想了很多辦法為子操作能够快速簡單,處理過程

1.將一些繁瑣的查詢條件進行分析,然后進行分類,使其簡單化

2.對于复制粘貼等,采用了對像,指針及類似Excel的操作方法實現

3.增加多种條件的篩選及統計,做相關的統計報表避免重复的工作

......

在做的過程中有一個問題,就是在選擇性更新過程中如何刷新使用戶能够立刻看到結果

第一种方法:

增加刷新的方法,利用update語句來實現更新,然后commit,最后根據選定的條件重新刷新界面,這是我用的比較多的,但目前不方便,刷新后,我看不到我正在更改的是哪條或哪几條記錄了(如果很多數據)

第二种方法:

利用dataset的edit,post方法進行更新

a.

 

    for i:= 0 to DSRFTDAVEW.Controller.SelectedRowCount-1 do

    begin

      DSRFTDAVEW.DataController.FocusSelectedRow(i); //这种方法需要设置 gridmode=true,但此时会将filtering,sorting,footer等失效

      OraQuery1.Edit;

      OraQuery1.FieldByName('FeatSN').Value := SerialNO;

    end;

這樣要首先設置gridmode=true,但就會出現最開始提到的問題
我試著在修改時將gridmode=true,當修寇成后再將其gridmode=false,雖然可以修改,但是在修改過程中如果利用某列的filtering先篩選一些數據后,就會出現問題。
b.
利用DSRFTDAVEW.Controller.FocusedRow := DSRFTDAVEW.Controller.SelectedRows[i];來獲取數據的焦點即用cxgridview的controller來實現,這樣就可以避免gridmode=true的衝突。
下面是在网上找到的相關的資料
2009-03-27 21:31
激活内置编辑控件 
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; 
此楼回复Re: 
--------------------------------------------------------------------------------
====================================================================== 
获得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; 
//=======================================================================================
数据库中的财务表为: 
ID 收支类型 金额 其它属性 
其中收支类型只有两种值:0 表示收入,1 表示支出 ;金额都是正数。 
设置cxGrid的Footer 可以使得在显示时,列表的下方出现汇总行:“金额”的和 
同样设置Default For Groups可以使得在用户拖动表头属性实现分组时,显示组内的汇总行:“金额”的和。 
上面说的,用过cxGrid应该都会,下面就有这么一个问题 
如果我想使汇总行的值变为如下的值应该怎样实现: 
收支类型为0的金额的和 - 收支类型为1的金额的和 
实现Footer的功能好办,因为它的值不会变,自己用循环写一个就完了,但是Default For Groups的功能就不好说了,因为它的值是根据用户拖动的属性计算的,而且还有可能是多层分组,想不出来了,所有到这来问 
是不是要设置什么属性?或者cxGrid根本就没这个功能,那该用什么方法解决?希望哪位帮我解决,谢谢了先! 
给你一个例子,可能对你有帮助, 
with tvOrders.DataController.Summary do 
begin 
BeginUpdate; 
try 
SummaryGroups.Clear; 
//The first summary group 
with SummaryGroups.Add do 
begin 
//Add proposed grouping column(s) 
TcxGridTableSummaryGroupItemLink(Links.Add).Column := tvOrdersCustomerID; 
//Add summary items 
with SummaryItems.Add as TcxGridDBTableSummaryItem do 
begin 
Column := tvOrdersPaymentAmount; 
Kind := skSum; 
Format := 'Amount Paid: $,0'; 
end; 
with SummaryItems.Add as TcxGridDBTableSummaryItem do 
begin 
Column := tvOrdersPaymentAmount; 
Kind := skCount; 
Format := 'Records: 0'; 
end; 
end; 
//The second summary group 
with SummaryGroups.Add do 
begin 
//Add proposed grouping column(s) 
TcxGridTableSummaryGroupItemLink(Links.Add).Column := tvOrdersProductID; 
//Add summary items 
with SummaryItems.Add as TcxGridDBTableSummaryItem do 
begin 
Column := tvOrdersQuantity; 
Kind := skSum; 
Position := spFooter; 
Format := 'TOTAL = 0'; 
end; 
with SummaryItems.Add as TcxGridDBTableSummaryItem do 
begin 
Column := tvOrdersPurchaseDate; 
Kind := skMin; 
Position := spFooter; 
end; 
end; 
finally 
EndUpdate; 
end; 
end;
2007-7-19 12:56:41 go on
订单号 商品名 单价 数量 金额
001 aa 11.00 2 22.00
001 bb 2.00 2 4.00
001 cc 3.00 3 9.00
----------------------合计 7 35.00
002 ee 11.00 2 22.00
002 bb 3.00 2 6.00
002 cc 3.00 3 9.00
----------------------合计 7 37.00
总计14 72.00
每个单号分一个小结,能实现吗?
最后在底下实现总的合计
回复人:dctony() ( ) 信誉:100 2007-1-12 21:48:23 得分:100
?
可以的,cxGrid的功能比你想象的还要强大。
1.你先放一个cxGrid,设置好View,设置View.DataController连接的DataSource
2.激活DataSource连接的DataSet,双击cxGrid,点击Retrieve Fields,取得所有的Column
3.设置View的OptionsView.Footer=True,OptionsView.GroupFooters=True,这是为了把分组小计和总计面板显示出来
4.将“订单号”字段拖到cxGrid上方的分组面板(GroupbyBox),将数据按“订单号”分组。这时你会发现单身所有的数据都缩起来了,如果想使所有的数据都展开,可以设置View.DataController.Options.dcoGroupsAlwaysExpanded=True
5.设置分组小计:把View.DataController.Summary.DefaultGroupSummaryItems点开,新增一个Item,Column属性在下拉里选择“数量”字段,FieldName属性为空,Format属性可以设置数值的显示格式,Kind属性下拉skSum加总,Position属性一定要选择spFooter。
6.设置总计:把View.DataController.Summary.FooterSummaryItems点开,新增一个Item,Column属性在下拉里选择“数量”字段,FieldName属性为空,Format属性可以设置数值的显示格式,Kind属性下拉skSum加总,Position属性一定要选择spFooter。
大功告成,按F9看一下胜利果实吧。
再奉送一个技巧,在Form1再放一个TcxGridPopupMenu控件,就在cxGrid控件旁边的那个,把TcxGridPopupMenu的Grid属性设置成你的cxGrid。
然后运行程序,在运行状态,点击Grid上的所有地方,左键或右键,你都会有意外收获。
ExpressQuantumGrid控件实在是太复杂,太庞大,最好的了解它的方法就是查帮助。
贴一些小技巧,希望与各位使用cxGrid的朋友共同交流 
各位有什么好个技巧也可以贴出来: 
技巧二:在内置右键菜单的后面增加菜单项 
首先应在Form上加一个cxGridPopupMenu控件 以启用右键菜单 
UseBuildInPopupMenus设为True 
procedure TFormItemList.FormCreate(Sender: TObject); 
var 
AMenu: TComponent; 
FMenuItem, FSubMenuItem: TMenuItem; 
begin 
AMenu := nil; 
if cxGridPopupMenu.BuiltInPopupMenus.Count = 0 then 
Exit; 
AMenu := cxGridPopupMenu.BuiltInPopupMenus[0].PopupMenu; //第一个内置右键菜单(表头菜单) 
if Assigned(AMenu) and AMenu.InheritsFrom(TPopupMenu) then 
begin 
TPopupMenu(AMenu).AutoHotkeys := maManual; //手动热键 
//------------------------- 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Caption := '-'; 
FMenuItem.Name := 'miLineForGroup'; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//展开所有组 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Name := 'miExpandAllGroup'; 
FMenuItem.Caption := '展开所有组(&X)'; 
FMenuItem.OnClick := miExpandAllGroupClick; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//收缩所有组 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Name := 'miCollapseAllGroup'; 
FMenuItem.Caption := '收缩所有组(&O)'; 
FMenuItem.OnClick := miCollapseAllGroupClick; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//------------------------- 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Caption := '-'; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//过滤面板 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Name := 'miFilterPanel'; 
FMenuItem.Caption := '过滤面板(&P)'; 
//自动显示 
FSubMenuItem := TMenuItem.Create(Self); 
FSubMenuItem.Name := 'miFilterPanelAuto'; 
FSubMenuItem.Caption := '自动(&A)'; 
FSubMenuItem.RadioItem := True; 
FSubMenuItem.GroupIndex := 5; //指定同一组 
FSubMenuItem.Checked := True; 
FSubMenuItem.OnClick := miFilterPanelClick; 
FMenuItem.Add(FSubMenuItem); //加入二级子菜单 
//总是显示 
FSubMenuItem := TMenuItem.Create(Self); 
FSubMenuItem.Name := 'miFilterPanelAlways'; 
FSubMenuItem.Caption := '总是显示(&W)'; 
FSubMenuItem.RadioItem := True; 
FSubMenuItem.GroupIndex := 5; 
FSubMenuItem.OnClick := miFilterPanelClick; 
FMenuItem.Add(FSubMenuItem); 
//从不显示 
FSubMenuItem := TMenuItem.Create(Self); 
FSubMenuItem.Name := 'miFilterPanelNerver'; 
FSubMenuItem.Caption := '从不显示(&N)'; 
FSubMenuItem.RadioItem := True; 
FSubMenuItem.GroupIndex := 5; 
FSubMenuItem.OnClick := miFilterPanelClick; 
FMenuItem.Add(FSubMenuItem); 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//自定义过滤 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Name := 'miCustomFilter'; 
FMenuItem.Caption := '自定义过滤(&M)'; 
FMenuItem.OnClick := miCustomFilterClick; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//过滤管理器 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Name := 'miFilterBuilder'; 
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 44); //添加图标图像 
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1; //指定图标序号 
FMenuItem.Caption := '过滤管理器'; 
FMenuItem.OnClick := Self.miFilterBuilderClick; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//--------------------- 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Caption := '-'; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//导出 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Name := 'miExport'; 
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 37); 
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1; 
FMenuItem.Caption := '导出(&E)'; 
FMenuItem.OnClick := Self.miExportClick; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
//打印 
FMenuItem := TMenuItem.Create(Self); 
FMenuItem.Name := 'miPrint'; 
FMenuItem.Caption := '打印(&P)'; 
TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend, 14); 
FMenuItem.ImageIndex := TPopupMenu(AMenu).Images.Count - 1; 
FMenuItem.OnClick := Self.miPrintClick; 
TPopupMenu(AMenu).Items.Add(FMenuItem); 
end; 
end; 
procedure TFormItemList.miExportClick(Sender: TObject); 
var 
FileName, FileExt, msg: String; 
begin 
if Self.aqyQuery.IsEmpty then 
begin 
msg := '没有导出数据...'; 
Application.MessageBox(PChar(msg), PChar(Application.Title), 
MB_OK or MB_IconWarning); 
Exit; 
end; 
Self.SaveDialogExport.Filter := 'Excel文件 (*.xls)|*.xls|XML文件 (*.xml)|*.xml' 
+ '|文本文件 (*.txt)|*.txt|网页文件 (*.html)|*.html'; 
Self.SaveDialogExport.Title := '导出为'; 
if not Self.SaveDialogExport.Execute then 
Exit; 
FileName := Self.SaveDialogExport.FileName; 
FileExt := LowerCase(ExtractFileExt(FileName)); 
if FileExt = '.xls' then 
ExportGrid4ToExcel(FileName, Self.cxGrid1) 
else if FileExt = '.xml' then 
ExportGrid4ToXML(FileName, Self.cxGrid1) 
else if FileExt = '.txt' then 
ExportGrid4ToText(FileName, Self.cxGrid1) 
else if FileExt = '.html' then 
ExportGrid4ToHTML(FileName, Self.cxGrid1) 
else 
begin 
msg := '不支持的导出文件类型...'; 
Application.MessageBox(PChar(msg), PChar(Application.Title), 
MB_OK or MB_IconError); 
Exit; 
end; 
msg := '导出完成...'; 
Application.MessageBox(PChar(msg), PChar(Application.Title), 
MB_OK or MB_IconInformation); 
end; 
procedure TFormItemList.miPrintClick(Sender: TObject); 
begin 
//打印 
Self.dxComponentPrinter.Preview(True, Self.dxComponentPrinterLink1); 
end; 
procedure TFormItemList.cxGridPopupMenuPopup(ASenderMenu: TComponent; 
AHitTest: TcxCustomGridHitTest; X, Y: Integer; var AllowPopup: Boolean); 
begin 
if GetHitTypeByHitCode(AHitTest.HitTestCode) = gvhtColumnHeader then //右击列标题时 
begin 
//if tvResult.DataController.Groups.GroupingItemCount > 0 then 
if tvResult.GroupedColumnCount > 0 then //有分组时显示 
begin 
TMenuItem(Self.FindComponent('miLineForGroup')).Visible := True; 
TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible := True; 
TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible := True; 
end 
else 
begin 
TMenuItem(Self.FindComponent('miLineForGroup')).Visible := False; 
TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible := False; 
TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible := False; 
end; 
end; 
end; 
procedure TFormItemList.miFilterBuilderClick(Sender: TObject); 
begin 
//过滤管理器 
//弹出Filter Builder Dialog对话框 
tvResult.Filtering.RunCustomizeDialog; 
end; 
procedure TFormItemList.miCustomFilterClick(Sender: TObject); 
var 
AHitTest: TcxCustomGridHitTest; 
begin 
//自定义过滤 
//弹出Custom Filter Dialog对话框 
AHitTest := cxGridPopupMenu.HitTest; 
if GetHitTypeByHitCode(AHitTest.HitTestCode) = gvhtColumnHeader then //获得右击的列 
tvResult.Filtering.RunCustomizeDialog(TcxGridColumnHeaderHitTest(AHitTest).Column); 
end; 
procedure TFormItemList.miFilterPanelClick(Sender: TObject); 
var 
mi: TMenuItem; 
begin 
//隐藏/显示过滤面板 
mi := TMenuItem(Sender); 
mi.Checked := True; 
if mi.Name = 'miFilterPanelAlways' then 
tvResult.Filtering.Visible := fvAlways 
else if mi.Name = 'miFilterPanelNerver' then 
tvResult.Filtering.Visible := fvNever 
else 
tvResult.Filtering.Visible := fvNonEmpty; 
end; 
procedure TFormItemList.miExpandAllGroupClick(Sender: TObject); 
begin 
//展开所有组 
tvResult.DataController.Groups.FullExpand; 
end; 
procedure TFormItemList.miCollapseAllGroupClick(Sender: TObject); 
begin 
//收缩所有组 
tvResult.DataController.Groups.FullCollapse; 
end; 
此楼回复Re: 
--------------------------------------------------------------------------------
在用,留名
此楼回复Re: 
--------------------------------------------------------------------------------
技巧三 按条件计算合计值 
在Footer的第一列显示[合计:] 
加一个Summary项,Column设为Grid的第一列,Kind设为skNone 
在该Summary项的OnGetText事件中,输入: 
procedure TFormExpense.tvExpenseTcxGridDBDataControllerTcxDataSummaryFooterSummaryItems2GetText( 
Sender: TcxDataSummaryItem; const AValue: Variant; AIsFooter: Boolean; 
var AText: String); 
begin 
AText := '合计:'; 
end; 
按条件汇总: 
在TableView的DataController->Summary->FooterSummary->OnSummary事件中,输入: 
procedure TFormExpense.tvExpenseDataControllerSummaryFooterSummaryItemsSummary( 
ASender: TcxDataSummaryItems; Arguments: TcxSummaryEventArguments; 
var OutArguments: TcxSummaryEventOutArguments); 
begin 
//得到字段名 TcxDBDataSummaryItem(Arguments.SummaryItem).FieldName; 
if (ASender.DataController.Values[Arguments.RecordIndex, tvExpenseLevel.Index] > 1) //只统计Level列=1的值 
and (TcxDBDataSummaryItem(Arguments.SummaryItem).Kind = skSum) then 
OutArguments.Value := 0; //Level > 1的统计值设为0 
end; 
此楼回复Re: 
--------------------------------------------------------------------------------
借贵地一用,问个CXGrid问题,在cxgrid中如何使一些行不能编辑,如:字段isenable = false的行
此楼回复Re: 
--------------------------------------------------------------------------------
楼上的问题 
请参考下面的技巧 
技巧四:根据某列的值设定其它列的可编辑性 
procedure TFormUser.tvUserEditing(Sender: TcxCustomGridTableView; 
AItem: TcxCustomGridTableItem; var AAllow: Boolean); 
begin 
//如果第三列值为True,则第4列不能修改 
if (tvUser.Controller.FocusedRecord.Values[2] = True) and (AItem.Index = 4) then 
AAllow := False 
else 
AAllow := True; 
end; 
此楼回复Re: 
--------------------------------------------------------------------------------
技巧五:保存/恢复Grid布局 
//恢复布局 
IniFileName := ExtractFilePath(Application.ExeName) + 'Layout/' + Self.Name + '.ini'; 
if FileExists(IniFileName) then 
Self.tvResult.RestoreFromIniFile(IniFileName) //从布局文件中恢复 
else 
begin 
Self.tvResult.BeginUpdate; 
for i := 0 to Self.tvResult.ItemCount - 1 do 
Self.tvResult.Items[i].ApplyBestFit; //调整为最佳宽度 
Self.tvResult.EndUpdate; 
end; 
//保存布局 
IniFileName := ExtractFilePath(Application.ExeName) + 'Layout/' + Self.Name + '.ini'; 
if not DirectoryExists(ExtractFileDir(IniFileName)) then 
CreateDir(ExtractFileDir(IniFileName)); 
Self.tvResult.StoreToIniFile(IniFileName); //保存为布局文件 
此楼回复Re: 
--------------------------------------------------------------------------------
借用地问一下:在 cxgrid中,如果我同时选中主表与子表中的记录,怎么样能同时进行对其所选记录进行处理呢。 
我现在只能判断 焦点是在主表还是从表中,然后只能对主表或子表中的数据进行处理。 
此楼回复Re: 
--------------------------------------------------------------------------------
看来用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; 
此楼回复Re: 
--------------------------------------------------------------------------------
====================================================================== 
当底层数据集为空时显示一条空记录 
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得到底层数据集后,再用数据集的 
方法来操作数据。