FireMonkey中TEdit.TagObject创建新对象后MyElement未同步的问题
解决FireMonkey中TMyEdit与TMyProperty双向绑定的指针同步问题
问题根源分析
你遇到的核心问题是Delphi对象变量的指针传递特性:当MyElement初始为nil时,你执行Edit1.TagObject := TMyTextProperty(MyElement),其实是把nil赋值给了TagObject——这两个变量(MyElement和TagObject)是独立的指针,只是暂时都指向nil。
当你在MyOnChange中给TagObject赋值新创建的TMyTextProperty实例时,你只是修改了TagObject这个指针变量的指向,而MyElement这个外部变量完全不知道这件事,它依然保持nil。因为两者是独立的指针,没有建立“引用关联”。
解决方案
这里提供两种实用的解决思路,你可以根据自己的需求选择:
方案1:使用事件回调通知外部更新(推荐,符合Delphi事件驱动模型)
这种方式通过给TMyEdit添加一个自定义事件,当内部创建新的TMyTextProperty实例时,主动通知外部代码将MyElement指向新对象,实现双向同步。
- 首先扩展
TMyEdit类,添加自定义事件:
type // 定义事件类型,用于传递新创建的属性对象 TOnPropertyCreated = procedure(Sender: TObject; NewProperty: TMyTextProperty) of object; TMyEdit = class(TEdit) private FOnPropertyCreated: TOnPropertyCreated; procedure MyOnChange(Sender: TObject); public // 暴露事件给外部代码 property OnPropertyCreated: TOnPropertyCreated read FOnPropertyCreated write FOnPropertyCreated; end;
- 修改
MyOnChange方法,创建新对象时触发事件:
procedure TMyEdit.MyOnChange(Sender : TObject); var NewProp: TMyTextProperty; begin if TagObject = nil then begin NewProp := TMyTextProperty.Create(''); TagObject := NewProp; // 如果外部注册了事件,就通知它更新MyElement if Assigned(FOnPropertyCreated) then FOnPropertyCreated(Self, NewProp); end; TMyTextProperty(TagObject).Value := Text; end;
- 在外部代码中注册事件,让
MyElement同步指向新对象:
// 初始化Edit1时注册事件 Edit1.OnPropertyCreated := procedure(Sender: TObject; NewProperty: TMyTextProperty) begin MyElement := NewProperty; // 让外部的MyElement指向新创建的对象 end; // 初始绑定(即使MyElement是nil也没关系) Edit1.TagObject := TMyTextProperty(MyElement);
方案2:使用双重指针直接修改外部变量(更直接,但需注意类型安全)
这种方式通过在TagObject中存储MyElement的地址(即指针的指针),直接在MyOnChange中修改外部变量的指向。
- 外部代码中,把
MyElement的地址赋值给TagObject:
// 注意:这里存储的是MyElement变量的地址,不是对象地址 Edit1.TagObject := @MyElement;
- 修改
MyOnChange方法,通过双重指针更新外部变量:
procedure TMyEdit.MyOnChange(Sender : TObject); var PropPtr: ^TMyTextProperty; // 定义指向TMyTextProperty指针的指针 begin PropPtr := TagObject; // 如果外部的MyElement是nil,创建新对象并直接赋值给它 if PropPtr^ = nil then begin PropPtr^ := TMyTextProperty.Create(''); end; // 同步文本到属性 PropPtr^.Value := Text; end;
这种方式不需要额外的事件,直接通过指针操作修改外部变量,但要确保TagObject存储的确实是TMyTextProperty类型变量的地址,否则容易引发类型错误。
额外说明
如果要实现完整的双向同步(对象属性变化时更新Edit的文本),你还需要给TMyTextProperty添加属性变更事件,当Value改变时主动更新TMyEdit的Text属性,这样就完成了双向绑定。
内容的提问来源于stack exchange,提问作者costateixeira
相关产品推荐
相关产品推荐

