我正在编写一个从TComboBox继承的组件。该组件具有通用方法,用于从私有字典中添加和检索值(可以是记录或类类型),并以键作为值的字符串表示形式的项目索引。
TGenericCombo = class (TComboBox)
private
FValues: TDictionary<integer, TValue>;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure AddValue<T>(const StringValue: string; Value: T); overload;
procedure AddValue<T>(Pair: TPair<T, string>); overload;
procedure AddValues<T>(StringFunction: TCalculateStringFunction<T>; Values: TList<T>); overload;
procedure AddValues<T>(Dictionary: TDictionary<T, string>); overload;
function GetCurrentValue<T>: T;
procedure SetCurrentValue<T>(Value: T);
end;
这是AddItem方法,当前将值存储为TValue,我也尝试过Variant。
procedure TGenericCombo.AddValue<T>(const StringValue: string; Value: T);
begin
Items.Add(StringValue);
FValues.Add(Items.Count - 1, TValue.From(Value));
end;
我遇到的问题是,当要在组合中设置所选值时,我正在将字典中的值强制转换为TObject以便与过去的值进行比较。这引发了“无效类型强制转换”运行时异常。 TRttiHelper.ObjectsAreEqual接受2个TObject作为参数。
procedure TGenericCombo.SetCurrentValue<T>(Value: T);
var
i: integer;
FFound: Boolean;
ListValue: TPair<integer, TValue>;
begin
for ListValue in FValues do
if TRttiHelper.ObjectsAreEqual(TValue.From(ListValue.Value).AsObject, TValue.From(Value).AsObject) then
begin
ItemIndex := ListValue.Key;
FFound := True;
Break
end;
if not FFound then
ItemIndex := -1;
end;
我确定应该将值存储为哪种类型,这些值又可以是记录类型或类,以使其正常工作。
编辑: 我认为添加几个用法示例会很有用。
TTestEnum =(teEnum1,teEnum2,teEnum3);
TTestObject = class
private
FStringProperty: string;
public
constructor Create(const StringProperty: string);
property StringProperty: string read FStringProperty write FStringProperty;
end;
TForm3 = class(TForm)
GenericCombo1: TGenericCombo;
GenericCombo2: TGenericCombo;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
procedure TForm3.Button1Click(Sender: TObject);
var
TestList: TObjectList<TTestObject>;
begin
TestList := TObjectList<TTestObject>.Create;
try
TestList.Add(TTestObject.Create('Object 1'));
TestList.Add(TTestObject.Create('Object 2'));
TestList.Add(TTestObject.Create('Object 3'));
GenericCombo1.AddValues<TTestList>(function(x: TTestObject): string begin Result := x.StringProperty end, TestObject);
finally
TestList.Free;
end;
end;
{ TTestObject }
constructor TTestObject.Create(const StringProperty: string);
begin
FStringProperty := StringProperty;
end;
procedure TForm3.Button2Click(Sender: TObject);
var
TestList: TDictionary<TTestEnum, string>;
begin
TestList := TDictionary<TTestEnum, string>.Create;
try
TestList.Add(teEnum1, 'Enum 1');
TestList.Add(teEnum2, 'Enum 2');
TestList.Add(teEnum3, 'Enum 3');
GenericCombo1.AddValues<TTestEnum>(TestList);
finally
TestList.Free;
end;
end;