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时由程序加入)
plaincopy
- 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. 拷贝文件时有进度显示
解决:
plaincopy
- 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
plaincopy
- 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;
plaincopy
- //恢复布局
- 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;