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看一下胜利果实吧。 

  

 

  

  

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];

posted on 2021-01-27 11:26  癫狂编程  阅读(187)  评论(0编辑  收藏  举报

导航

好的代码像粥一样,都是用时间熬出来的