Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 使用变量/动态名称更改记录属性_Delphi_Field_Record - Fatal编程技术网

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;

我有一个简单的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;
 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的评论对问题的所有修订都同样有效