Ale*_*lex 3 vb.net combobox autocomplete contains winforms
我想让我的ComboBox项目建议并在其中包含某些内容时附加其项目,而不仅仅是通过StartsWith函数.
我的ComboBox绑定到一个DataView,它包含长连接中的客户端[ CompanyName ],[ Address ],[ City ].
我希望我的用户能够在城市中输入并仍然找到与上述所有字段匹配的记录.我知道Infragistics可以实现这一点,但我没有这个包.
搜索词:" Sher "
这可能在VB.Net中还是我应该搜索其他内容?
小智 7
我做了一些研究,发现了以下问题:
在那个问题中,他们回答了另一个问题:
让我们引用该问题的最佳答案
现有的自动完成功能仅支持按前缀搜索.似乎没有任何体面的方式来覆盖行为.
有些人通过覆盖
OnTextChanged事件来实现自己的自动完成功能.这可能是你最好的选择.例如,您可以在其
ListBox下方添加一个TextBox,并将其默认可见性设置为false.然后您可以使用OnTextChanged事件TextBox和SelectedIndexChanged事件ListBox来显示和选择项目.这似乎是一个很好的例子:
Run Code Online (Sandbox Code Playgroud)public Form1() { InitializeComponent(); acsc = new AutoCompleteStringCollection(); textBox1.AutoCompleteCustomSource = acsc; textBox1.AutoCompleteMode = AutoCompleteMode.None; textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource; } private void button1_Click(object sender, EventArgs e) { acsc.Add("[001] some kind of item"); acsc.Add("[002] some other item"); acsc.Add("[003] an orange"); acsc.Add("[004] i like pickles"); } void textBox1_TextChanged(object sender, System.EventArgs e) { listBox1.Items.Clear(); if (textBox1.Text.Length == 0) { hideResults(); return; } foreach (String s in textBox1.AutoCompleteCustomSource) { if (s.Contains(textBox1.Text)) { Console.WriteLine("Found text in: " + s); listBox1.Items.Add(s); listBox1.Visible = true; } } } void listBox1_SelectedIndexChanged(object sender, System.EventArgs e) { textBox1.Text = listBox1.Items[listBox1.SelectedIndex].ToString(); hideResults(); } void listBox1_LostFocus(object sender, System.EventArgs e) { hideResults(); } void hideResults() { listBox1.Visible = false; }如果没有太多的努力,你可以做更多的事情:将文本附加到文本框,捕获其他键盘命令,等等.
改进了 BenD 在他的回答中展示的技术,以便让机制更优雅地处理某些角落:
public sealed class CCComboboxAutocomplete : ComboBox
{
public CCComboboxAutocomplete()
{
AutoCompleteMode = AutoCompleteMode.Suggest; //crucial otherwise exceptions occur when the user types in text which is not found in the autocompletion list
}
protected override void OnTextChanged(EventArgs e)
{
try
{
if (DesignMode || !string.IsNullOrEmpty(Text) || !Visible) return;
ResetCompletionList();
}
finally
{
base.OnTextChanged(e);
}
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
try
{
if (DesignMode) return;
if (e.KeyChar == '\r' || e.KeyChar == '\n')
{
e.Handled = true;
if (SelectedIndex == -1 && Items.Count > 0 && Items[0].ToString().ToLowerInvariant().StartsWith(Text.ToLowerInvariant()))
{
Text = Items[0].ToString();
}
DroppedDown = false;
return; //0
}
BeginInvoke(new Action(ReevaluateCompletionList)); //1
}
finally
{
base.OnKeyPress(e);
}
}
//0 Guardclose when detecting any enter keypresses to avoid a glitch which was selecting an item by means of down arrow key followed by enter to wipe out the text within
//1 Its crucial that we use begininvoke because we need the changes to sink into the textfield Omitting begininvoke would cause the searchterm to lag behind by one character That is the last character that got typed in
private void ResetCompletionList()
{
_previousSearchterm = null;
try
{
SuspendLayout();
var originalList = (object[])Tag;
if (originalList == null)
{
Tag = originalList = Items.Cast<object>().ToArray();
}
if (Items.Count == originalList.Length) return;
while (Items.Count > 0)
{
Items.RemoveAt(0);
}
Items.AddRange(originalList);
}
finally
{
ResumeLayout(performLayout: true);
}
}
private string _previousSearchterm;
private void ReevaluateCompletionList()
{
var currentSearchterm = Text.ToLowerInvariant();
if (currentSearchterm == _previousSearchterm) return; //optimization
_previousSearchterm = currentSearchterm;
try
{
SuspendLayout();
var originalList = (object[])Tag;
if (originalList == null)
{
Tag = originalList = Items.Cast<object>().ToArray(); //0
}
var newList = (object[])null;
if (string.IsNullOrEmpty(currentSearchterm))
{
if (Items.Count == originalList.Length) return;
newList = originalList;
}
else
{
newList = originalList.Where(x => x.ToString().ToLowerInvariant().Contains(currentSearchterm)).ToArray();
}
try
{
while (Items.Count > 0) //1
{
Items.RemoveAt(0);
}
}
catch
{
try
{
Items.Clear();
}
catch
{
}
}
Items.AddRange(newList.ToArray()); //2
}
finally
{
if (currentSearchterm.Length >= 2 && !DroppedDown)
{
DroppedDown = true; //3
Cursor.Current = Cursors.Default; //4
Text = currentSearchterm; //5
Select(currentSearchterm.Length, 0);
}
ResumeLayout(performLayout: true);
}
}
//0 backup original list
//1 clear list by loop through it otherwise the cursor would move to the beginning of the textbox
//2 reset list
//3 if the current searchterm is empty we leave the dropdown list to whatever state it already had
//4 workaround for the fact the cursor disappears due to droppeddown=true This is a known bu.g plaguing combobox which microsoft denies to fix for years now
//5 Another workaround for a glitch which causes all text to be selected when there is a matching entry which starts with the exact text being typed in
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10674 次 |
| 最近记录: |