如何在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
相关产品推荐
相关产品推荐

