17. 怎样设计多表头的cxGrid?
解决:cxGrid可以解决如下的表头:
---------------------------------
| 说明1 | 说明2 |
---------------------------------
| 字段1 | 字段2 | 字段3 | 字段4 |
| 字段5 | 字段6 |
| 字段7 | 字段8 | 字段9 |
实现这个很简单,你可以直接在上面拖动字段名,拖动时会显示箭头的,放入你想显示的位置就OK了。或者在鼠标右击cxGrid1DBBandedTableView1菜单里的Edit Layout里也可以拖放。
但是cxGrid不能实现如下的多表头形式:
---------------------------------
| 说明1 | 说明2 |
---------------------------------
| 说明3 | 说明4 | 说明5 | 说明6 |
| 字段1 | 字段2 |
| 字段3 | 字段4 | 字段5 |
不知道有谁能实现这样的多表头?
****************************************************************************
18. 在主从表结构时,当点开“+”时怎样将焦点聚在相应主表的记录上?
解决:
var
HitTest: TcxCustomGridHitTest;
procedure TColumnsShareDemoMainForm.tvProjectsMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
// Note that the Sender parameter is a Site
HitTest := (Sender as TcxGridSite).GridView.ViewInfo.GetHitTest(X, Y);
// The point belongs to the [+]/[-] button area
if HitTest is TcxGridExpandButtonHitTest then
// Move focus to the record
TcxGridExpandButtonHitTest(HitTest).GridRecord.Focused := True;
end;
****************************************************************************
19 CXGrid4如何展开全部节点
解决:GridDBTableView1.DataController.Groups.FullExpand;
****************************************************************************
20. cxGrid如何动态创建Items的Editor的项?
解决:cxGrid的列有一个属性,它的编辑框可以指定combobox,spinedit等.在设计时,可以为
combobox的items添加项目.请问是否可以动态创建?(run-time时由程序加入)
var A:TDataSource: B:TcxlookupcomboboxProperties; begin A:=TDataSource.create(self); B:=tcxlookupcomboboxproperties.create(self); A.Dataset:=Dic_ry_xb;//此处指定数据源。 b.listdource:=a;//此处指明字段的listsource属性。 b.keyfieldnames:='a'; //此处指明字段的关键字段 b.listfieldnames:='b'; //此处指明字段的返回值。 b.listcolumns.items[0].caption:='x; //此处默认是会建立一个字段,但是显示的表头是name,所以此处让它显示为自己想要的中午显示。 cxGrid1DBTableView1c1_sex_code.Properties:=b; //此处指明是那个字段。 end; //这个是初始化的代码
****************************************************************************
21. 拷贝文件时有进度显示
解决:
procedure TForm1.mycopyfile(sourcef,targetf:string); var FromF, ToF: file; NumRead, NumWritten: Integer; Buf: array[1..2048] of Char; n:integer; begin AssignFile(FromF, sourcef); Reset(FromF, 1); { Record size = 1 } AssignFile(ToF,targetf); { Open output file } Rewrite(ToF, 1); { Record size = 1 } n:=0; repeat BlockRead(FromF, Buf, SizeOf(Buf), NumRead); form1.label1.caption:=IntToStr(sizeof(buf)*n*100 div FileSize(FromF))+'100%'; application.ProcessMessages; //显示进度 BlockWrite(ToF, Buf, NumRead, NumWritten); inc(n); until (NumRead = 0) or (NumWritten <> NumRead); form1.Label1.Caption:='100%'; CloseFile(FromF); CloseFile(ToF); end; procedure TForm1.Button1Click(Sender: TObject); begin mycopyfile('e:/components/tv2k-w2k.zip','c:/a.zip'); end;
****************************************************************************
22. cxGrid 设置斑马线
解决:
在TcxGridDBBandedTableView.Styles属性中有 ContentEven(奇数行风格) ContentOdd (偶数行风格) ,设定一下风格就好了。
****************************************************************************
23 根据记录内容更改字体颜色
解决:
参考范例CustomDrawTableViewDemo,
主要在TcxGridDBBandedTableView.OnCustomDrawCell事件中实现。
如下代码:
if (Pos('-',AViewInfo.GridRecord.DisplayTexts[colOrderProductCount.Index]) > 0) then
begin //标识负数记录
//ACanvas.Canvas.Brush.Color:= clMoneyGreen;
ACanvas.Canvas.Font.Color:= clRed;//clActiveCaption
end;
其中colOrderProductCount是“产品订数”列。
还要有一步就是要刷新显示
TcxGridDBBandedTableView.LayoutChanged();
//tvCars.LayoutChanged(False);
TcxGridDBBandedTableView.Painter.Invalidate;
****************************************************************************
24 用代码展开/收缩主从结构
解决:
Self.tvDepartment.ViewData.Expand(True);
Self.tvDepartment.ViewData.Collaspe(True);
注:tvDepartment为主表对应的TableView
****************************************************************************
25 在内置右键菜单的后面增加菜单项
解决:
首先应在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;
****************************************************************************
26 根据某列的值设定其它列的可编辑性
解决:
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;
****************************************************************************
27 保存/恢复Grid布局
解决:
网格左上角的自定义布局按钮:
TableView-?OptionsCustiomize?ColumnsQuickCustomization true;
//恢复布局 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); //保存为布局文件 实例: IniFileName: string; procedure TMainFM.FormCreate(Sender: TObject); //窗体创建时读取布局 var i: Integer; begin qyHed.Open; IniFileName := ExtractFilePath(Application.ExeName) + '/Layout/' + cxGrd.Owner.ClassName + cxGrd.Name + '.ini'; if FileExists(IniFileName) then Self.cxTbv.RestoreFromIniFile(IniFileName) //从布局文件中恢复 else begin Self.cxTbv.BeginUpdate; for i := 0 to Self.cxTbv.ItemCount - 1 do Self.cxTbv.Items[i].ApplyBestFit; //调整为最佳宽度 Self.cxTbv.EndUpdate; end; end; procedure TMainFM.NSaveGrdClick(Sender: TObject); //保存布局文件 begin try IniFileName := ExtractFilePath(Application.ExeName) + '/Layout/' + cxGrd.Owner.ClassName + cxGrd.Name + '.ini'; if not DirectoryExists(ExtractFileDir(IniFileName)) then CreateDir(ExtractFileDir(IniFileName)); Self.cxTbv.StoreToIniFile(IniFileName); except end; end;
****************************************************************************
28保存/恢复带汇总行的布局解决:
<TableView>.StoreToIniFile('c:/Grid.ini', True, [gsoUseSummary]);
<GridView>.RestoreFromIniFile(<inifilename>,True,False{or True,optional},[gsoUseSummary]);
zj:本条与50条重复
****************************************************************************
28 在主从TableView中根据主TableView得到对应的从TableView
解决:
var
ADetailDC: TcxGridDataController;
AView: TcxCustomGridTableView;
begin
with cxGrid1DBTableView1.DataController do
ADetailDC := TcxGridDataController(GetDetailDataController(FocusedRecordIndex, 0));
AView := ADetailDC.GridView;
end;
==============================================================================
29 定位在第一行并显示内置编辑器
cxDBVerticalGrid1.FocusedRow := cxDBVerticalGrid1.Rows[0];
cxDBVerticalGrid1.ShowEdit;
==============================================================================
30 隐藏 "<No data to display>" 字符串
该文本存储在scxGridNoDataInfoText资源字符串,可以将该资源字符串的内容设为空
来隐藏该文本。
uses cxClasses, cxGridStrs;
...
cxSetResourceString(@scxGridNoDataInfoText, '');
//如果"<No data to display>" 字符串已经显示,需要调用:
<View>.LayoutChanged;
============================================================
31 删除应用过滤后的行
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;
=============================================================
32 根据单元的值设置样式
解决:
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];
****************************************************************************
33 动态生成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;
end;
****************************************************************************
34 当底层数据集为空时显示一条空记录
解决:
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;
****************************************************************************