2017-04-06 303 views
1

如何更改文本框上的自動完成?我希望當我輸入一個字符串時,該框會建議包含該字符串的項目而不是以開頭。自定義文本框自動完成

我的代碼是:

class MyClass 
{ 
    private AutoCompleteStringCollection autoCompleteList = new AutoCompleteStringCollection(); 

    public MyClass() 
    { 
     InitializeComponent(); 

     autoCompleteList.AddRange(ListNames.Select(x=>x.Name).ToArray()); 
     textBoxName.AutoCompleteCustomSource = autoCompleteList; 
     textBoxName.AutoCompleteSource = AutoCompleteSource.CustomSource; 
     textBoxName.AutoCompleteMode = AutoCompleteMode.Suggest; 
     textBoxName.KeyDown += TextBoxtextName_KeyDown; 
    } 

    private void TextBoxClient_KeyDown(object sender, KeyEventArgs e) 
    { 
     if (e.KeyData == Keys.Enter) 
     { 
      this.Name = (sender as TextBox).Text; 
     } 
    }  
} 

我想要什麼:

desired autocomplete

+0

你可能將不得不做手工。檢查第一個答案在這裏:http://stackoverflow.com/questions/7985620/autocomplete-contains-instead-of-starting-with-in-winform-textbox –

+0

@RufusL這個答案建議使用組合框,但我們可以寫在裏面。我會檢查一個自定義控件組合+文本框是否可以幫助我。 –

+0

@ A.Pissicat使用自定義文本框添加解決方案到您的問題 – EpicKip

回答

3

你的代碼看你有你需要的一切,但1行代碼。這條線是:

如果輸入

//Suggestion only 
textBoxName.AutoCompleteMode = AutoCompleteMode.Suggest; 
//Suggest and autocomplete 
textBoxName.AutoCompleteMode = AutoCompleteMode.SuggestAppend; 

這將作爲contains方法字符串的開始,但有一個自定義的控制工作,此功能才能

你可以還可以製作適合您需求的自定義文本框控件。
自定義文本類:

public class AutoCompleteTextBox : TextBox 
{ 
    private ListBox _listBox; 
    private bool _isAdded; 
    private String[] _values; 
    private String _formerValue = String.Empty; 

    public AutoCompleteTextBox() 
    { 
     InitializeComponent(); 
     ResetListBox(); 
    } 

    private void InitializeComponent() 
    { 
     _listBox = new ListBox(); 
     this.KeyDown += this_KeyDown; 
     this.KeyUp += this_KeyUp; 
    } 

    private void ShowListBox() 
    { 
     if (!_isAdded) 
     { 
      Parent.Controls.Add(_listBox); 
      _listBox.Left = Left; 
      _listBox.Top = Top + Height; 
      _isAdded = true; 
     } 
     _listBox.Visible = true; 
     _listBox.BringToFront(); 
    } 

    private void ResetListBox() 
    { 
     _listBox.Visible = false; 
    } 

    private void this_KeyUp(object sender, KeyEventArgs e) 
    { 
     UpdateListBox(); 
    } 

    private void this_KeyDown(object sender, KeyEventArgs e) 
    { 
     switch (e.KeyCode) 
     { 
      case Keys.Enter: 
      case Keys.Tab: 
      { 
       if (_listBox.Visible) 
       { 
        Text = _listBox.SelectedItem.ToString(); 
        ResetListBox(); 
        _formerValue = Text; 
        this.Select(this.Text.Length, 0); 
        e.Handled = true; 
       } 
       break; 
      } 
      case Keys.Down: 
      { 
       if ((_listBox.Visible) && (_listBox.SelectedIndex < _listBox.Items.Count - 1)) 
        _listBox.SelectedIndex++; 
        e.Handled = true; 
        break; 
       } 
       case Keys.Up: 
       { 
        if ((_listBox.Visible) && (_listBox.SelectedIndex > 0)) 
         _listBox.SelectedIndex--; 
        e.Handled = true; 
        break; 
       } 


      } 
     } 

     protected override bool IsInputKey(Keys keyData) 
     { 
      switch (keyData) 
      { 
       case Keys.Tab: 
        if (_listBox.Visible) 
         return true; 
        else 
         return false; 
       default: 
        return base.IsInputKey(keyData); 
      } 
     } 

     private void UpdateListBox() 
     { 
      if (Text == _formerValue) 
       return; 

      _formerValue = this.Text; 
      string word = this.Text; 

      if (_values != null && word.Length > 0) 
      { 
       string[] matches = Array.FindAll(_values, 
        x => (x.ToLower().Contains(word.ToLower()))); 
       if (matches.Length > 0) 
       { 
        ShowListBox(); 
        _listBox.BeginUpdate(); 
        _listBox.Items.Clear(); 
        Array.ForEach(matches, x => _listBox.Items.Add(x)); 
        _listBox.SelectedIndex = 0; 
        _listBox.Height = 0; 
        _listBox.Width = 0; 
        Focus(); 
        using (Graphics graphics = _listBox.CreateGraphics()) 
        { 
         for (int i = 0; i < _listBox.Items.Count; i++) 
         { 
          if (i < 20) 
          _listBox.Height += _listBox.GetItemHeight(i); 
         // it item width is larger than the current one 
         // set it to the new max item width 
         // GetItemRectangle does not work for me 
         // we add a little extra space by using '_' 
         int itemWidth = (int)graphics.MeasureString(((string)_listBox.Items[i]) + "_", _listBox.Font).Width; 
         _listBox.Width = (_listBox.Width < itemWidth) ? itemWidth : this.Width; ; 
        } 
       } 
       _listBox.EndUpdate(); 
      } 
      else 
      { 
       ResetListBox(); 
      } 
     } 
     else 
     { 
      ResetListBox(); 
     } 
    } 

    public String[] Values 
    { 
     get 
     { 
      return _values; 
     } 
     set 
     { 
      _values = value; 
     } 
    } 

    public List<String> SelectedValues 
    { 
     get 
     { 
      String[] result = Text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 
      return new List<String>(result); 
     } 
    } 
} 

用法:

string[] nameArray = { "name1", "name2", "name3", "bla name" }; 
AutoCompleteTextBox tb = new AutoCompleteTextBox(); 
tb.Values = nameArray; 
tb.Location = new Point(10,10); 
tb.Size = new Size(25,75); 
this.Controls.Add(tb); 

我從定製控件的代碼:SO Question - Autocomplete contains

+0

[此問題(Combobox AutoCompleteMode Suggest contains)](http://stackoverflow.com/questions/19020313/combobox-autocompletemode-suggest-contain)表明可能not enough enough – stuartd

+0

@stuartd我剛纔注意到了這一點,並在回答中添加了一條註釋。我會盡力找到完整的答案:) – EpicKip

+0

正如我所說的,我需要使用包含方法進行搜索。也許如果我創建自定義文本框並覆蓋自動填充方法,但我不知道它是如何工作的。我在設計器中設置了autocompletemode,我忘了將它複製到我的問題中。 –