自定义TextBox自动完成 [英] Customize TextBox autocomplete

查看:54
本文介绍了自定义TextBox自动完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何更改文本框的自动完成功能?我希望当我键入一个字符串时,该框会建议包含该字符串而不是开头的项目.

How do I change the autocomplete on a TextBox? I want that when I type a string, the box suggest items containing that string instead of starting with.

我的代码是:

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

我想要的东西:

推荐答案

查看您的代码,您只需要一行代码即可.该行是:

Looking at your code you have everything you need but 1 line of code. That line is:

这仅在输入字符串的开头时有效

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

这将用作contains方法,但可与自定义控件一起使用

This will work as a contains method but works with a custom control

您还可以根据需要创建自定义文本框控件.
自定义文本框类:

You can also make a custom textbox control that fits your needs.
Custom textbox class:

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

我从以下位置获得了自定义控件的代码:

I got the code for the custom control from: SO Question - Autocomplete contains

这篇关于自定义TextBox自动完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆