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

如何在绑定对象属性变更时通知Spring4D的TObjectDataSet

TObjectDataSet 模型属性变更后同步网格显示的解决方案

问题描述

  • 直接修改DataSet字段值时,关联网格会自动更新:
    ObjectDataSet.FieldByName('Description').AsString:='Bob';
    
  • 但直接修改当前模型的属性值时,网格无更新:
    ObjectDataSet.GetCurrentModel<TSaleLine>.Description:='Bob';
    

原因是TObjectDataSet默认不监控模型对象的属性变更,无法感知值变化,也就不会触发网格刷新逻辑。

你尝试的以下代码无效:

type
  TL = class(TGridDataLink);

begin
  ObjectDataSet.GetCurrentModel<TSaleLine>.Description:='Bob';

  var G:=TGridDataLink.Create(Grid);
  TL(G).RecordChanged(ObjectDataSet.FieldByName('Description'));
  G.Free;
end;

无效原因是手动创建的TGridDataLink未与DataSet的现有关联绑定,属于无关实例,无法触发网格的现有更新逻辑。


解决方案

方案1:给模型添加属性变更通知,让DataSet感知变化

步骤1:让模型类实现属性变更通知逻辑
type
  // 定义属性变更回调类型
  TPropertyChangedProc = TProc<string>;

  TSaleLine = class
  private
    FDescription: string;
    FOnPropertyChanged: TPropertyChangedProc;
    procedure SetDescription(const Value: string);
  public
    property Description: string read FDescription write SetDescription;
    // 暴露属性变更事件
    property OnPropertyChanged: TPropertyChangedProc read FOnPropertyChanged write FOnPropertyChanged;
  end;

procedure TSaleLine.SetDescription(const Value: string);
begin
  if FDescription <> Value then
  begin
    FDescription := Value;
    // 属性变更时触发通知
    if Assigned(FOnPropertyChanged) then
      FOnPropertyChanged('Description');
  end;
end;
步骤2:修改TObjectDataSet订阅模型的变更通知

在TObjectDataSet中,订阅当前模型的属性变更事件,触发字段更新通知:

type
  TObjectDataSet = class(TDataset)
  private
    FCurrentModel: TSaleLine;
    procedure HandleModelPropertyChanged(const PropertyName: string);
    procedure UpdateModelSubscription;
  protected
    procedure AfterScroll; override;
    procedure AfterOpen; override;
  end;

procedure TObjectDataSet.UpdateModelSubscription;
var
  NewModel: TSaleLine;
begin
  // 取消旧模型的订阅
  if Assigned(FCurrentModel) then
    FCurrentModel.OnPropertyChanged := nil;

  // 获取当前模型并订阅事件
  NewModel := GetCurrentModel<TSaleLine>;
  if Assigned(NewModel) then
  begin
    FCurrentModel := NewModel;
    FCurrentModel.OnPropertyChanged := HandleModelPropertyChanged;
  end
  else
    FCurrentModel := nil;
end;

procedure TObjectDataSet.AfterScroll;
begin
  inherited;
  // 切换记录时更新订阅
  UpdateModelSubscription;
end;

procedure TObjectDataSet.AfterOpen;
begin
  inherited;
  // 打开DataSet时初始化订阅
  UpdateModelSubscription;
end;

procedure TObjectDataSet.HandleModelPropertyChanged(const PropertyName: string);
var
  TargetField: TField;
begin
  TargetField := FieldByName(PropertyName);
  if Assigned(TargetField) then
  begin
    // 同步字段值(从模型读取最新值)
    TargetField.AsString := FCurrentModel.Description;
    // 触发字段变更事件,通知网格更新
    DataEvent(deFieldChange, NativeInt(TargetField));
  end;
end;

方案2:业务层手动触发更新(无需修改DataSet源码)

如果无法修改TObjectDataSet源码,修改模型属性后直接手动通知刷新:

begin
  ObjectDataSet.GetCurrentModel<TSaleLine>.Description:='Bob';
  
  // 方法1:刷新指定字段并触发变更事件
  with ObjectDataSet.FieldByName('Description') do
  begin
    Refresh;
    ObjectDataSet.DataEvent(deFieldChange, NativeInt(Self));
  end;

  // 方法2:强制刷新网格
  Grid.Invalidate;
end;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 23:54:50