delphi - 如何(正确)使用带有实时绑定(bind)的枚举类型(TObjectBindSourceAdapter)

标签 delphi enums livebindings

我正在使用 TObjectBindSourceAdapter 对对象使用实时绑定(bind)。 我与 TObjectBindSourceAdapter 一起使用的对象的属性之一具有枚举类型,但当我在对象中使用枚举类型时,适配器中的字段永远不会生成

我目前找到的唯一解决方案是将枚举类型定义为对象中的整数并对其进行类型转换。这似乎工作正常,但您必须保持枚举类型和整数的类型转换和返回。

这里有一些示例代码来解释我的意思。

第一个示例使用我最初尝试的枚举类型,但似乎不起作用:

 uses Data.Bind.ObjectScope;

 Type
   TMyEnumtype = (meOne, meTwo, meThree);

   TMyObject = class
     public
       MyEnumType: TMyEnumtype;
  end;

procedure TForm9.But1Click(Sender: TObject);
var
  MyObject: TMyObject;
  aBindSourceAdapter: TBindSourceAdapter;
begin
  MyObject := TMyObject.Create;
  MyObject.MyEnumType := meTwo;
  aBindSourceAdapter := TObjectBindSourceAdapter<TMyObject>.Create(nil, MyObject, False);
  if aBindSourceAdapter.FindField('MyEnumType') <> nil then
    ShowMessage('MyEnumType found')
  else
    showmessage('MyEnumType not found');
  FreeAndNil(MyObject);
  FreeAndNil(aBindSourceAdapter);
end;

第二个示例似乎通过类型转换为整数来工作

uses Data.Bind.ObjectScope;

Type
  TMyEnumtype = (meOne, meTwo, meThree);

  TMyObject = class
    public
      MyEnumType: integer;
  end;

procedure TForm9.But1Click(Sender: TObject);
var
  MyObject: TMyObject;
  aBindSourceAdapter: TBindSourceAdapter;
  aEnumType : TMyEnumtype;
begin
  MyObject := TMyObject.Create;
  MyObject.MyEnumType := Integer(meTwo);
  aBindSourceAdapter := TObjectBindSourceAdapter<TMyObject>.Create(nil, MyObject, False);
  if aBindSourceAdapter.FindField('MyEnumType') <> nil then
    ShowMessage('MyEnumType found')
  else
    showmessage('MyEnumType not found');

  aEnumType := TMyEnumtype(aBindSourceAdapter.FindField('MyEnumType').GetTValue.AsInteger);

  if aEnumType =  meTwo then
    showmessage('meTwo');

  FreeAndNil(MyObject);
  FreeAndNil(aBindSourceAdapter);
end;

我想知道其他人是否遇到过这个问题,以及是否有其他解决方案可以解决这个问题,而无需恢复为整数并继续使用枚举类型。我也不确定我的解决方法是否是执行此操作的常用方法。

最佳答案

我认为最好的方法是注册转换器。事实证明这非常简单,但前提是要深入研究 VCL 源代码。我没有找到任何有用的文档。但它就在这里。

unit MyConverters;

interface

uses System.Rtti, System.Bindings.Outputs;

type
  TMyEnum = (Value1, Value2, Value3);

implementation

procedure RegisterConverters;
begin
  TValueRefConverterFactory.RegisterConversion(TypeInfo(TMyEnum), TypeInfo(string),
    TConverterDescription.Create(
      procedure(const InValue: TValue; var OutValue: TValue)
      var
        MyEnum: TMyEnum;
        S: string;
      begin
        MyEnum := InValue.AsType<TMyEnum>;
        case MyEnum of
          Value1:  S := 'First Value';
          Value2:  S := 'Second Value';
          Value3:  S := 'Third Value';
          else     S := 'Other';
        end;
        OutValue := TValue.From<string>(S);
      end,
      'TMyEnumToString',
      'TMyEnumToString',
      '', // TODO what is the AUnitName param used for?
      True, // TODO what is ADefaultEnabled used for?  What does it mean?
      'Converts a TMyEnum value to a string',
      nil)
  );
end;

initialization
  RegisterConverters;
end.

简而言之,您调用 TValueRefConverterFactor.RegisterConversion() 并传入:

  • 此转换器转换的类型FROM
  • 此转换器转换的类型TO
  • 一个 TConverterDescription,其中包含一个实际执行转换的匿名过程以及一些其他元数据。

在上面的代码中,initialization 部分调用 RegisterConverters,因此所需要做的就是在项目中包含该单元,实时绑定(bind)框架将使用转换器每当需要将 TMyEnum 值转换为 string 时。

关于delphi - 如何(正确)使用带有实时绑定(bind)的枚举类型(TObjectBindSourceAdapter),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16943387/

相关文章:

delphi - 我们可以在Delphi XE2 LiveBinding表达式中使用 bool 运算符吗?

mysql - 在 MySQL 中返回枚举值的最佳方法是什么?

delphi - 如何在Delphis LiveBindings中提取BindSource的对象?

arrays - 创建一个默认值的 TDictionary 常量数组

sql - dbExpress TSQLConnection参数问题

c# - 为 List<Enum> 构建通用方法

java - 不使用 extends 的 Java 中的可扩展枚举

delphi - LiveBinding 的用法

delphi - 如何制作一个自定义组件来检测表单上是否有新组件

delphi - 使用 VCL 样式时覆盖某些 TBitButton 的样式