我有一个函数来更新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;
答案 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属性可能会在没有任何代码的情况下避免这个问题,但是我找不到任何代码。