C#winformscomboboxdynamic自动完成
我的问题是类似于这一个: 我怎样才能dynamic更改自动完成在C#combobox或文本框中的条目? 但我仍然没有find解决办法。
简单的问题是:
我有一个ComboBox
和大量的logging显示在其中。 当用户开始input时,我想加载以input文本开头的logging,并提供用户自动完成。 正如上面的主题所述,我不能加载他们在сomboBox_TextChanged
因为我总是覆盖以前的结果,从来没有看到他们。
我可以只使用ComboBox
实现这个吗? (不是TextBox
或ListBox
)
我使用这个设置:
сomboBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend; сomboBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
这是我的最终解决scheme。 它可以很好地处理大量的数据。 我使用Timer
来确保用户想要查找当前值。 它看起来很复杂,但它不。 感谢Max Lambertini的想法。
private bool _canUpdate = true; private bool _needUpdate = false; //If text has been changed then start timer //If the user doesn't change text while the timer runs then start search private void combobox1_TextChanged(object sender, EventArgs e) { if (_needUpdate) { if (_canUpdate) { _canUpdate = false; UpdateData(); } else { RestartTimer(); } } } private void UpdateData() { if (combobox1.Text.Length > 1) { List<string> searchData = Search.GetData(combobox1.Text); HandleTextChanged(searchData); } } //If an item was selected don't start new search private void combobox1_SelectedIndexChanged(object sender, EventArgs e) { _needUpdate = false; } //Update data only when the user (not program) change something private void combobox1_TextUpdate(object sender, EventArgs e) { _needUpdate = true; } //While timer is running don't start search //timer1.Interval = 1500; private void RestartTimer() { timer1.Stop(); _canUpdate = false; timer1.Start(); } //Update data when timer stops private void timer1_Tick(object sender, EventArgs e) { _canUpdate = true; timer1.Stop(); UpdateData(); } //Update combobox with new data private void HandleTextChanged(List<string> dataSource) { var text = combobox1.Text; if (dataSource.Count() > 0) { combobox1.DataSource = dataSource; var sText = combobox1.Items[0].ToString(); combobox1.SelectionStart = text.Length; combobox1.SelectionLength = sText.Length - text.Length; combobox1.DroppedDown = true; return; } else { combobox1.DroppedDown = false; combobox1.SelectionStart = text.Length; } }
这个解决scheme不是很酷。 所以,如果有人有另一种解决scheme,请与我分享。
我最近也碰到过这样的要求。我把下面的属性设置成了写出它的工作代码,看看这是否对你有帮助。
是的,你当然可以……但需要一些工作才能使其无缝工作。 这是我想出的一些代码。 请记住,它不使用combobox的自动完成function,如果用它来筛选很多项目,它可能会很慢。
string[] data = new string[] { "Absecon","Abstracta","Abundantia","Academia","Acadiau","Acamas", "Ackerman","Ackley","Ackworth","Acomita","Aconcagua","Acton","Acushnet", "Acworth","Ada","Ada","Adair","Adairs","Adair","Adak","Adalberta","Adamkrafft", "Adams" }; public Form1() { InitializeComponent(); } private void comboBox1_TextChanged(object sender, EventArgs e) { HandleTextChanged(); } private void HandleTextChanged() { var txt = comboBox1.Text; var list = from d in data where d.ToUpper().StartsWith(comboBox1.Text.ToUpper()) select d; if (list.Count() > 0) { comboBox1.DataSource = list.ToList(); //comboBox1.SelectedIndex = 0; var sText = comboBox1.Items[0].ToString(); comboBox1.SelectionStart = txt.Length; comboBox1.SelectionLength = sText.Length - txt.Length; comboBox1.DroppedDown = true; return; } else { comboBox1.DroppedDown = false; comboBox1.SelectionStart = txt.Length; } } private void comboBox1_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Back) { int sStart = comboBox1.SelectionStart; if (sStart > 0) { sStart--; if (sStart == 0) { comboBox1.Text = ""; } else { comboBox1.Text = comboBox1.Text.Substring(0, sStart); } } e.Handled = true; } }
此代码写入您的表单加载。 当用户在combobox中input字母时,它将显示数据库中的所有巡视。 该代码自动build议并追加用户所需的正确select。
con.Open(); cmd = new SqlCommand("SELECT DISTINCT Tour FROM DetailsTB", con); SqlDataReader sdr = cmd.ExecuteReader(); DataTable dt = new DataTable(); dt.Load(sdr); combo_search2.DisplayMember = "Tour"; combo_search2.DroppedDown = true; List<string> list = new List<string>(); foreach (DataRow row in dt.Rows) { list.Add(row.Field<string>("Tour")); } this.combo_search2.Items.AddRange(list.ToArray<string>()); combo_search2.AutoCompleteMode = AutoCompleteMode.SuggestAppend; combo_search2.AutoCompleteSource = AutoCompleteSource.ListItems; con.Close();
在以前的答复是缺点。 提供其自己的版本,在下拉列表中select所需的项目:
private ConnectSqlForm() { InitializeComponent(); cmbDatabases.TextChanged += UpdateAutoCompleteComboBox; cmbDatabases.KeyDown += AutoCompleteComboBoxKeyPress; } private void UpdateAutoCompleteComboBox(object sender, EventArgs e) { var comboBox = sender as ComboBox; if(comboBox == null) return; string txt = comboBox.Text; string foundItem = String.Empty; foreach(string item in comboBox.Items) if (!String.IsNullOrEmpty(txt) && item.ToLower().StartsWith(txt.ToLower())) { foundItem = item; break; } if (!String.IsNullOrEmpty(foundItem)) { if (String.IsNullOrEmpty(txt) || !txt.Equals(foundItem)) { comboBox.TextChanged -= UpdateAutoCompleteComboBox; comboBox.Text = foundItem; comboBox.DroppedDown = true; Cursor.Current = Cursors.Default; comboBox.TextChanged += UpdateAutoCompleteComboBox; } comboBox.SelectionStart = txt.Length; comboBox.SelectionLength = foundItem.Length - txt.Length; } else comboBox.DroppedDown = false; } private void AutoCompleteComboBoxKeyPress(object sender, KeyEventArgs e) { var comboBox = sender as ComboBox; if (comboBox != null && comboBox.DroppedDown) { switch (e.KeyCode) { case Keys.Back: int sStart = comboBox.SelectionStart; if (sStart > 0) { sStart--; comboBox.Text = sStart == 0 ? "" : comboBox.Text.Substring(0, sStart); } e.SuppressKeyPress = true; break; } } }
我发现Max Lambertini的回答非常有帮助,但已经修改了他的HandleTextChanged方法:
//I like min length set to 3, to not give too many options //after the first character or two the user types public Int32 AutoCompleteMinLength {get; set;} private void HandleTextChanged() { var txt = comboBox.Text; if (txt.Length < AutoCompleteMinLength) return; //The GetMatches method can be whatever you need to filter //table rows or some other data source based on the typed text. var matches = GetMatches(comboBox.Text.ToUpper()); if (matches.Count() > 0) { //The inside of this if block has been changed to allow //users to continue typing after the auto-complete results //are found. comboBox.Items.Clear(); comboBox.Items.AddRange(matches); comboBox.DroppedDown = true; Cursor.Current = Cursors.Default; comboBox.Select(txt.Length, 0); return; } else { comboBox.DroppedDown = false; comboBox.SelectionStart = txt.Length; } }
我写了这样的东西….
private void frmMain_Load(object sender, EventArgs e) { cboFromCurrency.Items.Clear(); cboComboBox1.AutoCompleteMode = AutoCompleteMode.Suggest; cboComboBox1.AutoCompleteSource = AutoCompleteSource.ListItems; // Load data in comboBox => cboComboBox1.DataSource = ..... // Other things } private void cboComboBox1_KeyPress(object sender, KeyPressEventArgs e) { cboComboBox1.DroppedDown = false; }
这就是(Y)
using (var client = new UserServicesClient()) { var list = new AutoCompleteStringCollection(); list.AddRange(client.ListNames(query).ToArray()); comboBoxName.AutoCompleteCustomSource = list; }