Как создать combobox с двумя столбцами (один скрытый) в Delphi 7?

Как создать TComboBox С двумя столбцами, у которых один из столбцов скрыт, чтобы он мог сохранить значение id вместе с фактическим элементом в нем? И затем, как программно добраться до этого значения id?

2 ответов


здесь нет необходимости в двух столбцах.

вы можете воспользоваться тем, что TComboBox.Items (как и многие другие вещи в Делфи, как TStringList, TMemo.Lines и TListBox.Items) спускается от TStrings, которая имеет Strings и Objects свойства. Objects магазинах ничего размер TObject, который является указателем.

это означает, что вы можете сохранить целочисленное значение, просто набрав его в TObject при добавлении и типизации его обратно к целое при получении его.

что-то вроде этого должно работать:

procedure TForm1.FormCreate(Snder: TObject);
var
  i: Integer;
  sItem: String;
begin
  for i := 0 to 9 do
  begin
    sItem := Format('Item %d', [i]);
    ComboBox1.Items.AddObject(sItem, TObject(i));
  end;
end;

чтобы получить значение:

procedure TForm1.ComboBox1Click(Sender: TObject);
var
  Idx: Integer;
  Value: Integer;
begin
  Idx := ComboBox1.ItemIndex;
  if Idx <> -1 then
  begin
    Value := Integer(ComboBox1.Items.Objects[Idx]);
    // Do something with value you retrieved
  end;
end;

обратите внимание, что после объекты свойство на самом деле предназначено для хранения объекты, это дает вам большую гибкость. Вот пример (намеренно очень тривиальный) хранения контактной информации клиента в связанном экземпляре объекта и отображения ее в метках, когда элемент из списка выбирается.

unit Unit1;

interface

uses
  Windows, Messages, Variants, Classes, Graphics, Controls, 
  Forms, Dialogs, StdCtrls;

type
  TCustomer=class
  private
    FContact: string;
    FPhone: string;
  public
    constructor CreateCustomer(const AContact, APhone: string);
    property Contact: string read FContact write FContact;
    property Phone: string read FPhone write FPhone;
  end;

  TForm1 = class(TForm)
    ListBox1: TListBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    lblContact: TLabel;
    lblPhone: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ListBox1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TCustomer }

constructor TCustomer.CreateCustomer(const AContact, APhone: string);
begin
  inherited Create;
  FContact := AContact;
  FPhone := APhone;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  i: Integer;
begin
  for i := 0 to ListBox1.Items.Count - 1 do
    ListBox1.Items.Objects[i].Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  lblContact.Caption := '';
  lblPhone.Caption := '';

  // Create some customers. Of course in the real world you'd load this
  // from some persistent source instead of hard-coding them here.
  ListBox1.Items.AddObject('N Company', TCustomer.CreateCustomer('Nancy', '555-3333'));
  ListBox1.Items.AddObject('B Company', TCustomer.CreateCustomer('Brad', '555-1212'));
  ListBox1.Items.AddObject('A Company', TCustomer.CreateCustomer('Angie', '555-2345'));
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
  Cust: TCustomer;
begin
  if ListBox1.ItemIndex <> -1 then
  begin
    Cust := TCustomer(ListBox1.Items.Objects[ListBox1.ItemIndex]);
    lblContact.Caption := Cust.Contact;
    lblPhone.Caption := Cust.Phone;
  end;
end;

end.

элементы управления ComboBox не поддерживают столбцы, и вам не нужен скрытый столбец, чтобы выполнить то, что вам нужно.

на TComboBox.Items свойство TStrings потомок. Он может одновременно содержать как строковые значения, так и связанные пользовательские значения данных, но пользователь будет видеть только строковые значения в пользовательском интерфейсе. Используйте Items.AddObject() метод для добавления значений string+ID в список, а затем используйте Items.Objects[] свойство для извлечения значений ID, когда необходимый.

кроме того, вы можете просто сохранить свои значения ID в отдельном массиве, который имеет то же количество элементов, что и ComboBox, а затем использовать индексы элементов ComboBox для доступа к значениям массива. Это особенно важно, если вам нужно сохранить значение -1, потому что это конкретное значение не извлекается из Objects[] свойства TComboBox из-за того, как реализован метод геттера, как сказал Роб.