我使用TObjectBindSourceAdapter
与对象一起使用livebindings。
与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;
我想知道是否有其他人遇到过这个问题,是否有其他解决方案可以解决这个问题,而不需要恢复整数并继续使用枚举类型。我也不确定我的解决方法是否是常见的方法。
答案 0 :(得分:2)
我认为最好的方法是注册转换器。事实证明这很简单,但只有在深入了解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()
并传入:
在上面的代码中,initialization
部分调用了RegisterConverters
,因此所有必要的是将单元包含在项目中,并且实时绑定框架将在需要转换时使用转换器TMyEnum
的{{1}}值。
答案 1 :(得分:0)
将枚举作为整数和背面进行转换实际上是适合这种情况的适当方法。比方说吧......
type
TMyEnum = (meOne, meTwo, meThree);
正如您已经演示的那样,这些可以作为整数进行转换。当作为整数进行转换时,它使用索引,其中每个索引都在定义中列出。所以......
0 = meOne
1 = meTwo
2 = meThree
您可以将TMyEnum
转换为Integer
,如...
Something := Integer(MyEnumValue);
然后把它丢回......
Something := TMyEnum(MyIntegerValue);
这被广泛用于解决您的确切问题,我自己一直使用它。我很久以前就研究了同样的场景,并得出结论,这是实现这一目的的唯一方法 - 除非你想做一些更复杂的转换,比如使用字符串......
function MyEnumToStr(const MyEnum: TMyEnum): String;
begin
case MyEnum of
meOne: Result:= 'meOne';
meTwo: Result:= 'meTwo';
meThree: Result:= 'meThree';
end;
end;
function StrToMyEnum(const Str: String): TMyEnum;
var
S: String;
begin
S:= UpperCase(Str);
if S = 'MEONE' then Result:= meOne
else if S = 'METWO' then Result:= meTwo
else if S = 'METHREE' then Result:= meThree;
end;
(我确信还有其他方法可以if
使用StrToMyEnum
语句
以这种方式使用字符串可以使事情更具可读性。一个更现实世界的例子......
type
TCustomerType = (cmRetail, cmWholesale, cmDesigner);
其中...
cmRetail = 'Retail Customer'
cmWholesale = 'Wholesale Customer'
cmDesigner = 'Designer Customer'