delphi cxgrid记录一些网上都不一定能找到的资料

主从表的问题.

效果图大概如下图所示,它能体现出主表里每一条记录的入仓记录,左边的加减号可以展示与隐藏从表.

 

 结构设计如上图右下角所示,做两个level,和两个DB table,从结构上可以很晰的看到,TV报废池是主表,TV查询是从表.

我们需要做两组数据集,SQL内容按业务自己看着写.

 

 然后是主从表的关联设置,这方面网上资料有很多,但都没有配图,所以我打算细讲这部分内容.

主表设置: 选中TV报废池,在左边属性面板里按如下设置.这里只要设置keyFieldNames这个属性就可以了.需要注意的是,这里要设置成主表里具有唯一性的字段,否则IDE可能会崩溃,比如我的10.3.3

 

然后是从表设置.选中TV查询,按下图设置:,这里有一点要注意,主表与从表的关联字段要一致,意思是从表会以主表关联的这个字段值,作为筛选条件返回数据.从表如果没有具有唯一特性的字段,keyFieldNames可以留空.

 

最后一步,也很关键,很多人按上面的内容设置好后,结果发现只返回了一条数据,或者根本没有数据展现出来.

先说后面一种吧,建议先看一下数据库里有没有符合条件的数据吧,我TMD当时就做了一回SB..

如果数据库里明明有好多条记录,结果只返回了一条,说明你SQL写得不对.解决的方案是在从表的SQL语句后面加个order by 关联字段.我们上面设置的关联字段是"物料代码",所以下图就是按这个字段排序的.

 

 

 这样就算是设置好一个主从表了.

然后我们来看看怎么取从表里的数据,还有从表的RecordCount

看看下面这一句:

DetailRecCount:=cxGrid1DBTableView1.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView.DataController.RecordCount; 

没错,这TMD就是用来获取从表记录数的,谁能想到它隐藏得这么深!我当时在网上找了半天资料没找到,在群里问也没人回,总算是知道原因了--实在是老司机也不一定知道啊!

然后是取从表的数据:

V:= TcxGridDBTableView(cxGrid1DBTableView1.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView).ViewData.Rows[j].Values[k];
吖吖个呸!
下面是效果图和完整代码

 


 

 

 

procedure TForm1.Button1Click(Sender: TObject);
var i,j,k,DetailRecCount:integer;
    s:string;
    v:Variant;
begin
  memo1.Clear;
  for i:=0 to cxGrid1DBTableView1.DataController.RowCount-1 do begin
    DetailRecCount:=cxGrid1DBTableView1.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView.DataController.RecordCount;  
    memo1.Lines.Append('');
    s:='';
    for k:=0 to 2 do begin
      v:=cxGrid1DBTableView1.ViewData.Rows[i].Values[k];
      if VarIsNull(v) then
        s:=s+'; '
      else
        s:=s+string(v)+'; ';
    end;
    memo1.Lines.Append(s);
    for j:=0 to DetailRecCount-1 do begin
      s:='    ';
      for k:=0 to 3 do begin
        if k=1 then continue;
        with TcxGridDBTableView(cxGrid1DBTableView1.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView) do
          v:=ViewData.Rows[j].Values[k];
        if VarIsNull(v) then
          s:=s+'; '
        else
          s:=s+string(v)+'; ';
      end;
      memo1.Lines.Append(s);
    end;
    memo1.Lines.Append('    从表共 '+inttostr(DetailRecCount)+' 笔记录.');
  end;
end;

end.

 

然后,我又在想,能不能实现只有从表里面有数据时,才显示从表,否则忽略用户对 + 号的点击呢?

需要用到 DataController 下的 OnDetailExpanding事件

 

 

 //ARecordIndex: 主表当前操作的行,AAllow 是否显示从表

 

procedure T申领申购报废清单.TV报废池DataControllerDetailExpanding(ADataController: TcxCustomDataController;
  ARecordIndex: Integer; var AAllow: Boolean);
var
  n: integer; //从表记录数
begin  
  n := TV报废池.ViewData.Rows[ARecordIndex].AsMasterDataRow.ActiveDetailGridView.DataController.RecordCount;
  AAllow := n > 0;      //如果从表记录数大于0,则展开从表,否则不展开
end;

 

接下来,我又想通过从表的单元格双击事件,来实现更新主表内容,并收起从表

//更新供应商和用途到报废池
procedure T申领申购报废清单.TV查询CellDblClick(Sender: TcxCustomGridTableView; ACellViewInfo:
  TcxGridTableDataCellViewInfo; AButton: TMouseButton; AShift: TShiftState; var AHandled: Boolean);
var
  recordid, 供应商ID, 用途: string;
  i, iRow, iCol1, iCol2: integer;
begin
  iRow := ACellViewInfo.RecordViewInfo.Index;
  iCol1 := Col用途.Index;
  iCol2 := Col供应商ID.Index;
  recordid := DM.fdq报废池.FieldByName('recordid').AsString;
  i := TV报废池.Controller.FocusedRowIndex;
  用途 := TcxGridDBTableView(TV报废池.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView).ViewData.Rows
    [iRow].Values[iCol1];

  供应商ID := TcxGridDBTableView(TV报废池.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView).ViewData.Rows
    [iRow].Values[iCol2];

  with DM.FD公共查询 do
  begin
    close;
    SQL.Text := 'update 报废池 set 供应商=' + 供应商ID + ',用途=' + 用途.QuotedString + ' where recordid=' +
      recordid;
    ExecSQL;
  end;
  //更新后,更新数据集
  DM.FDQ报废池.Refresh;
  //收起从表
   TV报废池.ViewData.Collapse(True);
   //收起当前从表
//   TV报废池.ViewData.Rows[TV报废池.DataController.FocusedRowIndex].Collapse(True);
end;

其他收起与展开的代码如下,使用时 tvQuery 对应的是主表,这一点必须要理解.

1:展开所有行
tvQuery.ViewData.Expand(True);
2:收起所有行
tvQuery.ViewData.Collapse(True);
3:展开当前行
tvQuery.ViewData.Rows[tvQuery.DataController.FocusedRowIndex].Expand(True);
4:收起当前行
tvQuery.ViewData.Rows[tvQuery.DataController.FocusedRowIndex].Collapse(True);

 

2023-01-20追加

如何设置与访问 cxgrid 中列的 Properties 属性.

从表Column1.PropertiesClass :=TCXCurrencyEditProperties ;  //动态设置属性
TCXCurrencyEditProperties(从表Column1.Properties).displayFormat := '0.##';  //设置显示样式
TcxSpinEditProperties: 是指你给这一列设置的 Properties 类型,其他类型有:
TcxTextEditProperties;  
TcxDateEditProperties;  
TcxCalcEditProperties; 
TcxCheckboxProperties; 
...其他的你们自己照着画就行了,一般都能点出来
访问(取属性值),和上面的差不多
ShowMessage(TCXCurrencyEditProperties(从表Column1.Properties).displayFormat);

 2023-02-07追加

cxGrid删除与创建所有字段

IcxCustomGridDataController(cxGrid1DBTableView1.DataController).DeleteAllItems;    //CXGRID删除所有字段
IcxCustomGridDataController(cxGrid1DBTableView1.DataController).CreateAllItems(False);   //CXGRID创建所有字段

 2024-04-03追加

cxgrid取得指定字段排在第几列.感谢 [狼行卫野] 大佬的指点

  AText := cxGrid1DBTableView1.GetColumnByFieldName('物料名称').Index.ToString      //物理位置,不管是否有隐藏字段
    AText := cxGrid1DBTableView1.GetColumnByFieldName('物料名称').visibleIndex.ToString      //视觉位置,隐藏的列将会被忽略不计

 

posted @ 2023-01-18 15:12  一曲轻扬  阅读(464)  评论(0编辑  收藏  举报