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

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指向新对象,实现双向同步。

  1. 首先扩展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;
  1. 修改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;
  1. 在外部代码中注册事件,让MyElement同步指向新对象:
// 初始化Edit1时注册事件
Edit1.OnPropertyCreated := procedure(Sender: TObject; NewProperty: TMyTextProperty)
begin
  MyElement := NewProperty; // 让外部的MyElement指向新创建的对象
end;

// 初始绑定(即使MyElement是nil也没关系)
Edit1.TagObject := TMyTextProperty(MyElement);

方案2:使用双重指针直接修改外部变量(更直接,但需注意类型安全)

这种方式通过在TagObject中存储MyElement的地址(即指针的指针),直接在MyOnChange中修改外部变量的指向。

  1. 外部代码中,把MyElement的地址赋值给TagObject:
// 注意:这里存储的是MyElement变量的地址,不是对象地址
Edit1.TagObject := @MyElement;
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:23:15