需要一个带过滤的ComboBox [英] Need a ComboBox with filtering

查看:130
本文介绍了需要一个带过滤的ComboBox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些类型的ComboBox,它可以从DB加载它的项目。虽然我在其中键入一些文本,它应该过滤它的列表,只留下那些项目,有我的文字在某处(开始,中间...)。不是所有的DataSet都有过滤功能,所以不可能使用它们。有任何准备好使用具有这样的能力的组件吗?我试图在JVCL中搜索,但没有运气。

I need some type of ComboBox which can load it's items from DB. While I type some text in to it, it should filter it's list, leaving only those items, that have my text somewhere (at the beginning, middle...). Not all my DataSet's have filtering capabilities, so it is not possible to use them. Is there any ready to use components with such abilities? I have tried to search in JVCL, but without luck.

推荐答案

您可以尝试定制自定义ComboBox的自动完成功能。从DB加载项目很容易:

You could try customizing the autocomplete functionality of a regular ComboBox. Loading its items from a DB is easy:

    ComboBox1.Items.Clear;   
    while not Table1.Eof do begin
      ComboBox1.Items.AddObject( Table1.FieldByName('Company').AsString,  
       TObject(Table1.FieldByName('CustNo').AsInteger) );
      Table1.Next;   
    end;

对于中间词匹配的自动完成,您可以尝试调整此代码。通过将AutoComplete设置为true来启用在项目中文本开头匹配的功能,并且需要在尝试编写自动完成的OnChange事件处理程序之前关闭该功能。我建议你可以更安全地在回车键上进行匹配和选择,因为尝试在飞行中做它使事情很毛茸茸,因为下面的代码会显示你:

As far as the auto-complete for middle-of-word matching, you might try adapting this code. The functionality that matches at the beginning of the text in the Items is enabled by setting AutoComplete to true, and needs to be turned off before you try writing your own OnChange event handler that does auto-complete. I suggest that you could more safely do the match and selection on the enter key, because attempting to do it on the fly makes things quite hairy, as the code below will show you:

这是我的基本版本:使用onKeyDown和onChange事件的常规组合框,并将AutoComplete设置为false,使用上述代码填充它和这两个事件

Here's my basic version: Use a regular combobox with onKeyDown, and onChange events, and AutoComplete set to false, use above code to populate it, and these two events

procedure TForm2.ComboBox1Change(Sender: TObject);
var
  SearchStr,FullStr: string;
  i,retVal,FoundIndex: integer;
  ctrl:TComboBox;
begin
  if fLastKey=VK_BACK then
       exit;

  // copy search pattern
  ctrl := (Sender as TCombobox);
  SearchStr := UpperCase(ctrl.Text);
  FoundIndex := -1;
  if SearchStr<>'' then
  for i := 0 to ctrl.Items.Count-1 do begin
    if Pos(SearchStr, UpperCase(ctrl.Items[i]))>0 then
    begin
       FoundIndex := i;
       fsearchkeys := ctrl.Text;
       break;
    end;
  end;

  if (FoundIndex>=0) then
  begin
    retVal := ctrl.Perform(CB_SELECTSTRING, 0, LongInt(PChar(ctrl.Items[FoundIndex]))) ;

    if retVal > CB_Err then
    begin
      ctrl.ItemIndex := retVal;
      ctrl.SelStart := Pos(SearchStr,UpperCase(ctrl.Text))+Length(SearchStr)-1;
      ctrl.SelLength := (Length(ctrl.Text) - Length(SearchStr));
    end; // retVal > CB_Err

  end; // lastKey <> VK_BACK

end;

procedure TForm2.ComboBox1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  fLastKey := Key;
end;

假设列表的内容是David Smith和Mark Smithers。你输入S,它匹配的姓氏的第一个字母,在David Smith。现在它显示了David Smith的David S部分未选择,并选择了mith部分(以便您键入的下一个字符将替换自动完成部分,一种标准自动完成技术)。请注意,上面的代码必须在您输入的S前面加上您没有键入的David部分。如果你比我更聪明,你可以找到一种方法记住用户键入s,然后,可能是一个m,其次是一些更多的字母,最后键入Smithe,匹配史密斯,而不是总是大卫史密斯。另请注意,您只能设置SelStart和SelLength来选择字符串的连续长度。

Suppose the contents of the list are "David Smith", and "Mark Smithers". You type S and it matches the first letter of the last name, in David Smith. Now it shows David Smith with the "David S" part not selected, and the "mith" part selected (so that the next characters you type will replace the auto completed portion, a standard auto-complete technique). Note that the above code has had to prefix the S you typed with the "David " part you didn't type. If you are a lot more clever than me, you can find a way to remember that the user typed "s" and then, maybe an "m", followed by some more letters, and eventually having typed "Smithe", match Smithers, instead of always David smith. Also note that you can only set the SelStart and SelLength to select a continuous length of a string.

我提供的代码只有在项目列表从不包含任何重复的子字符串。有很好的理由为什么Windows Common Control组合框自动完成功能只能使用前缀匹配,而不是中间字符串匹配。

The code I have provided will only work when the list of items never contains any repeated substrings. There are good reasons why the Windows Common Control combobox "autocomplete" functionality only works with prefix matching, and not mid-string matching.

由于任何将实现中间字符串匹配应该可以绘制您在未选择的部分中输入的部分,并且由于未选择的部分将在中间字符串中,因此您可能需要从头开始编写自己的控件,而不依赖于TComboBox基本代码及其底层MS Common控制组合框功能。

Since anything that would implement mid-string matching should probably draw the part you typed in not-selected, and since that not-selected part would be in mid-string, you would probably need to write your own control from scratch and not rely on the TComboBox base code, and its underlying MS Common Controls combobox functionality.

这篇关于需要一个带过滤的ComboBox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆