如何(正确)使用带有实时绑定的枚举类型(TObjectBindSourceAdapter) [英] how to (correctly) use an enumerated type with livebindings (TObjectBindSourceAdapter)

查看:41
本文介绍了如何(正确)使用带有实时绑定的枚举类型(TObjectBindSourceAdapter)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using TObjectBindSourceAdapter to use livebindings with an object. One of the properties of the object i'm using with TObjectBindSourceAdapter has an enumerated type, but the field in the adapter is never generated when i use an enumerated type in my object

我现在发现的唯一解决方案是在我的对象中将枚举类型定义为整数并进行类型转换.这似乎可以正常工作,但您必须避免从枚举的类型和整数中进行类型强制转换.

The Only solution i have found for now is to define the enumerated type as an integer in my object and typecast it. This seems to work fine but you have to keep type casting from and back the enumerated type and integers.

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

Here is some example code to explain what i mean.

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

First example which uses the enumerated type that i tried initially and does not seem to work:

 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;

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

Second example that seems to work by typecasting to integers

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;

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

I was wondering if someone else had come across this problem and if there is perhaps some other solution to solve this without reverting to integers and keep using the enumerated types. I'm also not sure if my workaround is the common way to do this or not.

推荐答案

我认为最好的方法是注册一个转换器.事实证明这很容易,但是只有在深入研究了VCL源代码之后才可以.我没有找到任何有用的文档.但是就在这里.

I believe the best way is to register a converter. It turns out to be very easy, but only after digging through the VCL source code. I didn't find any useful documentation. But here it is.

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()并传入:

In a nutshell, you call TValueRefConverterFactor.RegisterConversion() and pass in:

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

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

In the above code, the initialization section calls RegisterConverters, so all that is necessary is to include the unit in your project and the live bindings framework will use the converter whenever it needs to convert a TMyEnum value to a string.

这篇关于如何(正确)使用带有实时绑定的枚举类型(TObjectBindSourceAdapter)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆