我想让我的ComboBox项目建议并在其中包含某些内容时附加其项目,而不仅仅是通过StartsWith函数。
我的ComboBox绑定到DataView,其中包含长连接中的客户端[ CompanyName ],[地址],[城市]。
我希望我的用户能够输入城市并仍然找到与上述所有字段匹配的记录。我知道这可以通过Infragistics实现,但我没有这个包。
搜索字词:" Sher "
这可能在VB.Net中使用,还是应该搜索其他内容?
答案 0 :(得分:6)
我做了一些研究,发现了以下问题:
Override Winforms ComboBox Autocomplete Suggest Rule
在那个问题中,他们回答了另一个问题:
让我们引用该问题的最佳答案
现有的自动完成功能仅支持搜索 字首。似乎没有任何体面的方式可以覆盖 行为。
有些人已经实现了自己的自动完成功能 覆盖
OnTextChanged
事件。这可能是你最好的选择。例如,您可以在
ListBox
下方添加TextBox
并进行设置 其默认可见性为false。然后你可以使用OnTextChanged
事件的TextBox
和SelectedIndexChanged
事件ListBox
显示和选择项目。这似乎是一个很好的例子:
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; }
如果没有太多努力,你可以做更多的事情:追加文字 到文本框,捕获其他键盘命令,等等。
答案 1 :(得分:4)
改进了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
}
答案 2 :(得分:-3)
ComboBox
,TextBox
,我认为DropDownList
具有自动完成属性
看http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.autocompletemode(v=vs.110).aspx
它解释了您应该使用哪个AutoCompleteMode以及如何设置AutoCompleteSource
答案 3 :(得分:-3)
您可以尝试以下几行,它对我有用
cbxName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
cbxName.AutoCompleteSource = AutoCompleteSource.ListItems;