在cxGrid中更新字段表现得很奇怪

时间:2015-06-15 08:23:18

标签: delphi devexpress tcxgrid

我有一个函数来更新cxGrid,它是在Loop through records on a cxgrid and update a field/column

的答案的帮助下制作的

但它有时表现得有些奇怪。如果我使用cxGrid打开表单并单击列标题而不执行任何其他操作,则会更新记录。但如果'选择栏'从顶部移开,标记的记录不会更新。 我确信这是一个需要改变的属性,但是哪个属性。

变量fSelected在FormShow中设置为False,因此用户也可以取消选择记录。

parsed_input = json.loads(self.intervalos)
extremo_inferior_0 = parsed_input['operandos'][0]['extremoInferior']

Delphi XE7,DevExpress 14.2.2,UniDAC 5.5.12 for DB access

注释: 基于MartynA的答案和输入,我最终得到了以下解决方案

procedure TfrmContactsSelect.colContactSelectedHeaderClick(Sender: TObject);
var
  i: Integer;
  Index: Integer;
  BookMark : TBookMark;
  Contact: variant;
begin
  if fMulti = True then
    begin
     Screen.Cursor := crHourGlass;
     fSelected := not fSelected;
      BookMark := qryContacts.GetBookmark;
      qryContacts.DisableControls;
      try
        for i := 0 to grdContactsView1.DataController.FilteredRecordCount - 1 do
          begin
            Index := grdContactsView1.DataController.FilteredRecordIndex[i];
            Contact := grdContactsView1.DataController.Values[Index, 4];
            if grdContactsView1.DataController.LocateByKey(Contact) then
              begin
                qryContacts.Edit;
                qryContacts.FieldByName('fldcontact_selected').AsBoolean := fSelected;
                qryContacts.Post;
              end;
          end;
      finally
        qryContacts.EnableControls;
        qryContacts.GotoBookmark(BookMark);
        qryContacts.FreeBookmark(BookMark);
      end;
      Screen.Cursor := crDefault;
    end;
end;

1 个答案:

答案 0 :(得分:1)

我可以使用我在回答您的其他问题时发布的示例项目重现您的问题。

试试这个:将TMemo添加到表单中,然后在'if grdContactsView1.DataController.LocateByKey(Contact)then block中,将行唯一数据字段的值和Selected datafield值写入备忘录。

然后,当选择除顶行之外的某行时,我得到的是在备忘录中列出两行,其中Selected和false都是false,并且过滤器中的一行根本没有列出我认为这是你所看到的行为的原因。如果我然后注释掉.Edit .. .Post行,它会正确列出过滤器中的所有行。

显然,在迭代DBTableView的FilteredRecordIndex属性的块中进行Selected字段更改是导致问题的原因。

就个人而言,我发现通过数据库感知控件修改代码中的数据集行有点不利(因为你通常最终会对控件的DB感知进行斗争),但在这种情况下,它很简单通过cxGrid的DBTableView进行处理。

procedure TForm1.ProcessFilteredRecords;
var
  PrevV,
  V : Variant;
  i,
  Index: Integer;
  S : String;
begin

  //  First, pick up a reference to the current record
  //  so that we can return to it afterwards
  Index := cxGrid1DBTableView1.DataController.FocusedRecordIndex;
  PrevV := cxGrid1DBTableView1.DataController.Values[Index, 0];

  try
    for i := 0 to cxGrid1DBTableView1.DataController.FilteredRecordCount - 1 do begin
      Index := cxGrid1DBTableView1.DataController.FilteredRecordIndex[i];
      V := cxGrid1DBTableView1.DataController.Values[Index, 0];
      if cxGrid1DBTableView1.DataController.LocateByKey(V) then begin
        cxGrid1DBTableView1.DataController.Edit;
        // 2 is the index of my Selected column in the grid
        if cxGrid1DBTableView1.DataController.SetEditValue(2, True, evsText) then
          Caption := 'OK'
        else
          Caption := 'Failed';
        cxGrid1DBTableView1.DataController.Post;
      end;
    end;
  finally
    if cxGrid1DBTableView1.DataController.LocateByKey(PrevV) then
      Caption := 'OK'
    else
      Caption := 'Failed';
  end;
end;

避免此问题的另一种方法是分两步更改选定状态:

  • 迭代FilteredRecordIndex以构建要更改的行列表 - 在您的情况下,这将是一个guid列表

  • 然后,迭代行列表并更新其选定状态。

代码:

procedure TForm1.ProcessFilteredRecords;
var
  V : Variant;
  i,
  Index: Integer;
  BM : TBookMark;
  S : String;
  TL : TStringList;
begin
  Memo1.Lines.Clear;
  TL := TStringList.Create;
  try
    for i := 0 to cxGrid1DBTableView1.DataController.FilteredRecordCount - 1 do begin
      Index := cxGrid1DBTableView1.DataController.FilteredRecordIndex[i];
      V := cxGrid1DBTableView1.DataController.Values[Index, 0];

      if cxGrid1DBTableView1.DataController.LocateByKey(V) then begin
        if CDS1.FieldByName('Selected').AsBoolean then
          S := 'True'
        else
          S := 'False';
        S := CDS1.FieldByName('Name').AsString + ' ' + S;
        Memo1.Lines.Add(S);
        TL.Add(CDS1.FieldByName('Guid').AsString);
      end;
    end;

    try
      BM := CDS1.GetBookMark;
      CDS1.DisableControls;
      for i := 0 to TL.Count - 1 do begin
        if CDS1.Locate('guid', TL[i], []) then begin
          CDS1.Edit;
          CDS1.FieldByName('Selected').AsBoolean := True;
          CDS1.Post;
        end
      end;
    finally
      CDS1.EnableControls;
      CDS1.GotoBookmark(BM);
      CDS1.FreeBookmark(BM);
    end;
  finally
    TL.Free;
  end;
end;

和你一样,我期待更改一个或两个cxGrid属性可能会在没有任何代码的情况下避免这个问题,但是我找不到任何代码。

相关问题