如何按名称而不是按索引访问TDBGrid列?

时间:2016-06-16 07:40:51

标签: delphi

如何按名称而不是索引访问TDBGrid列?

例如,现在我使用:

 grdInvoiceItems.Columns[2].Visible := False;

但是写一些类似的东西会好得多:

 grdInvoiceItems.Columns['UnitPrice'].Visible := False;

同时我使用for循环,如:

  for idx := 0 to grdInvoiceItems.Columns.Count - 1 do
    begin
    if (
         (grdInvoiceItems.Columns[idx].FieldName = 'UnitPrice') or
         (grdInvoiceItems.Columns[idx].FieldName = 'Discount') or
         (grdInvoiceItems.Columns[idx].FieldName = 'SecretCode')
       ) then
      grdInvoiceItems.Columns[idx].Visible := False;
    end;

使用colum name是IMO更好的tham列索引,因为索引比名称更容易发生变化。

关于如何更好地封装它的任何想法?

3 个答案:

答案 0 :(得分:12)

您可以尝试这样的事情:

function ColumnByName(Grid : TDBGrid; const AName : String) : TColumn;
var
  i : Integer;
begin
  Result := Nil;
  for i := 0 to Grid.Columns.Count - 1 do begin
  if (Grid.Columns[i].Field <> Nil) and (CompareText(Grid.Columns[i].FieldName, AName) = 0) then begin
       Result := Grid.Columns[i];
       exit;
     end;
  end;
end;

当然,如果您使用的是最近版本足以支持Class Helper的Delphi版本,您可以将此函数包装为Class Helper TDBGrid,就像这样

type
  TGridHelper = class helper for TDBGrid
    function ColumnByName(const AName : String) : TColumn;
  end;
[...]

function TGridHelper.ColumnByName(const AName: String): TColumn;
var
  i : Integer;
begin
  Result := Nil;
  for i := 0 to Columns.Count - 1 do begin
     if (Columns[i].Field <> Nil) and (CompareText(Columns[i].FieldName, AName) = 0) then begin
       Result := Columns[i];
       exit;
     end;
  end;
end;

然后,你可以这样做

Col := DBGrid1.ColumnByName('SomeName');

显然,你可以编写一个类似的函数来搜索列的标题,而不是相关的Field的FieldName。

答案 1 :(得分:1)

您可以在列名和网格索引之间创建映射,例如作为字典并使用它。请注意,并非数据集中的每个列都必须在dbgrid中可见。此外,数据集中可能存在计算字段,因此请不要忘记这些字段。创建映射的最安全方法是迭代dbgrid的列,并将其字段名称与列索引一起存储。这样您就不会获得任何无效条目,并且映射中没有的任何字段都没有dbgrid列。

答案 2 :(得分:0)

我想做类似的事情,但我在想,如果 dbgrid 不知道列名 (对于这种情况),也许还有其他 (说到组件) 确实已经知道了。

就我而言,我使用 fdquery -> 数据源 -> DBgrid 连接。 FDQuery 通过名称和 ID 识别字段。

因此考虑到您使用类似的组件,您可以做到

dbgrid1.Columns[fdquery1.FieldByName('UnitPrice').Index].visible:=false;