如何(正确)使用带有实时绑定的枚举类型(TObjectBindSourceAdapter) [英] how to (correctly) use an enumerated type with livebindings (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屋!