You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TPrototypeBindSource.OnCreateAdapter外部创建绑定对象?

搞定TPrototypeBindSource移ViewModel创建到窗体构造函数的坑

我之前折腾Delphi数据绑定时也碰到过一模一样的问题,咱们先搞明白根源,再给你俩靠谱的解决办法:

为啥原来的写法没问题?

你之前在OnCreateAdapter事件里创建ViewModel是踩对了时机——这个事件是TPrototypeBindSource自身初始化完全完成后,才会触发的,它已经准备好接收你创建的对象并生成适配器了。但你移到窗体构造函数(TForm.Create)时,TPrototypeBindSource的内部绑定逻辑还没初始化好,相当于你提前把对象塞给了一个还没睡醒的控件,自然会出问题。

两种可行的解决思路

思路1:手动叫醒控件(强制重建适配器)

如果你铁了心要在窗体构造函数里创建ViewModel,那就在构造函数末尾手动触发适配器重建,让TPrototypeBindSource用你提前创建好的对象:

constructor TForm.Create(AOwner: TComponent);
begin
  inherited;
  // 先创建ViewModel
  _viewModel := TViewModel.Create;
  // 强制PrototypeBindSource重新生成适配器,用咱们的ViewModel
  PrototypeBindSource.RecreateAdapter;
end;

// 同时修改OnCreateAdapter事件,直接用已有的ViewModel就行
procedure TForm.PrototypeBindSourceCreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TObjectBindSourceAdapter<TViewModel>.Create(Self, _viewModel);
end;

思路2:换个更稳妥的时机(移到FormCreate事件)

其实没必要死磕构造函数,把ViewModel的创建移到窗体的OnCreate事件里更省心——这个事件是在所有控件都初始化完毕后才触发的,此时TPrototypeBindSource已经完全就绪了:

procedure TForm.FormCreate(Sender: TObject);
begin
  _viewModel := TViewModel.Create;
  // 直接给PrototypeBindSource指定适配器就行
  PrototypeBindSource.Adapter := TObjectBindSourceAdapter<TViewModel>.Create(Self, _viewModel);
end;

// 这时候OnCreateAdapter事件可以留空,或者也直接用已有的ViewModel
procedure TForm.PrototypeBindSourceCreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TObjectBindSourceAdapter<TViewModel>.Create(Self, _viewModel);
end;

最后提个关键注意点

别忘了在窗体销毁时释放ViewModel,不然会内存泄漏:

procedure TForm.FormDestroy(Sender: TObject);
begin
  _viewModel.Free;
end;

内容的提问来源于stack exchange,提问作者aQuu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:44:07