C # winforms combobox dinamico completamento automatico

Il mio problema è simile a questo: Come posso modificare dynamicmente le voci di completamento automatico in una combobox o una casella di testo C #? Ma ancora non trovo la soluzione.

Il problema brevemente:

Ho un ComboBox e un gran numero di record da mostrare al suo interno. Quando l’utente inizia a digitare, voglio caricare i record che iniziano con il testo di input e offrono all’utente il completamento automatico. Come descritto nell’argomento sopra, non riesco a caricarli su сomboBox_TextChanged perché sovrascrivo sempre i risultati precedenti e non li vedo mai.

Posso implementarlo usando solo ComboBox ? (non TextBox o ListBox )

Io uso queste impostazioni:

 сomboBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend; сomboBox.AutoCompleteSource = AutoCompleteSource.CustomSource; 

Ho anche incontrato di recente questo tipo di requisiti. Imposto le proprietà sottostanti senza scrivere il codice che funziona. Vedi se questo ti aiuta.

inserisci la descrizione dell'immagine qui

Ecco la mia soluzione finale. Funziona bene con una grande quantità di dati. Io uso il Timer per assicurarmi che l’utente voglia trovare il valore corrente. Sembra complesso ma non lo è. Grazie a Max Lambertini per l’idea.

  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 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 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; } } 

Questa soluzione non è molto bella. Quindi se qualcuno ha un’altra soluzione per favore condividila con me.

Sì, puoi sicuramente … ma ha bisogno di un po ‘di lavoro per farlo funzionare senza problemi. Questo è un codice che ho trovato. Ricorda che non utilizza le funzioni di completamento automatico di Combobox e potrebbe essere piuttosto lento se lo si utilizza per setacciare molti articoli …

 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; } } 

Ho scritto qualcosa del genere ….

 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; } 

Questo è tutto (Y)

Ho trovato la risposta di Max Lambertini molto utile, ma ho modificato il suo metodo HandleTextChanged in quanto tale:

  //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; } } 

Questo codice è scritto sul caricamento del modulo. Visualizza tutto il Tour nel database quando la lettera del tipo di utente nella casella combinata. Questo codice suggerisce automaticamente e aggiunge la scelta giusta come desidera l’utente.

  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 list = new List(); foreach (DataRow row in dt.Rows) { list.Add(row.Field("Tour")); } this.combo_search2.Items.AddRange(list.ToArray()); combo_search2.AutoCompleteMode = AutoCompleteMode.SuggestAppend; combo_search2.AutoCompleteSource = AutoCompleteSource.ListItems; con.Close(); 

Nelle risposte precedenti ci sono degli inconvenienti. Offre la propria versione con la selezione nell’elenco a discesa l’elemento desiderato:

  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; } } } 
  using (var client = new UserServicesClient()) { var list = new AutoCompleteStringCollection(); list.AddRange(client.ListNames(query).ToArray()); comboBoxName.AutoCompleteCustomSource = list; }