ComboBox中的名称值对

Jam*_*ass 17 delphi combobox

我确信这一定是一个常见的问题,但我似乎无法找到一个简单的解决方案......

我想使用名称值对的组合框控件作为项目.ComboBox将TStrings作为其项目,因此应该没问题.

不幸的是,组合框上的绘图方法绘制了Items [i],因此您可以在框中获得Name = Value.

我希望隐藏的值,所以我可以使用代码中的值,但用户会看到名称.

有任何想法吗?

And*_*and 14

设置StylecsOwnerDrawFixed

procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
begin
  ComboBox1.Canvas.TextRect(Rect, Rect.Left, Rect.Top, ComboBox1.Items.Names[Index]);
end;
Run Code Online (Sandbox Code Playgroud)


Mar*_*ema 11

如果值是整数:拆分名称值对,将名称存储在组合框的字符串中以及相应对象中的值.

  for i := 0 to List.Count - 1 do
    ComboBox.AddItem(List.Names[i], TObject(StrToInt(List.ValueFromIndex[i], 0)));
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以继续以通用方式使用控件,并且仍然可以通过以下方式获得值:

Value := Integer(ComboBox.Items.Objects[ComboBox.ItemIndex]);
Run Code Online (Sandbox Code Playgroud)

此方法也可用于其他对象的列表.例如,包含TPerson对象实例的TObjectList:

var
  i: Integer;
  PersonList: TObjectList;
begin
  for i := 0 to PersonList.Count - 1 do
    ComboBox.AddItem(TPerson(PersonList[i]).Name, PersonList[i]);
Run Code Online (Sandbox Code Playgroud)

并通过以下方式检索所选项目的相应TPerson:

Person := TPerson(ComboBox.Items.Objects[ComboBox.ItemIndex]);
Run Code Online (Sandbox Code Playgroud)

更新

一种更好的方式 - 以及一个不依赖于为整数的值 - 是预先处理列表,在一个简单的类包装的值和添加实例它们到列表的对象.

简单 - 基于RTTI的扩展 - 包装类:

type
  TValueObject = class(TObject)
  strict private
    FValue: TValue;
  public
    constructor Create(const aValue: TValue);
    property Value: TValue read FValue;
  end;

  { TValueObject }

constructor TValueObject.Create(const aValue: TValue);
begin
  FValue := aValue;
end;
Run Code Online (Sandbox Code Playgroud)

如果您使用的是D1010之前版本的Delphi,只需使用string而不是TValue.

预处理列表:

// Convert the contents so both the ComboBox and Memo can show just the names
// and the values are still associated with their items using actual object
// instances.
for idx := 0 to List.Count - 1 do
begin
  List.Objects[idx] := 
    TValueObject.Create(List.ValueFromIndex[idx]);

  List.Strings[idx] := List.Names[idx];
end;
Run Code Online (Sandbox Code Playgroud)

将列表加载到Combo现在是一个简单的任务:

// Load the "configuration" contents of the string list into the combo box
ComboBox.Items := List; // Does an Assign!
Run Code Online (Sandbox Code Playgroud)

请记住,在内部执行分配,因此在释放List之前,最好确保组合不再能够访问其列表对象的实例.

从列表中获取名称和值:

begin
  Name_Text.Caption := List.Items[idx];
  Value_Text.Caption := TValueObject(List.Objects[idx]).Value.AsString;
end;
Run Code Online (Sandbox Code Playgroud)

或者来自ComboBox:

begin
  Name_Text.Caption := ComboBox.Items[idx];
  Value_Text.Caption := TValueObject(ComboBox1.Items.Objects[idx]).Value.AsString;
end;
Run Code Online (Sandbox Code Playgroud)

可以在我的博客上找到相同的信息以及更全面的解释:TL; ComboBoxes和Kinfolk中的名称值对的DR版本