【问题标题】:Delphi Live binding, error converting text to TStrings fieldDelphi Live 绑定,将文本转换为 TStrings 字段时出错
【发布时间】:2021-11-26 08:06:23
【问题描述】:

德尔福 10.4

我遇到了双向 Tstrings 绑定问题。我有一个带有 2 个控件和一个绑定源的简单应用程序。我正在尝试将对象的 TStrings 属性双向绑定到 TMemo 控件。我正在使用带有 TObjectBindSourceAdapter 的 TPrototypeBindSource 作为绑定源适配器。

我将 TPrototypeBindSource 上的 lines 属性设置为 ftTStrings 字段类型

TFoo 定义为;

  TFoo = class  (TObject)
  private
    Fname: string;
    flines: TStrings;
  published
    constructor Create;
    destructor destroy; override;
    property name: string read Fname write Fname;
    property lines: Tstrings read Flines write Flines;
  end;

适配器是通过 on create 事件设置的

procedure TForm1.PrototypeBindSource1CreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TObjectBindSourceAdapter<TFoo>.Create(Self, GetFoo, False);
end;

使用实时绑定我有

PrototypeBindSource name fielddef 编辑文本字段。 PrototypeBindSource 行 fielddef 备注文本字段。

当您阅读或更新名称 编辑控件以及设置备注文本字段时,一切都很好。它将 TPrototypeBindSource 中的 lines 字段识别为 TStrings。

但是,当我更改备忘录中的文本并将其发布回 TPrototypeBindSource 时,我得到了这个异常

EBindConverterError : 无法在类型字符串和 TObject 之间转换或找到转换器

有一个 TStrings to string 和 string to TStrings 转换器注册。但是对象中的 TString 和适配器之间似乎存在脱节,因为它似乎看不到它的类型。

是我遗漏了什么还是 RTL 有问题?

编辑:

谢谢,我错过了那个二传手。即使解决了问题仍然存在......

  TFoo = class  (TObject)
    ...
    procedure SetLines(const aValue: TStrings);
    ...
  end;

procedure TFoo.SetLines(const Value: TStrings);
begin
  Flines.Assign(Value);
end;

转换器不通过他们使用 TStrings 文本属性的设置器

system.bindings.outputs

class procedure TConverterUtils.StringToStrings(const I: TValue; var O: TValue);
var
  oOut: TStrings;
begin
  oOut := TStrings(O.AsObject);                                            
  if oOut <> nil then
  begin
    if I.IsEmpty then
      oOut.Text := ''
    else
      oOut.Text := I.AsString;
  end;
end;

跟踪绑定代码,转换器在这里被调用

procedure TBindingOutput.SetValue(AExpression: TObject; const ValueFunc: TBindOutValueFunc);

begin
...
  if AllowConverter then
    CanConvert := ValueConverter.CanConvert(LFinalOutVal.TypeInfo, LocationRec.Location.GetType);
...
end

哪个电话;

function TValueRefConverter.CanConvert(AFrom, ATo: PTypeInfo): Boolean;
begin
  Result := GetConverter(AFrom, ATo, False) <> nil;
end;

当从 TStrings 属性转到 TMemo 上的 Text 属性时,AFrom 的 TypeInfo 显示为 TStringlist,但是当它以另一种方式返回时,ATo PTypeInfo 显示 TObject 而不是 TStringList。

由于转换器是为 TStrings 注册的,它找不到合适的转换器。

我在试图弄清楚信息的存储位置时迷路了。

【问题讨论】:

  • 您创建活页夹适配器的代码是否正确?查看 Delphi 附带的 LiveBindings\AdapterbindSource 示例,您似乎定义了适配器绑定器代码错误。难道不是ABindSourceAdapter := TObjectBindSourceAdapter&lt;TStrings&gt;.Create(Self, GetFoo, False);。您需要告诉活页夹适配器它将使用什么类型的数据。但是在您的代码中,您正在传递自定义对象的类。这可能就是你得到TObject 类型而不是预期的TStrings 的原因。

标签: delphi livebindings


【解决方案1】:

如果您查看TMemo 源代码,您会发现Lines 属性的定义与您的Lines 属性不同

property Lines: TStrings read FLines write SetLines;

如您所见,TMemolines 属性依赖于使用 writer 方法,而不是像在代码中那样直接写入 FLines 字段。

在那个SetLines writer方法TStrings.Assign方法被调用。

procedure TCustomMemo.SetLines(Value: TStrings);
begin
  FLines.Assign(Value);
end;

使用此方法将字符串从源复制到目标。

设置编码的方式只需将源TLines 对象的引用分配给flines 字段,使两个对象共享相同的TLines 对象。这是非常危险的,因为如果源对象被破坏,您的对象最终会引用不再存在的数据,这可能会导致很多问题。

修复您的 Lines 属性以匹配 TMemo 的设计,这应该可以解决您的问题

【讨论】:

  • 修复了二传手,谢谢。问题仍然存在,请参阅更新的问题。干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多