У меня есть TFrame, унаследованный от TBaseFrame = class (TFrame)
Внутри него встроен TFrame с таким же наследованием.
TViewStandardMovimentoFinanceiro = class(TFrameBase)
ViewStandardEdiMovimentoFinanceiro1: TViewStandardEdiMovimentoFinanceiro;
TViewStandardEdiMovimentoFinanceiro = class(TFrameBase)
TFrameBase = class(TFrame, INaharView, INaharViewAdapter)
TViewStandardMovimentoFinanceiro создается с родительским элементом, установленным для основной формы (в частности, для THorzScrollBox)
ВНУТРИ кадра TViewStandardMovimentoFinanceiro я попробовал классический подход с использованием списка детей и не нашел этот встроенный TFrame.
Я также безуспешно пытался использовать список «Родительские дети». То же самое и со списком компонентов
Что я хочу сделать, так это найти все доступные TFrames, чтобы я мог запросить интерфейс (я знаю, как это сделать)
Что мне не хватает?
Следуя приведенным ниже рекомендациям, я реализовал этот код для тестирования:
function TFrameBase.LocateControl(AControl: TControl; ADomainName: string): TControlHandler;
var
NaharView: INaharView;
ControlHandler: TControlHandler;
i: integer;
begin
result := nil;
for i := 0 to AControl.ChildrenCount - 1 do
if (AControl.Children[i] is TFrame) and (AControl.Children[i] <> Self) then
if Supports((AControl.Children[i] as TFrame), INaharView, NaharView) then
begin
ControlHandler := NaharView.Control[ADomainName];
if Assigned(ControlHandler) then
exit(ControlHandler);
end;
end;
function GetUltimateParent(Control: TControl): TControl;
begin
if Control.Parent is TControl then
Result := GetUltimateParent(TControl(Control.Parent))
else
Result := Control;
end;
function TFrameBase.GetNaharControl(ADomainName: string): TControlHandler;
var
i: integer;
ControlHandler: TControlHandler;
begin
if NaharControls.ContainsKey(ADomainName) then
Exit(NaharControls.Items[ADomainName])
else
begin
ControlHandler := LocateControl(GetUltimateParent(Self), ADomainName);
if Assigned(ControlHandler) then
exit(ControlHandler);
end;
raise EViewControlDomainNameNotFound.Create(ADomainName);
end;
Когда выполняется LocateControl, он поднимается на несколько уровней вверх и оттуда пытается выполнить итерацию по списку дочерних элементов, он содержит только 3 элемента в форме, полной элементов управления.
@OndrejKelle, хорошо, как мне получить конечного родителя, чтобы я мог перебирать потомков? в конце концов, мой родитель не является непосредственно TForm?
Попробуйте что-нибудь рекурсивное, например function GetUltimateParent(Control: TControl): TControl; begin if Control.Parent is TControl then Result := GetUltimateParent(TControl(Control.Parent)) else Result := Control; end;
@OndrejKelle Я реализовал ваше предложение, и оно поднялось на несколько уровней вверх, а в ChildrenCount всего 3 объекта. Так что, похоже, что-то не так или совсем другое в FMX. Я разместил код вопроса.
Поиск детей тоже должен быть рекурсивным.
Как заявил Ондрей, ваша функция LocateControl должна быть рекурсивной. Что-то вроде этого
function TFrameBase.LocateControl(AControl: TControl; ADomainName: string): TControlHandler;
var
NaharView: INaharView;
ControlHandler: TControlHandler;
i: integer;
begin
result := nil;
for i := 0 to AControl.ChildrenCount - 1 do
begin
if (AControl.Children[i] is TFrame) and (AControl.Children[i] <> Self) then
begin
if Supports((AControl.Children[i] as TFrame), INaharView, NaharView) then
begin
ControlHandler := NaharView.Control[ADomainName];
if Assigned(ControlHandler) then
begin
exit(ControlHandler);
end;
end;
end;
// recursive bit
Result := LocateControl(AControl.Children[i], ADomainName):
if assigned( Result ) then
begin
exit;
end;
end;
end;
Shure Ondrej заслуживает признания, но, поскольку вы опубликовали окончательное решение в качестве ответа, я принял его. Это сработало.
Наверное, что-то в вашем коде. В VCL TFrame является потомком TWinControl, поэтому рекурсивное повторение дочерних элементов от конечного родителя (формы) должно найти любые экземпляры. В FireMonkey TFrame является потомком TControl, но действует тот же принцип.