cxGrid 使用指南 2

CxGrid使用小结(续)   
======================================================================== 
 
  激活内置编辑控件 
 
    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上的所有地方,左键或右键,你都会有意外收获。




1:cxgrid是应该数据关联的控件,类似dbgrid。

2:一般用来查阅表信息,如果要修改的话,直接在上面编辑或添加非常不方便
通常要放几个EDit来对选中的记录进行编辑或添加记录。
因为表一般都有主键,而用cxgrid很难控制。在post之前的主键检查工作。

3:由于没有直接进行编辑,而post之前又要进行主键检查工作(需要循环
adoquery,此时的记录索引已经改变了)。所以我们要用一个bookmack。在编辑
的时候先Getbookmack,在确认修改数据的时候,先GotoBookMark,再把值更 新。

4:在选择某条记录后,需要得到相应的字段值显示在Edit上面,这个时候就要用
cxGridDBTableView的Cellclick事件里面处理;
可以用click事件里面的一个参数:ACellViewInfo。该参数的一个属性;
如:EdtMperson.text := ACellViewInfo.GridRecord.Values[2];

5:当需要得到随即选择的多条记录时有两种办法
qrymast是一个adoquery
⑴第一步得到选择的总数
Icount := cxGrid1DBTableView1.DataController.GetSelectedCount;

⑵循环所有所选择的记录
for n := 0 to icount-1 do
begin
⑶将选择记录的索引转换为数据集的索引
i := cxGrid1DBTableView1.DataController.GetSelectedRowIndex(n);
如果cxgriddbtableview没有设置排序,那么第一种方法也是正确的(因为cxgriddbtableview显示
的数据和qrymast显示的数据顺序是一样的)

//这是第一种方法,取qrymast的数据
inc(i);//因为qrymast的记录是从1开始的
qryMast.RecNo := i;
得到需要的数据值
listbox1.Items.Add(qrymast.fields[0].asstring);

//这是第二种方法,取cxGrid1DBTableView1.ViewData的数据
if i =0 then
cxGrid1DB.DataController.GotoFirst
else
cxGrid1DBTableView1.DataController.RecNo := i;
str := cxGrid1DBTableView1.ViewData.Rows[i].Values[0];
listbox1.Items.Add(str);
end;

(一次测试的时候,cxGrid1DBTableView1.DataController.RecNo := 0;语句会报错,如果改为cxGrid1DB.DataController.GotoFirst,就没有问题)

6: 当有时候用到ACellViewInfo.GridRecord.Values[2]时候,由于values[2]是一个变体
类型Variant,而如果这个时候相应的字段值如果为空,下面这样用就会报错。
EdtMperson.text := ACellViewInfo.GridRecord.Values[2];
可以先判断一下:
if ACellViewInfo.GridRecord.Values[4]<>null then
MemRdesc.Lines.Text := ACellViewInfo.GridRecord.Values[4];
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值