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时由程序加入)

[delphi] view
plain
copy

  1. var
  2. A:TDataSource:
  3. B:TcxlookupcomboboxProperties;
  4. begin
  5. A:=TDataSource.create(self);
  6. B:=tcxlookupcomboboxproperties.create(self);
  7. A.Dataset:=Dic_ry_xb;//此处指定数据源。
  8. b.listdource:=a;//此处指明字段的listsource属性。
  9. b.keyfieldnames:='a'; //此处指明字段的关键字段
  10. b.listfieldnames:='b'; //此处指明字段的返回值。
  11. b.listcolumns.items[0].caption:='x; //此处默认是会建立一个字段,但是显示的表头是name,所以此处让它显示为自己想要的中午显示。
  12. cxGrid1DBTableView1c1_sex_code.Properties:=b; //此处指明是那个字段。
  13. end; //这个是初始化的代码

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

21. 拷贝文件时有进度显示

解决:

[delphi] view
plain
copy

  1. procedure TForm1.mycopyfile(sourcef,targetf:string);
  2. var
  3. FromF, ToF: file;
  4. NumRead, NumWritten: Integer;
  5. Buf: array[1..2048] of Char;
  6. n:integer;
  7. begin
  8. AssignFile(FromF, sourcef);
  9. Reset(FromF, 1); { Record size = 1 }
  10. AssignFile(ToF,targetf); { Open output file }
  11. Rewrite(ToF, 1); { Record size = 1 }
  12. n:=0;
  13. repeat
  14. BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
  15. form1.label1.caption:=IntToStr(sizeof(buf)*n*100 div FileSize(FromF))+'100%';
  16. application.ProcessMessages;
  17. //显示进度
  18. BlockWrite(ToF, Buf, NumRead, NumWritten);
  19. inc(n);
  20. until (NumRead = 0) or (NumWritten <> NumRead);
  21. form1.Label1.Caption:='100%';
  22. CloseFile(FromF);
  23. CloseFile(ToF);
  24. end;
  25. procedure TForm1.Button1Click(Sender: TObject);
  26. begin
  27. mycopyfile('e:/components/tv2k-w2k.zip','c:/a.zip');
  28. 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

[delphi] view
plain
copy

  1. procedure   TFormItemList.FormCreate(Sender:   TObject);
  2. var
  3. AMenu:   TComponent;
  4. FMenuItem,   FSubMenuItem:   TMenuItem;
  5. begin
  6. AMenu   :=   nil;
  7. if   cxGridPopupMenu.BuiltInPopupMenus.Count   =   0   then
  8. Exit;
  9. AMenu   :=   cxGridPopupMenu.BuiltInPopupMenus[0].PopupMenu; //第一个内置右键菜单(表头菜单)
  10. if   Assigned(AMenu)   and   AMenu.InheritsFrom(TPopupMenu)   then
  11. begin
  12. TPopupMenu(AMenu).AutoHotkeys   :=   maManual;         //手动热键
  13. //-------------------------
  14. FMenuItem   :=   TMenuItem.Create(Self);
  15. FMenuItem.Caption   :=   '-';
  16. FMenuItem.Name   :=   'miLineForGroup';
  17. TPopupMenu(AMenu).Items.Add(FMenuItem);
  18. //展开所有组
  19. FMenuItem   :=   TMenuItem.Create(Self);
  20. FMenuItem.Name   :=   'miExpandAllGroup';
  21. FMenuItem.Caption   :=   '展开所有组(&X)';
  22. FMenuItem.OnClick   :=   miExpandAllGroupClick;
  23. TPopupMenu(AMenu).Items.Add(FMenuItem);
  24. //收缩所有组
  25. FMenuItem   :=   TMenuItem.Create(Self);
  26. FMenuItem.Name   :=   'miCollapseAllGroup';
  27. FMenuItem.Caption   :=   '收缩所有组(&O)';
  28. FMenuItem.OnClick   :=   miCollapseAllGroupClick;
  29. TPopupMenu(AMenu).Items.Add(FMenuItem);
  30. //-------------------------
  31. FMenuItem   :=   TMenuItem.Create(Self);
  32. FMenuItem.Caption   :=   '-';
  33. TPopupMenu(AMenu).Items.Add(FMenuItem);
  34. //过滤面板
  35. FMenuItem   :=   TMenuItem.Create(Self);
  36. FMenuItem.Name   :=   'miFilterPanel';
  37. FMenuItem.Caption   :=   '过滤面板(&P)';
  38. //自动显示
  39. FSubMenuItem   :=   TMenuItem.Create(Self);
  40. FSubMenuItem.Name   :=   'miFilterPanelAuto';
  41. FSubMenuItem.Caption   :=   '自动(&A)';
  42. FSubMenuItem.RadioItem   :=   True;
  43. FSubMenuItem.GroupIndex   :=   5; //指定同一组
  44. FSubMenuItem.Checked   :=   True;
  45. FSubMenuItem.OnClick   :=   miFilterPanelClick;
  46. FMenuItem.Add(FSubMenuItem); //加入二级子菜单
  47. //总是显示
  48. FSubMenuItem   :=   TMenuItem.Create(Self);
  49. FSubMenuItem.Name   :=   'miFilterPanelAlways';
  50. FSubMenuItem.Caption   :=   '总是显示(&W)';
  51. FSubMenuItem.RadioItem   :=   True;
  52. FSubMenuItem.GroupIndex   :=   5;
  53. FSubMenuItem.OnClick   :=   miFilterPanelClick;
  54. FMenuItem.Add(FSubMenuItem);
  55. //从不显示
  56. FSubMenuItem   :=   TMenuItem.Create(Self);
  57. FSubMenuItem.Name   :=   'miFilterPanelNerver';
  58. FSubMenuItem.Caption   :=   '从不显示(&N)';
  59. FSubMenuItem.RadioItem   :=   True;
  60. FSubMenuItem.GroupIndex   :=   5;
  61. FSubMenuItem.OnClick   :=   miFilterPanelClick;
  62. FMenuItem.Add(FSubMenuItem);
  63. TPopupMenu(AMenu).Items.Add(FMenuItem);
  64. //自定义过滤
  65. FMenuItem   :=   TMenuItem.Create(Self);
  66. FMenuItem.Name   :=   'miCustomFilter';
  67. FMenuItem.Caption   :=   '自定义过滤(&M)';
  68. FMenuItem.OnClick   :=   miCustomFilterClick;
  69. TPopupMenu(AMenu).Items.Add(FMenuItem);
  70. //过滤管理器
  71. FMenuItem   :=   TMenuItem.Create(Self);
  72. FMenuItem.Name   :=   'miFilterBuilder';
  73. TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend,   44); //添加图标图像
  74. FMenuItem.ImageIndex   :=   TPopupMenu(AMenu).Images.Count   -   1; //指定图标序号
  75. FMenuItem.Caption   :=   '过滤管理器';
  76. FMenuItem.OnClick   :=   Self.miFilterBuilderClick;
  77. TPopupMenu(AMenu).Items.Add(FMenuItem);
  78. //---------------------
  79. FMenuItem   :=   TMenuItem.Create(Self);
  80. FMenuItem.Caption   :=   '-';
  81. TPopupMenu(AMenu).Items.Add(FMenuItem);
  82. //导出
  83. FMenuItem   :=   TMenuItem.Create(Self);
  84. FMenuItem.Name   :=   'miExport';
  85. TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend,   37);
  86. FMenuItem.ImageIndex   :=   TPopupMenu(AMenu).Images.Count   -   1;
  87. FMenuItem.Caption   :=   '导出(&E)';
  88. FMenuItem.OnClick   :=   Self.miExportClick;
  89. TPopupMenu(AMenu).Items.Add(FMenuItem);
  90. //打印
  91. FMenuItem   :=   TMenuItem.Create(Self);
  92. FMenuItem.Name   :=   'miPrint';
  93. FMenuItem.Caption   :=   '打印(&P)';
  94. TPopupMenu(AMenu).Images.AddImage(FormMain.ImageListExtend,   14);
  95. FMenuItem.ImageIndex   :=   TPopupMenu(AMenu).Images.Count   -   1;
  96. FMenuItem.OnClick   :=   Self.miPrintClick;
  97. TPopupMenu(AMenu).Items.Add(FMenuItem);
  98. end;
  99. end;
  100. procedure   TFormItemList.miExportClick(Sender:   TObject);
  101. var
  102. FileName,   FileExt,   msg:   String;
  103. begin
  104. if   Self.aqyQuery.IsEmpty   then
  105. begin
  106. msg   :=   '没有导出数据...';
  107. Application.MessageBox(PChar(msg),   PChar(Application.Title),
  108. MB_OK   or   MB_IconWarning);
  109. Exit;
  110. end;
  111. Self.SaveDialogExport.Filter   :=   'Excel文件   (*.xls)|*.xls|XML文件   (*.xml)|*.xml'
  112. +   '|文本文件   (*.txt)|*.txt|网页文件   (*.html)|*.html';
  113. Self.SaveDialogExport.Title   :=   '导出为';
  114. if   not   Self.SaveDialogExport.Execute   then
  115. Exit;
  116. FileName   :=   Self.SaveDialogExport.FileName;
  117. FileExt   :=   LowerCase(ExtractFileExt(FileName));
  118. if   FileExt   =   '.xls'   then
  119. ExportGrid4ToExcel(FileName,   Self.cxGrid1)
  120. else   if   FileExt   =   '.xml'   then
  121. ExportGrid4ToXML(FileName,   Self.cxGrid1)
  122. else   if   FileExt   =   '.txt'   then
  123. ExportGrid4ToText(FileName,   Self.cxGrid1)
  124. else   if   FileExt   =   '.html'   then
  125. ExportGrid4ToHTML(FileName,   Self.cxGrid1)
  126. else
  127. begin
  128. msg   :=   '不支持的导出文件类型...';
  129. Application.MessageBox(PChar(msg),   PChar(Application.Title),
  130. MB_OK   or   MB_IconError);
  131. Exit;
  132. end;
  133. msg   :=   '导出完成...';
  134. Application.MessageBox(PChar(msg),   PChar(Application.Title),
  135. MB_OK   or   MB_IconInformation);
  136. end;
  137. procedure   TFormItemList.miPrintClick(Sender:   TObject);
  138. begin
  139. //打印
  140. Self.dxComponentPrinter.Preview(True,   Self.dxComponentPrinterLink1);
  141. end;
  142. procedure   TFormItemList.cxGridPopupMenuPopup(ASenderMenu:   TComponent;
  143. AHitTest:   TcxCustomGridHitTest;   X,   Y:   Integer;   var   AllowPopup:   Boolean);
  144. begin
  145. if   GetHitTypeByHitCode(AHitTest.HitTestCode)   =   gvhtColumnHeader   then //右击列标题时
  146. begin
  147. //if   tvResult.DataController.Groups.GroupingItemCount   >   0   then
  148. if   tvResult.GroupedColumnCount   >   0   then //有分组时显示
  149. begin
  150. TMenuItem(Self.FindComponent('miLineForGroup')).Visible   :=   True;
  151. TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible   :=   True;
  152. TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible   :=   True;
  153. end
  154. else
  155. begin
  156. TMenuItem(Self.FindComponent('miLineForGroup')).Visible   :=   False;
  157. TMenuItem(Self.FindComponent('miExpandAllGroup')).Visible   :=   False;
  158. TMenuItem(Self.FindComponent('miCollapseAllGroup')).Visible   :=   False;
  159. end;
  160. end;
  161. end;
  162. procedure   TFormItemList.miFilterBuilderClick(Sender:   TObject);
  163. begin
  164. //过滤管理器
  165. //弹出Filter   Builder   Dialog对话框
  166. tvResult.Filtering.RunCustomizeDialog;
  167. end;
  168. procedure   TFormItemList.miCustomFilterClick(Sender:   TObject);
  169. var
  170. AHitTest:   TcxCustomGridHitTest;
  171. begin
  172. //自定义过滤
  173. //弹出Custom   Filter   Dialog对话框
  174. AHitTest   :=   cxGridPopupMenu.HitTest;
  175. if   GetHitTypeByHitCode(AHitTest.HitTestCode)   =   gvhtColumnHeader   then //获得右击的列
  176. tvResult.Filtering.RunCustomizeDialog(TcxGridColumnHeaderHitTest(AHitTest).Column);
  177. end;
  178. procedure   TFormItemList.miFilterPanelClick(Sender:   TObject);
  179. var
  180. mi:   TMenuItem;
  181. begin
  182. //隐藏/显示过滤面板
  183. mi   :=   TMenuItem(Sender);
  184. mi.Checked   :=   True;
  185. if   mi.Name   =   'miFilterPanelAlways'   then
  186. tvResult.Filtering.Visible   :=   fvAlways
  187. else   if   mi.Name   =   'miFilterPanelNerver'   then
  188. tvResult.Filtering.Visible   :=   fvNever
  189. else
  190. tvResult.Filtering.Visible   :=   fvNonEmpty;
  191. end;
  192. procedure   TFormItemList.miExpandAllGroupClick(Sender:   TObject);
  193. begin
  194. //展开所有组
  195. tvResult.DataController.Groups.FullExpand;
  196. end;
  197. procedure   TFormItemList.miCollapseAllGroupClick(Sender:   TObject);
  198. begin
  199. //收缩所有组
  200. tvResult.DataController.Groups.FullCollapse;
  201. 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;

[delphi] view
plain
copy

  1. //恢复布局
  2. IniFileName   :=   ExtractFilePath(Application.ExeName)   +   'Layout/'   +   Self.Name   +   '.ini';
  3. if   FileExists(IniFileName)   then
  4. Self.tvResult.RestoreFromIniFile(IniFileName) //从布局文件中恢复
  5. else
  6. begin
  7. Self.tvResult.BeginUpdate;
  8. for   i   :=   0   to   Self.tvResult.ItemCount   -   1   do
  9. Self.tvResult.Items[i].ApplyBestFit; //调整为最佳宽度
  10. Self.tvResult.EndUpdate;
  11. end;
  12. //保存布局
  13. IniFileName   :=   ExtractFilePath(Application.ExeName)   +   'Layout/'   +   Self.Name   +   '.ini';
  14. if   not   DirectoryExists(ExtractFileDir(IniFileName))   then
  15. CreateDir(ExtractFileDir(IniFileName));
  16. Self.tvResult.StoreToIniFile(IniFileName); //保存为布局文件
  17. 实例:
  18. IniFileName: string;
  19. procedure TMainFM.FormCreate(Sender: TObject);     //窗体创建时读取布局
  20. var i: Integer;
  21. begin
  22. qyHed.Open;
  23. IniFileName := ExtractFilePath(Application.ExeName) + '/Layout/' + cxGrd.Owner.ClassName + cxGrd.Name + '.ini';
  24. if FileExists(IniFileName) then
  25. Self.cxTbv.RestoreFromIniFile(IniFileName) //从布局文件中恢复
  26. else
  27. begin
  28. Self.cxTbv.BeginUpdate;
  29. for i := 0 to Self.cxTbv.ItemCount - 1 do
  30. Self.cxTbv.Items[i].ApplyBestFit; //调整为最佳宽度
  31. Self.cxTbv.EndUpdate;
  32. end;
  33. end;
  34. procedure TMainFM.NSaveGrdClick(Sender: TObject);      //保存布局文件
  35. begin
  36. try
  37. IniFileName := ExtractFilePath(Application.ExeName) + '/Layout/' + cxGrd.Owner.ClassName + cxGrd.Name + '.ini';
  38. if not DirectoryExists(ExtractFileDir(IniFileName)) then
  39. CreateDir(ExtractFileDir(IniFileName));
  40. Self.cxTbv.StoreToIniFile(IniFileName);
  41. except
  42. end;
  43. 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;

04-16 17:23