Delphi cxGrid 选择速度优化

表格有一个选择列,用来选择数据后。提取选中的记录做某些事,这种是很常见的。

现有以下需求:

右键全选 、反选(支持选择过滤后的数据)

如果全部采取DB感知的方式 ,数据多的时候很卡。测试1000多条就很卡了

解决方案:

 //改成智能新
   cxGridDB.DataController.DataModeController.SyncMode := True;
   cxGridDB.DataController.DataModeController.SmartRefresh := True;
   //设置key 这个是关键,查询出来的数据要有ID 唯一
   cxGridDB.DataController.KeyFieldNames := 'id';
   //选择列改成非绑定的
   CxCol_xz.DataBinding.FieldName := '';
   CxCol_xz.DataBinding.ValueType := 'Boolean';
   CxCol_xz.PropertiesClassName := 'TcxCheckBoxProperties';
   TcxCheckBoxProperties(CxCol_xz.Properties).NullStyle := nssUnchecked;

全选 、反选:

//要加beginupdate 、endupdate 速度会很快
//直接操作ViewData 的数据就可以了
 cxGridDB.BeginUpdate();
  for i := 0 to cxGridDB.ViewData.RowCount -1 do
   cxGridDB.ViewData.Rows[i].Values[CxCol_xz.Index] := xz;
  cxGridDB.EndUpdate;

获取选择的数据:思路是过滤出选择=True的 循环去修改ADO 里的数据。也可不用修改,但是要过滤后去取值。这里看应用场景

procedure DocxGridViewChoose(var View:TcxGridDBTableView; idColumn, AChooseColumn :TcxGridDBColumn; AChooseFieldName:string='xz');
var
 Ds:TADOQuery;
 OrgFocusRow ,i: integer;
 mStream:TMemoryStream;
 OrgFiltered:Boolean;
 idFieldName:string;
begin
 Ds := TADOQuery(View.DataController.DataSource.DataSet);
 if Ds= nil then
  Exit;
 if not Ds.IsEmpty then
    View.DataController.Post();
  OrgFocusRow := View.Controller.FocusedRowIndex;
  idFieldName := idColumn.DataBinding.FieldName;
  Ds.DisableControls;
  if not Ds.IsEmpty then
   SetQryFilter(Ds, AChooseFieldName+'=True');
  with Ds do
  begin
   if not IsEmpty then
   begin
    First;
    while not eof do
    begin
     Ds.Edit;
     Ds.FieldByName(AChooseFieldName).Value := False;
     Ds.post;
    end;
   end;    
  end;
  ClearQryFilter(Ds);
  try
   mStream := TMemoryStream.Create;
   mStream.Position:=0;//流指针指向开始位
   View.DataController.Filter.Root.Criteria.SaveToStream(mStream);//将过滤状态存入流
   OrgFiltered := View.DataController.Filter.Active;
   View.DataController.Filter.Root.Clear; //过滤出选择的
   View.DataController.Filter.Root.AddItem(View.Columns[AChooseColumn.Index],foEqual,'True','');
   View.DataController.Filter.Active:=True;//激活过滤
   if View.DataController.FilteredRecordCount>0 then
   begin
    for i := 0 to View.DataController.RowCount-1 do
    begin
     if Ds.Locate(idFieldName,View.ViewData.Rows[i].Values[idColumn.Index], []) then
     begin
      Ds.Edit;
      Ds.FieldByName(AChooseFieldName).Value := True;
      Ds.Post;
     end;
    end;
   end;
  finally
   //恢复原来的过滤
   View.DataController.Filter.Root.Clear;
   mStream.Position:=0;
   View.DataController.Filter.Root.Criteria.LoadFromStream(mStream);
   View.DataController.Filter.Active:=OrgFiltered;
   mStream.Free;
   ds.EnableControls;
   View.Controller.FocusedRowIndex :=  OrgFocusRow;
  end;
end;

重新打开窗口时,如何把选择的数据恢复:

退出时先保存一下对应选中的数据的ID

//要加beginupdate 、endupdate 速度快很多
cxGridDB.BeginUpdate();
if cxGridDB.DataController.LocateByKey(ID) then
        cxGridDB.ViewData.Rows[cxGridDB.DataController.FocusedRowIndex].Values[0] := True;
cxGridDB.EndUpdate;

 

posted @ 2022-06-27 12:04  Tag  阅读(575)  评论(0)    收藏  举报