Delphi 使用变量/动态名称更改记录属性
我有一个简单的Delphi记录:Delphi 使用变量/动态名称更改记录属性,delphi,field,record,Delphi,Field,Record,我有一个简单的Delphi记录: type TCustomer = record name : string[30]; age : byte; end; 我知道我可以通过在代码中硬编码字段名来设置此记录的字段: var customer : TCustomer; begin // Set up our customer record customer.name := 'Fred Bloggs'; customer.age := 23;
type
TCustomer = record
name : string[30];
age : byte;
end;
我知道我可以通过在代码中硬编码字段名来设置此记录的字段:
var
customer : TCustomer;
begin
// Set up our customer record
customer.name := 'Fred Bloggs';
customer.age := 23;
end;
但我有一个TEdit,旁边有一个TComboBox,还有一个TButton。组合框是固定的,有两个项目,名称和年龄。它将首先设置为Name。用户在编辑框中键入其名称值。是一种保存类型的按钮,会有一个OnClick事件,如:
procedure TMainForm.SaveButtonClick(Sender: TObject);
begin
if(MyComboBox.Text = 'Name') then
begin
customer.name := MyEditBox.Text;
end
else
begin
customer.age := MyEditBox.Text;
end;
end;
该记录已在其他地方初始化。我在这里得到的是,在我的例子中,有101个可能的组合框项目。我应该用大量的case语句来处理这个问题,还是可以通过将重新排序的字段名与另一个控件(在本例中为组合框)设置的动态信息匹配来合并代码?屏幕上的组件是它们自己的变量。它们独立于您的记录而存在 您需要根据需要从一个复制到另一个 使用我的代码作为指导-它在语法上可能不完全正确
// UI component declarations within the form
TForm1 = class(TForm)
. . .
cbo : TComboBox;
edt : TEdit;
. . .
end;
. . .
var
Form1 : TForm1;
. . .
// to copy values from customer to UI components:
cbo.ItemIndex := customer.age; // assuming this is what the combobox is used for,
// and it starts at zero
edt := customer.name;
// to copy from UI components into customer, you'll need to do it inside of one
// of the event handlers.
TForm1.cboCloseUp( sender : TObject ); // the onCloseUp handler, when the combo drop-down closes
begin
customer.age := cbo.ItemIndex; // or StrToInt(cbo.Text)
end;
TForm1.edtChange( sender : TObject ); // the onChange handler whenever the edit changes
begin
customer.name := edt.Text;
end;
这就是要点。如果组合框中的年龄不是从零开始的,那么在复制客户记录和组合框时,您需要相应地调整偏移量。如果值是线性的,您可以设置ItemIndex+offset,或者只需将一个值写入cbo.Text。如果您的Delphi版本增强了RTTI Delphi 2010及更高版本,您可以这样做 然而,有几个陷阱: 1.必须将短字符串定义为类型,编译器才能为这些字段创建typeinfo,就像我对String30所做的那样 2.TValue是增强型RTTI中的类型,它不会像编辑中的字符串那样自动转换为年龄字段的整数。这就是为什么我选择了一个变量,并将其转换为字段的正确类型(仅适用于ShortString和Integer),其余部分留给读者作为练习 3.TValue不喜欢不同短字符串类型的转换String30与短字符串不同,这就是我使用TValue.Make的原因。缺少的是检查所提供的值是否与类型匹配,比如超过30个字符。当然,它也不兼容unicode
uses
Rtti,
TypInfo;
type
String30 = string[30];
TCustomer = record
name: String30;
age: byte;
end;
var
c: TCustomer;
function CastFromVariant(ATypeInfo: PTypeInfo; const AValue: Variant): TValue;
var
asShort: ShortString;
begin
case ATypeInfo.Kind of
tkInteger: Result := TValue.From<Integer>(AValue);
tkString:
begin
asShort := AValue;
TValue.Make(@asShort, ATypeInfo, Result);
end;
end;
end;
procedure TForm5.Button1Click(Sender: TObject);
var
ctx: TRttiContext;
t: TRttiType;
f: TRttiField;
v: TValue;
begin
t := ctx.GetType(TypeInfo(TCustomer));
f := t.GetField(ComboBox1.Text);
v := CastFromVariant(f.FieldType.Handle, Edit1.Text);
f.SetValue(@c, v);
end;
procedure TForm5.ComboBox1Change(Sender: TObject);
var
ctx: TRttiContext;
t: TRttiType;
f: TRttiField;
v: TValue;
begin
t := ctx.GetType(TypeInfo(TCustomer));
f := t.GetField(ComboBox1.Text);
v := f.GetValue(@c);
Edit1.Text := v.ToString;
end;
你把那行代码放在哪里了?还有,可能是你可以使用RTTI的一个副本,但可能不能使用上个世纪的那些短字符串。说真的,这些短字符串是怎么回事?这个例子来自这里,这是一个DelphiBasics给你的示例代码,应该埋在100英尺深的地下,因为它大约属于1984年。2014年,我们使用类和泛型,在记录中不使用短字符串[30]。根据使用方式的不同,在需要记录数据时从UI复制回记录可能更好,而不是每次UI更改时。当然,根据使用方式的不同,会有很多变化,OP没有解释。。。这只是一个例子。我认为OP缺少的是UI组件有自己的存储,独立于他的记录提供的内容。有些用户界面框架需要提供变量,用户界面组件实际上在这些变量中存储值——Delphi不这么做。我想你误解了这个问题。他想在TComboBox中选择他想在TEdit中编辑的记录中的哪个字段。自从我发布了我的答案后,OP似乎改变了问题。@Stefan的评论对问题的所有修订都同样有效