How to create a combobox with two columns (one hidden) in Delphi 7?

前端 未结 2 1457
庸人自扰
庸人自扰 2021-01-02 18:56

How to create a TComboBox with two columns that has one of its columns hidden so that it can keep an id value along with the actual item in it? And then how to get

相关标签:
2条回答
  • 2021-01-02 19:39

    There's no need for two columns here.

    You can take advantage of the fact that TComboBox.Items (like many other things in Delphi, like TStringList, TMemo.Lines, and TListBox.Items) descends from TStrings, which has both the Strings and Objects properties. Objects stores anything the size of a TObject, which is a pointer.

    This means you can store your integer value by simply typecasting it to a TObject when adding it, and typecasting it back to an Integer when retrieving it.

    Something like this should work:

    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;
    

    To retrieve the value:

    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;
    

    Note that, since the Objects property is actually meant to store objects, this gives you a lot of flexibility. Here's an example (intentionally very trivial) of storing a customer's contact information in an associated object instance and displaying it in labels when an item from a listbox is selected.

    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.
    
    0 讨论(0)
  • 2021-01-02 19:48

    ComboBox controls do not support columns, and you do not need a hidden column anyway to accomplish what you need.

    The TComboBox.Items property is a TStrings descendant. It can hold both string values and associated user-defined data values together at the same time, but the user will only see the string values in the UI. Use the Items.AddObject() method to add string+ID values to the list, and then use the Items.Objects[] property to retrieve the ID values when needed.

    Alternatively, you could just store your ID values in a separate array that has the same number of elements as the ComboBox and then use the ComboBox item indexes to access the array values. This is especially important if you need to store a value of -1, because that particular value is not retrievable from the Objects[] property of a TComboBox due to the way the getter method is implemented, like Rob said.

    0 讨论(0)
提交回复
热议问题