【问题标题】:Common handler for DBGrid and DBGridEh's columns visibilityDBGrid 和 DBGridEh 的列可见性的通用处理程序
【发布时间】:2021-12-02 01:05:31
【问题描述】:

TDBGridEh 属于哪个类?我试过了:

if (AForm.Components[i] IS TDBGridEh)
if (AForm.Components[i] IS TCustomDBGrid) or 
if (AForm.Components[i] IS TCustomGrid) or
if (AForm.Components[i] IS TDBGrid) or 
 

但我收到错误:未声明的标识符 '***'

更新:

这是TMainMenu 的子元素和TDBGrid 的列的常用处理程序。我必须在这个通用处理程序中为TDBGridEh 添加一些代码。

有没有办法为TDBGridTDBGridEhTMainMenu 的子元素设置一个过程?

procedure RightsOnSubElements(AForm: TForm; AComp: TComponent);

  function FindFieldColumn(AComp: TComponent; const FieldName: String):  TColumn;
  var
    i: Integer;
  begin
    Result := nil;
    for i := 0 to (AComp as TDBGrid).Columns.Count - 1 do
      if AnsiCompareText((AComp as TDBGrid).Columns[i].FieldName, FieldName) = 0 then
      begin
        Result := (AComp as TDBGrid).Columns[i];
        Break;
      end;
  end;
     
var
  Column : TColumn;
  i: Integer;
begin
  fMain.qSubElements.Close;
  fMain.qSubElements.Parambyname('Form_Name').AsString := AForm.Name;
  fMain.qSubElements.Parambyname('ROLE_ID').AsInteger := ROLE_ID;
  fMain.qSubElements.Parambyname('name').AsString := AComp.Name;
  fMain.qSubElements.Open;
  if fMain.qSubElements.RecordCount > 0 then begin
    while not fMain.qSubElements.Eof do begin
      for i := 0 to AForm.ComponentCount - 1 do
        if (AForm.Components[i] is TMenuItem) then begin
          if UpperCase(AForm.Components[i].Name) = UpperCase(fMain.qSubElements.FieldByName('Sub_Name').AsString) then
          begin
            (AForm.Components[i] as TMenuItem).Visible := fmain.qSubElements.FieldByName('Visible').AsBoolean;
            (AForm.Components[i] as TMenuItem).Enabled := fmain.qSubElements.FieldByName('Enabled').AsBoolean;
          end;
        end
        else if (AForm.Components[i] is TDBGrid) then begin
          if UpperCase(AForm.Components[i].Name) = UpperCase(fMain.qSubElements.FieldByName('Name').AsString) then
          begin
            Column := FindFieldColumn(AComp as TDBGrid, fMain.qSubElements.FieldByName('sub_name').AsString);
            if Assigned(Column) then Column.Visible := fMain.qSubElements.FieldByName('Visible').AsBoolean;
          end;
      end;
                
      fMain.qSubElements.Next;
    end;
  end;
end;

【问题讨论】:

  • 您知道您可以使用ClassParent 方法来查找应用程序中每个现有类的父类。将其放入循环中,您可以获得一整棵层次结构树。

标签: delphi


【解决方案1】:

DBGridEh 组件的父类是什么?

根据EhLib的documentation

因此,当AForm.Components[i] 引用TDBGridEh 对象时,它将对TDBGridEh 测试为阳性,但对TCustomDBGridTCustomGridTDBGrid 测试为阴性。

您已经知道如何区分 TMainMenuTDBGrid,那么是什么阻止您区分 TDBGridEhTDBGrid

procedure RightsOnSubElements(AForm: TForm; AComp: TComponent);

  function FindFieldColumn(AComp: TDBGrid; const FieldName: String): TColumn;
  var
    i: Integer;
  begin
    for i := 0 to AComp.Columns.Count - 1 do begin
      Result := AComp.Columns[i];
      if SameText(Reslut.FieldName, FieldName) then
        Exit;
    end;
    Result := nil;
  end;
     
  function FindFieldColumnEh(AComp: TDBGridEh; const FieldName: String): TColumnEh;
  var
    i: Integer;
  begin
    for i := 0 to AComp.Columns.Count - 1 do begin
      Result := AComp.Columns[i];
      if SameText(Result.FieldName, FieldName) then
        Exit;
    end;
    Result := nil;
  end;

var
  Comp: TComponent;
  Column : TColumn;
  ColumnEh : TColumnEh;
  i: Integer;
begin
  fMain.qSubElements.Close;
  fMain.qSubElements.Parambyname('Form_Name').AsString := AForm.Name;
  fMain.qSubElements.Parambyname('ROLE_ID').AsInteger := ROLE_ID;
  fMain.qSubElements.Parambyname('name').AsString := AComp.Name;
  fMain.qSubElements.Open;
  while not fMain.qSubElements.Eof do begin
    Comp := AForm.FindComponent(fMain.qSubElements.FieldByName('Name').AsString);
    if (Comp is TMenuItem) then begin
      with TMenuItem(Comp) do begin
        Visible := fmain.qSubElements.FieldByName('Visible').AsBoolean;
        Enabled := fmain.qSubElements.FieldByName('Enabled').AsBoolean;
      end;
    end
    else if (Comp is TDBGrid) then begin
      Column := FindFieldColumn(TDBGrid(Comp), fMain.qSubElements.FieldByName('Sub_Name').AsString);
      if Column <> nil then Column.Visible := fMain.qSubElements.FieldByName('Visible').AsBoolean;
    end
    else if (Comp is TDBGridEh) then begin
      ColumnEh := FindFieldColumnEh(TDBGridEh(Comp), fMain.qSubElements.FieldByName('Sub_Name').AsString);
      if Column <> nil then Column.Visible := fMain.qSubElements.FieldByName('Visible').AsBoolean;
    end;                
    fMain.qSubElements.Next;
  end;
end;

话虽如此,由于TDBGridEhTDBGrid 具有相似的接口,但实际上并非派生自TDBGrid,因此在Delphi 2009+ 中,您可以使用@987654327 为TDBGridTDBGridEh 编写通用代码@,例如:

type
  TInternalDBGridHelper<TDBGridType: class, TColumnType: class> = class 
    class function FindFieldColumn(AGrid: TDBGridType; const AFieldName: string): TColumnType;
    class procedure SetFieldColumnVisible(AGrid: TDBGridType; const AFieldName: string; AVisible: Boolean);
  end;

  TInternalHelper_DBGrid   = TInternalDBGridHelper<TDBGrid, TColumn>;
  TInternalHelper_DBGridEh = TInternalDBGridHelper<TDBGridEh, TColumnEh>;

  TDBGridHelper = class helper for TDBGrid
    procedure SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
  end;

  TDBGridEhHelper = class helper for TDBGridEh
    procedure SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
  end;

class function TInternalDBGridHelper<TDBGridType, TColumnType>.FindFieldColumn(
  AGrid: TDBGridType; const AFieldName: string): TColumnType;
var
  I: Integer;
begin
  for I := 0 to AGrid.Columns.Count-1 do
  begin
    Result := AGrid.Columns[I];
    if SameText(Result.FieldName, AFieldName) then
      Exit;
  end;
  Result := nil;
end;

class function TInternalDBGridHelper<TDBGridType, TColumnType>.SetFieldColumnVisible(
  AGrid: TDBGridType; const AFieldName: string; AVisible: Boolean);
var
  Column: TColumnType;
begin
  Column := FindFieldColumn(AGrid, AFieldName);
  if Assigned(Column) then Column.Visible := AVisible;
end;

procedure TDBGridHelper.SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
begin
  TInternalHelper_DBGrid.SetFieldColumnVisible(Self, AFieldName, AVisible);
end;

procedure TDBGridEhHelper.SetFieldColumnVisible(const AFieldName: string; AVisible: Boolean);
begin
  TInternalHelper_DBGridEh.SetFieldColumnVisible(Self, AFieldName, AVisible);
end;

procedure RightsOnSubElements(AForm: TForm; AComp: TComponent);
var
  Comp: TComponent;
  i: Integer;
begin
  fMain.qSubElements.Close;
  fMain.qSubElements.Parambyname('Form_Name').AsString := AForm.Name;
  fMain.qSubElements.Parambyname('ROLE_ID').AsInteger := ROLE_ID;
  fMain.qSubElements.Parambyname('name').AsString := AComp.Name;
  fMain.qSubElements.Open;
  while not fMain.qSubElements.Eof do begin
    Comp := AForm.FindComponent(fMain.qSubElements.FieldByName('Name').AsString);
    if (Comp is TMenuItem) then begin
      with TMenuItem(Comp) do begin
        Visible := fmain.qSubElements.FieldByName('Visible').AsBoolean;
        Enabled := fmain.qSubElements.FieldByName('Enabled').AsBoolean;
      end;
    end
    else if (Comp is TDBGrid) then begin
      TDBGrid(Comp).SetFieldColumnVisible(
        fMain.qSubElements.FieldByName('Sub_Name').AsString,
        fMain.qSubElements.FieldByName('Visible').AsBoolean);
    end
    else if (Comp is TDBGridEh) then begin
      TDBGridEh(Comp).SetFieldColumnVisible(
        fMain.qSubElements.FieldByName('Sub_Name').AsString,
        fMain.qSubElements.FieldByName('Visible').AsBoolean);
    end;                
    fMain.qSubElements.Next;
  end;
end;

【讨论】:

  • Remy Lebeau,正如我所见,没有一种通用程序可以设置 DBGrid 列、DBGridEh 列和 MainMenu 项的可见性。谢谢你的代码示例。
  • Remy Lebeau,你怎么称呼你的程序?例如,我这样调用我的程序:RightsOnSubElements(self, MainMenu1) 或 RightsOnSubElements(self, dbgrid1) 你呢? p.s.我在上面添加了完整的程序。谢谢。
  • "据我所知,没有办法为提供一个通用的程序——当它们有不同的类型时,没有。但是,如果他们有共同的名字,你总是可以求助于 RTTI。当然,您可以使用其他设计习惯用法(多态包装器等)。 “你怎么称呼你的程序?” - 我不明白你在问什么。我发布的示例向您展示了它们是如何被调用的。是什么阻止您将我的示例代码应用于您的情况?我已经更新了我的答案以显示这一点。
  • Remy Lebeau 我明天试试并告知结果。非常感谢您的尝试。
  • Remy Lebeau,显示编译错误:'未声明的标识符 TColumnType'、'TColumnType 不是类型标识符'、'未声明的标识符:'TInternalDBGridHelper'。 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 2015-04-17
  • 2019-08-17
相关资源
最近更新 更多