locked
Limit dropdown list autocomplete textbox RRS feed

  • Pregunta

  • Hi,

    I create an auto complete list for a textbox. I shows 16 values. This makes the list to long for me. Is it possible to shorten de list to 5 items?

    This is what i have:

    using (AutoComplete aCompleteSource = new AutoComplete())
                    {								
                        AutoCompleteStringCollection DataCollection;
                        DataCollection = aCompleteSource.CreAutoCompleteListFromTrv(TreeViewExecuteQueries);  //Create the autocomplete list for the search box
                        TextBoxSearchInQueryTreeView.AutoCompleteSource = AutoCompleteSource.CustomSource;
                        TextBoxSearchInQueryTreeView.AutoCompleteCustomSource = DataCollection;                    
    					TextBoxSearchInQueryTreeView.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                    }
    				
    				
    public class AutoComplete : IDisposable
        {
            
            public AutoCompleteStringCollection CreAutoCompleteListFromTrv(TreeView Trv)
            {
                if (Trv != null)
                {
                    AutoCompleteStringCollection DataCollection = new AutoCompleteStringCollection();
                    addItems(DataCollection, Trv);
    
                    return DataCollection;
                }
                else
                {
                    return null;
                }
            }
            private void addItems(AutoCompleteStringCollection col, TreeView Trv)
            {
                TreeNodeCollection nodes = Trv.Nodes;
                foreach (TreeNode n in nodes)
                {
                    GetTrvNodeName(n, col);
                }
            }
            private void GetTrvNodeName(TreeNode treeNode, AutoCompleteStringCollection col)
            {
                col.Add(treeNode.Name);
                foreach (TreeNode tn in treeNode.Nodes)
                {
                    GetTrvNodeName(tn, col);
                }
            }
    
    
            #region Dispose 
            ...
            #endregion Dispose
        }		

    • Cambiado CoolDadTx lunes, 17 de agosto de 2020 14:04 Winforms related
    domingo, 16 de agosto de 2020 18:53

Todas las respuestas

  • Hi HansvB69,

    Thank you for posting here.

    There is no ready-made API to limit the number of displays, but we can use linq to select the number we want from the source data and use it as the AutoCompleteCustomSource of the textbox.

               using (AutoComplete aCompleteSource = new AutoComplete())
                {
                    AutoCompleteStringCollection DataCollection;
                    DataCollection = aCompleteSource.CreAutoCompleteListFromTrv(treeView1);  //Create the autocomplete list for the search box
    
                    AutoCompleteStringCollection DataCollection1 = new AutoCompleteStringCollection();
                   DataCollection1.AddRange(DataCollection.Cast<string>().Take(5).ToArray());
                   textBox1.AutoCompleteCustomSource = DataCollection1;
    
                    textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
                    textBox1.AutoCompleteMode = AutoCompleteMode.Suggest;
                }

    Hope this could be helpful.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    lunes, 17 de agosto de 2020 6:46
  • Hi,

    That is not the answer i am looking for. This limits the list to 5 items. What i want is a complete list but only the dropdownlist must show 3 values and a scrollbar so you can scroll through the list.

    So to use you're example. In the dropdown list you see "name0, name1, name2" and name3, name4 is still there but you have to scroll for them.

    Greatings, Hans

    miércoles, 19 de agosto de 2020 15:42
  • Hi HansvB69,

    Unfortunately, the autocomplete provided by Microsoft cannot achieve this function. I think we have to use a custom textbox to replace the original textbox.

    Please refer to the following code, which is basically from this link.

    I made some modifications to it to suit your requirements.

     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;
    
                _listBox.DoubleClick += _listBox_DoubleClick;
            }
    
            private void _listBox_DoubleClick(object sender, EventArgs e)
            {
                this.Text = _listBox.SelectedItem.ToString();
                ResetListBox();
            }
    
            private void ShowListBox()
            {
                if (!_isAdded)
                {
                    Form parentForm = this.FindForm(); // new line added
                    parentForm.Controls.Add(_listBox); // adds it to the form
                    Point positionOnForm = parentForm.PointToClient(this.Parent.PointToScreen(this.Location)); // absolute position in the form
                    _listBox.Left = positionOnForm.X;
                    _listBox.Top = positionOnForm.Y + 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 =_listBox.GetItemHeight(0)*6 ;
                        _listBox.Width = 0;
                        Focus();
                        using (Graphics graphics = _listBox.CreateGraphics())
                        {
                            for (int i = 0; i < _listBox.Items.Count; i++)
                            {
                                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);
                }
            }
        }
        public partial class Form1 : Form
        {
            private readonly String[] _values = { "test1", "test2", "test3", "test4", "test5", "test6", "test7",
            "test8","test9","test10"};
            public Form1()
            {
                InitializeComponent();
                autoCompleteTextBox1.Values = _values;
            }
        }

    Hope this could be helpful.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    viernes, 21 de agosto de 2020 2:04