Общий обработчик для видимости столбцов DBGrid и DBGridEh

#delphi

#delphi

Вопрос:

К какому классу 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 .

Есть ли способ иметь одну процедуру для подэлементов TDBGrid , TDBGridEh , и TMainMenu ?

 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;
 

Комментарии:

1. Вы знаете, что можете использовать метод ClassParent для поиска родительского класса каждого существующего класса в вашем приложении. Поместите это в цикл, и вы можете получить целое иерархическое дерево.


Ответ №1:

Что является родительским классом компонента DBGridEh?

Согласно документации EhLib:

Таким образом, при AForm.Components[i] обращении к TDBGridEh объекту он будет положительным для TDBGridEh , но будет отрицательным для TCustomDBGrid , TCustomGrid , и TDBGrid .

Вы уже знаете, как отличать TMainMenu от TDBGrid , так что же мешает вам отличать TDBGridEh от TDBGrid ?

 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;
 

При этом, поскольку TDBGridEh имеет аналогичные интерфейсы, но фактически не является производным от, TDBGrid , то в Delphi 2009 вы могли бы написать общий код для обоих TDBGrid и TDBGridEh с помощью дженериков, например:

 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;
 

Комментарии:

1. Реми Лебо, как я вижу, нет способа создать одну общую процедуру для настройки видимости столбцов DBGrid, столбцов DBGridEh и элементов MainMenu. Спасибо за ваш пример кода.

2. Реми Лебо, как ты называешь свою процедуру? Например, я вызываю свою процедуру так: RightsOnSubElements(self, MainMenu1) или RightsOnSubElements(self, dbgrid1) а вы? p.s. Я добавляю полную процедуру выше. Спасибо.

3. » Как я вижу, нет способа иметь одну общую процедуру для » — не тогда, когда у них разные типы, нет. Но, если у них общие имена, вы всегда можете прибегнуть к RTTI. Конечно, вместо этого вы можете использовать другие идиомы дизайна (полиморфные оболочки и т. Д.). » как вы называете свою процедуру? » — Я не понимаю, о чем вы спрашиваете. В примере, который я опубликовал, показано, как они вызываются. Что мешает вам применить мой пример кода к вашей ситуации? Я обновил свой ответ, чтобы показать это.

4. Реми Лебо Я попробую завтра и сообщу о результате. большое вам спасибо за ваши попытки.

5. Реми Лебо, отображаются ошибки компиляции: ‘необъявленный идентификатор TColumnType’, ‘TColumnType не является идентификатором типа’, ‘Необъявленный идентификатор: ‘TInternalDBGridHelper’. 🙁