Search code examples
c#winformsdatagridviewcomboboxdropdown

Prevent ComboBox in DataGridView from opening and closing instantly in C# Winforms


I have a C# WinForms application, and I succeed in filtering ComboBox items by writing any part of its items and pressing enter after inputing the text part, using this code:

        private void detailsGridView_EditingControlShowing(object sender,
            DataGridViewEditingControlShowingEventArgs e)
        {
            var comboBox = e.Control as ComboBox;
            if (comboBox != null)
            {
                comboBox.DropDownStyle = ComboBoxStyle.DropDown;
                comboBox.PreviewKeyDown += ComboBox_PreviewKeyDown;
            }
        }

        private void ComboBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if ((e.KeyCode & e.KeyData) == Keys.Return)
            {
                if (((ComboBox)sender).SelectedItem == null)
                {
                    e.IsInputKey = true;
                    ((ComboBox)sender).DataSource = accounts
                        .Where(a => a.Name.Contains(((ComboBox)sender).Text))
                        .ToList();
                    ((ComboBox)sender).DroppedDown = true;
                }
            }
        }

Then I encountered a problem in line ((ComboBox)sender).DroppedDown = true where the list was dropping and closing instantly.

I noticed while debugging that KeyDown event raised twice so I tried a flag variable to check the second raise and cancel, but wasn't useful. I tried many other approaches like:

  • Adding line comboBox.PreviewKeyDown -= ComboBox_PreviewKeyDown; (with minus), before plus line.
  • Using each of KeyDown and PreviewKeyDown event listeners.

But the list still closing instantly after it had appeared.

What is the right approach in this context?

Edit:

I noticed that when I remove condition line if ((e.KeyCode & e.KeyData) == Keys.Return)

The function not work correctly but also the dropdown list stay open.


Solution

  • I solved this issue by adding a separate method for handling filter, and another method for handling KeyDown issue, this is the code:

    
    
            private void detailsGridView_EditingControlShowing(object sender,
                DataGridViewEditingControlShowingEventArgs e)
            {
                
                if (e.Control is ComboBox comboBox)
                {
                    comboBox.DropDownStyle = ComboBoxStyle.DropDown;
    
                    comboBox.KeyDown += ComboBox_KeyDown;
                    comboBox.PreviewKeyDown += ComboBox_PreviewKeyDown;
                }
            }
    
            private void ComboBox_PreviewKeyDown(object sender, 
                PreviewKeyDownEventArgs e)
            {
                if ((e.KeyCode & e.KeyData) == Keys.Enter)
                    if (((ComboBox)sender).SelectedItem == null)
                        e.IsInputKey = true;
            }
    
            private void ComboBox_KeyDown(object sender, KeyEventArgs e)
            {
                if ((e.KeyCode & e.KeyData) == Keys.Enter)
                {
                    if (((ComboBox)sender).SelectedItem == null)
                    {
                        e.SuppressKeyPress = e.Handled = true;
                        ((ComboBox)sender).DataSource = accounts
                            .Where(a => a.Name.Contains(((ComboBox)sender).Text))
                            .ToList();
                        ((ComboBox)sender).DroppedDown = true;
                    }
                }
            }
    

    Anyone can test this easily, its valid for any project.