如何在TMS WEB Core中使用GetClass动态创建TWebFrame?
问题描述
静态创建并加载TWebFrame到窗体的函数运行正常,但需要根据类名字符串动态创建组件。尝试用GetClass实现的代码编译通过,但运行时调用LoadFromForm出现Uncaught TypeError: Cannot read properties of null (reading 'appendChild')错误,且已在帧的.pas文件中注册TFrame_Home类。因需创建大量帧,不想硬编码,求正确的动态创建方法。
原静态创建代码:
procedure LoadHomePage(); var FramePage: TWebFrame; begin FramePage := TFrame_Home.Create(Self); FramePage.Name := 'layHome'; FramePage.Visible := False; FramePage.Parent := LayoutContainer; FramePage.Align := alClient; FramePage.LoadFromForm; end;
尝试的动态创建代码:
procedure LoadHomePageDynamically(); var FrameClass: TPersistentClass; FramePage: TWebFrame; begin FrameClass := GetClass('TFrame_Home'); FramePage := TWebFrame(FrameClass.Create); FramePage.Name := 'layHome'; FramePage.Visible := False; FramePage.Parent := LayoutContainer; FramePage.Align := alClient; FramePage.LoadFromForm; end;
解决方法
1. 核心问题:创建组件时未传入Owner参数
静态代码中TFrame_Home.Create(Self)传入了Owner(Self),但动态代码里FrameClass.Create无参数调用,导致组件初始化时缺少必要的上下文关联,最终引发DOM操作的空指针错误。
2. 修正后的动态创建代码
procedure LoadHomePageDynamically(); var FrameClass: TWebFrameClass; // 改用TWebFrameClass类型,避免强制类型转换风险 FramePage: TWebFrame; begin // 获取注册的类,确保类已正确注册且对应单元被引用 FrameClass := TWebFrameClass(GetClass('TFrame_Home')); if not Assigned(FrameClass) then raise Exception.CreateFmt('类 %s 未注册或未引用对应单元', ['TFrame_Home']); // 创建组件时传入Owner参数,匹配静态代码的初始化逻辑 FramePage := FrameClass.Create(Self); // 后续属性设置与加载逻辑保持不变 FramePage.Name := 'layHome'; FramePage.Visible := False; FramePage.Parent := LayoutContainer; FramePage.Align := alClient; FramePage.LoadFromForm; end;
3. 确保类注册和单元引用正确
- 必须在
TFrame_Home所在的.pas文件中添加注册代码:initialization RegisterClass(TFrame_Home); - 确保包含
TFrame_Home的单元已被主窗体单元引用,否则GetClass无法定位到该类。
4. 可选:RTTI方式创建(适用于复杂场景)
如果需要更灵活的类型创建,可通过RTTI实现:
uses System.Rtti; procedure LoadHomePageDynamically(); var RttiContext: TRttiContext; RttiType: TRttiType; ConstructorMethod: TRttiMethod; FramePage: TWebFrame; begin RttiContext := TRttiContext.Create; try // 需指定类的完整命名空间 RttiType := RttiContext.FindType('你的命名空间.TFrame_Home'); if not Assigned(RttiType) then raise Exception.Create('未找到目标类'); ConstructorMethod := RttiType.GetMethod('Create'); if not Assigned(ConstructorMethod) then raise Exception.Create('未找到合适的构造函数'); // 调用构造函数并传入Owner参数 FramePage := ConstructorMethod.Invoke(RttiType.AsInstance.MetaclassType, [Self]).AsType<TWebFrame>; // 属性设置与加载逻辑 FramePage.Name := 'layHome'; FramePage.Visible := False; FramePage.Parent := LayoutContainer; FramePage.Align := alClient; FramePage.LoadFromForm; finally RttiContext.Free; end; end;
内容的提问来源于stack exchange,提问作者Shaun Roselt
相关产品推荐
相关产品推荐

