Calling TEdit objects based on DB query

血红的双手。 提交于 2019-12-24 04:49:04

问题


I have a form with 7 TEdit having name EditPhone1, EditPhone2 and so on. In the same form I query a DB to get data to fill those TEdits. Of course I cannot know in advance how many results the query will return. How can I call the various TEdit objects when looping on the rowcount of the query?


回答1:


Use FindComponent to "convert" a component name to the component itself:

var
  Edit: TEdit;
  I: Integer;
begin
  DataSet.First;
  I := 1;
  while not DataSet.Eof do
  begin
    Edit := TEdit(FindComponent(Format('EditPhone%d', [I])));
    if Edit <> nil then
      Edit.Text := DataSet.FieldValues['PhoneNo'];
    DataSet.Next;
    Inc(I);
  end;

Now, this requires to hard-code the EditPhone%d string into the source which results in all kinds of maintainability issues. For example: consider renaming the edits.

Alternative 1:

To not rely on the component names, you could instead make use of TLama's idea and add all the edits to a list:

uses
  ... , Generics.Collections;

type
  TForm1 = class(TForm)
    EditPhone1: TEdit;
    ...
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FEdits: TList<TEdit>;
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FEdits := TList<TEdit>.Create;
  FEdits.AddRange([EditPhone1, EditPhone2, EditPhone3, EditPhone4, EditPhone5,
    EditPhone6, EditPhone7]);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FEdits.Free;
end;

procedure TForm1.ADOQuery1AfterOpen(DataSet: TDataSet);
var
  I: Integer;
begin
  DataSet.First;
  I := 0;
  while (not DataSet.Eof) and (I < FEdits.Count) do
  begin
    FEdits[I].Text := DataSet.FieldValues['PhoneNo'];
    DataSet.Next;
    Inc(I);
  end;
end;

This still requires some maintenance in case of adding edits in future.

Alternative 2:

You could also loop over all edits in the form to find the ones tagged to be added to the list, instead of adding them each explicitly:

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  FEdits := TList<TEdit>.Create;
  for I := 0 to ComponentCount - 1 do
    if (Components[I] is TEdit) and (TEdit(Components[I]).Tag = 1) then
      FEdits.Add(TEdit(Components[I]));
end;

But keeping those tags up to date is another burden.

Alternative 3:

I suggest you use a TDBGrid which is a data-component. Opening the linked dataset will automatically add all phone numbers to the grid. With some settings, the grid may kind of look like a couple of edits below each other.




回答2:


You can, for example, use Tag property, to find needed component. Set all you TEdit's tag from 1 to 7 (or more), and find component by:

Var I: Integer;
    MyEdit : TEdit;

For I = 0 To Self.ComponentCount - 1 Do
 if (Self.Components[I] IS TEdit) AND (Self.Components[I] AS TEdit).Tag = YourTag
   MyEdit = (Self.Components[I] AS TEdit);

You can also dynamically create so many TEdits, you need, and assign Tag property on creation, and find it this code later in runtime.




回答3:


I'd suggest using DBCtrlGrid. You place your controls for one row on it, and it repeats the controls for as many rows as your data set has.




回答4:


  1. Get query result (usually using .RowCount property of TDataset return)
  2. After getting the number of row, do iteration to make TEdit and set the text property

Here is sample of code:

...
For i:=0 to RowCount do
Begin
 A:=TEdit.Create(self);
 A.Parent:=AForm;
 A.Top:=i*14;
 A.Text:=ADataset.Field(i).AsString;
End;
...


来源:https://stackoverflow.com/questions/12815962/calling-tedit-objects-based-on-db-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!