如何使用全文搜索自动填充支持组合框? [英] How to make a combo box with fulltext search autocomplete support?
问题描述
我希望用户能够从 TComboBox
项目中输入第二个或第三个单词,并且该项目将显示在 AutoSuggest
下拉式选项
I would like a user to be able to type in the second or third word from a TComboBox
item and for that item to appear in the AutoSuggest
dropdown options
例如,组合框包含以下项目:
For example, a combo box contains the items:
- 约翰布朗先生
- 阿曼达·布朗夫人
- Brian Jones先生
- Samantha Smith
- Mr John Brown
- Mrs Amanda Brown
- Mr Brian Jones
- Mrs Samantha Smith
当用户键入Br时,下拉列表显示:
When the user types "Br" the dropdown displays:
- 约翰·布朗先生
- 阿曼达·布朗夫人
- 布赖恩·琼斯先生
当用户键入Jo时,下拉菜单显示:
and when the user types "Jo" the dropdown displays:
- John Brown先生
- Brian Jones先生
问题是, AutoSuggest
功能仅包括下拉列表中的项目,从用户输入的内容开始,因此在上述示例中,下拉菜单中不会出现任何内容。
The problem is that the AutoSuggest
functionality only includes items in the dropdown list that begin with what the user has input and so in the examples above nothing will appear in the dropdown.
可以使用 IAutoComplete
接口和/或其他相关的界面来解决这个问题吗? p>
Is it possible to use the IAutoComplete
interface and/or other related interfaces to get around this issue?
推荐答案
以下示例使用插入的 TComboBox
组件。与原始类的主要区别在于,这些项目存储在单独的 StoredItems
属性中,而不是
项目
通常(由于简单而使用) br>
The following example uses the interposed class of the TComboBox
component. The main difference from the original class is that the items are stored in the separate StoredItems
property instead of
the Items
as usually (used because of simplicity).
StoredItems com / Libraries / en / System.Classes.TStringList.OnChangerel =noreferrer> OnChange
事件,每当您更改它们(例如添加或从这个字符串列表中删除),即使当组合
列表被删除时,当前的过滤器也会反映出来。
The StoredItems
are being watched by the OnChange
event and whenever you change them (for instance by adding or deleting from this string list), the current filter will reflect it even when the combo
list is dropped down.
这里的要点是抓住 WM_COMMAND
消息通知 CBN_EDITUPDATE
。当它到达时,您只需搜索 StoredItems
列表中您在组合编辑中键入的内容,然后填写 项目
属性与匹配。
The main point here is to catch the WM_COMMAND
message notification CBN_EDITUPDATE
which is being sent whenever the combo edit text is changed but not rendered yet. When it arrives, you just search through the StoredItems
list for what you have typed in your combo edit and fill the Items
property with matches.
对于文本搜索, ContainsText
,所以搜索不区分大小写。忘记了,
自动完成
功能必须关闭,因为它有自己的,不客气的逻辑,为此目的。
For text searching is used the ContainsText
so the search is case insensitive. Forgot to mention,
the AutoComplete
feature has to be turned off because it has its own, unwelcomed, logic for this purpose.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, StrUtils, ExtCtrls;
type
TComboBox = class(StdCtrls.TComboBox)
private
FStoredItems: TStringList;
procedure FilterItems;
procedure StoredItemsChange(Sender: TObject);
procedure SetStoredItems(const Value: TStringList);
procedure CNCommand(var AMessage: TWMCommand); message CN_COMMAND;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property StoredItems: TStringList read FStoredItems write SetStoredItems;
end;
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
constructor TComboBox.Create(AOwner: TComponent);
begin
inherited;
AutoComplete := False;
FStoredItems := TStringList.Create;
FStoredItems.OnChange := StoredItemsChange;
end;
destructor TComboBox.Destroy;
begin
FStoredItems.Free;
inherited;
end;
procedure TComboBox.CNCommand(var AMessage: TWMCommand);
begin
// we have to process everything from our ancestor
inherited;
// if we received the CBN_EDITUPDATE notification
if AMessage.NotifyCode = CBN_EDITUPDATE then
// fill the items with the matches
FilterItems;
end;
procedure TComboBox.FilterItems;
var
I: Integer;
Selection: TSelection;
begin
// store the current combo edit selection
SendMessage(Handle, CB_GETEDITSEL, WPARAM(@Selection.StartPos),
LPARAM(@Selection.EndPos));
// begin with the items update
Items.BeginUpdate;
try
// if the combo edit is not empty, then clear the items
// and search through the FStoredItems
if Text <> '' then
begin
// clear all items
Items.Clear;
// iterate through all of them
for I := 0 to FStoredItems.Count - 1 do
// check if the current one contains the text in edit
if ContainsText(FStoredItems[I], Text) then
// and if so, then add it to the items
Items.Add(FStoredItems[I]);
end
// else the combo edit is empty
else
// so then we'll use all what we have in the FStoredItems
Items.Assign(FStoredItems)
finally
// finish the items update
Items.EndUpdate;
end;
// and restore the last combo edit selection
SendMessage(Handle, CB_SETEDITSEL, 0, MakeLParam(Selection.StartPos,
Selection.EndPos));
end;
procedure TComboBox.StoredItemsChange(Sender: TObject);
begin
if Assigned(FStoredItems) then
FilterItems;
end;
procedure TComboBox.SetStoredItems(const Value: TStringList);
begin
if Assigned(FStoredItems) then
FStoredItems.Assign(Value)
else
FStoredItems := Value;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
ComboBox: TComboBox;
begin
// here's one combo created dynamically
ComboBox := TComboBox.Create(Self);
ComboBox.Parent := Self;
ComboBox.Left := 10;
ComboBox.Top := 10;
ComboBox.Text := 'Br';
// here's how to fill the StoredItems
ComboBox.StoredItems.BeginUpdate;
try
ComboBox.StoredItems.Add('Mr John Brown');
ComboBox.StoredItems.Add('Mrs Amanda Brown');
ComboBox.StoredItems.Add('Mr Brian Jones');
ComboBox.StoredItems.Add('Mrs Samantha Smith');
finally
ComboBox.StoredItems.EndUpdate;
end;
// and here's how to assign the Items of the combo box from the form
// to the StoredItems; note that if you'll use this, you have to do
// it before you type something into the combo's edit, because typing
// may filter the Items, so they would get modified
ComboBox1.StoredItems.Assign(ComboBox1.Items);
end;
end.
这篇关于如何使用全文搜索自动填充支持组合框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!