如何根据键入的内容过滤组合框的内容?

时间:2011-07-12 15:45:00

标签: delphi autocomplete combobox

我们有一个包含100多个项目的组合框。

我们想要在组合框中输入字符时过滤掉项目。例如,如果我们输入'ac'并单击下拉选项,那么我们希望它显示仅以'ac'开头的项目。

我该怎么做?

5 个答案:

答案 0 :(得分:9)

也许你会更乐意使用操作系统内置的自动完成功能。我先前在这里给了an outline of how to do that。创建一个IAutoComplete对象,将其连接到组合框的列表并编辑控件,操作系统将在用户键入时自动显示潜在匹配的下拉列表。您不需要自己调整组合框的列表。

答案 1 :(得分:4)

为了扩展Rob关于使用OnChange事件的答案,这里有一个如何做他建议的例子。

procedure TForm1.FormCreate(Sender: TObject);
begin
  FComboStrings := TStringList.Create;
  FComboStrings.Add('Altair');
  FComboStrings.Add('Alhambra');
  FComboStrings.Add('Sinclair');
  FComboStrings.Add('Sirius');
  FComboStrings.Add('Bernard');
  FComboStrings.Sorted := True;
  ComboBox1.AutoComplete := False;
  ComboBox1.Items.Text := FComboStrings.Text;
  ComboBox1.Sorted := True;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FComboStrings);
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
var
  Filter: string;
  i: Integer;
  idx: Integer;
begin
  // Dropping down the list puts the text of the first item in the edit, this restores it
  Filter := ComboBox1.Text;
  ComboBox1.DroppedDown := True;
  ComboBox1.Text := Filter;
  ComboBox1.SelStart := Length(Filter);

  for i := 0 to FComboStrings.Count - 1 do
    if SameText(LeftStr(FComboStrings[i], Length(ComboBox1.Text)), ComboBox1.Text) then
    begin
      if ComboBox1.Items.IndexOf(FComboStrings[i]) < 0 then
        ComboBox1.Items.Add(FComboStrings[i]);
    end
    else
    begin
      idx := ComboBox1.Items.IndexOf(FComboStrings[i]);
      if idx >= 0 then
        ComboBox1.Items.Delete(idx);
    end;
end;

答案 2 :(得分:2)

我使用组合框中的对象做了简短的贡献:

procedure FilterComboBox(Combo: TComboBox; DefaultItems: TStrings);

  function Origin: TStrings;
  begin
    if Combo.Tag = 0 then
    begin
      Combo.Sorted := True;
      Result := TStrings.Create;
      Result := Combo.Items;
      Combo.Tag := Integer(Result);
    end
    else
      Result := TStrings(Combo.Tag);
  end;

var
  Filter: TStrings;
  I: Integer;
  iSelIni: Integer;
begin
  if(Combo.Text <> EmptyStr) then
  begin
    iSelIni:= Length(Combo.Text);
    Filter := TStringList.Create;
    try
      for I := 0 to Origin.Count - 1 do
        if AnsiContainsText(Origin[I], Combo.Text) then
          Filter.AddObject(Origin[I], TObject(Origin.Objects[I]));

        Combo.Items.Assign(Filter);
        Combo.DroppedDown:= True;
        Combo.SelStart := iSelIni;
        Combo.SelLength := Length(Combo.Text);
    finally
      Filter.Free;
    end;
  end
  else
    Combo.Items.Assign(DefaultItems);
end;

答案 3 :(得分:1)

您可以处理组合框的OnChange事件。保留与UI控件分开的所有项目的主列表,并且每当组合框的编辑控件更改时,相应地调整组合框的列表。删除与当前文本不匹配的项目,或者从先前删除的主列表中重新添加项目。

答案 4 :(得分:1)

正如Rob已经回答的那样,您可以对OnChange事件进行过滤,请参阅以下代码示例。它适用于多个ComboBox。

{uses}
  Contnrs, StrUtils;

type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    ComboBox2: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure ComboBoxChange(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FComboLists: TList;
    procedure FilterComboBox(Combo: TComboBox);
  end;

implementation

{$R *.dfm}

procedure TForm1.ComboBoxChange(Sender: TObject);
begin
  if Sender is TComboBox then
    FilterComboBox(TComboBox(Sender));
end;

procedure TForm1.FilterComboBox(Combo: TComboBox);

  function Origin: TStrings;
  begin
    if Combo.Tag = 0 then
    begin
      Combo.Sorted := True;
      Result := TStringList.Create;
      Result.Assign(Combo.Items);
      FComboLists.Add(Result);
      Combo.Tag := Integer(Result);
    end
    else
      Result := TStrings(Combo.Tag);
  end;

var
  Filter: TStrings;
  I: Integer;
begin
  Filter := TStringList.Create;
  try
    for I := 0 to Origin.Count - 1 do
      if AnsiStartsText(Combo.Text, Origin[I]) then
        Filter.Add(Origin[I]);
    Combo.Items.Assign(Filter);
    Combo.SelStart := Length(Combo.Text);
  finally
    Filter.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FComboLists := TObjectList.Create(True);
  // For Each ComboBox, set AutoComplete at design time to false:
  ComboBox1.AutoComplete := False;
  ComboBox2.AutoComplete := False;
end;

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