Solved

DataGridViewComboBoxColumn very slow

Posted on 2011-09-26
6
1,145 Views
Last Modified: 2013-12-17
Hello!

I have a DataGrid, with several columns. One of them is DataGridViewComboBoxColumn. I have a lot of items in this column - more than 1000 - and I need all of them. So grouping is not an option - all items must be there, users must be able to select from all.
The problem is, DataGridViewComboBoxColumn becomes painfully slow, when number of items is about 1000, and above. This issues is well known to Microsoft, it dates back to Visual Studio 2005: http://connect.microsoft.com/VisualStudio/feedback/details/117024/datagridviewcomboboxcolumn-responds-very-slow-compared-with-the-stand-alone-combobox-control.

The problem is still present in Visual Studio 2010. Any ideas how to solve this?
0
Comment
Question by:AntonioRodrigo
  • 3
  • 3
6 Comments
 
LVL 15

Accepted Solution

by:
x77 earned 500 total points
ID: 36711756
For large list of options, I use modified DataGridViewTextBoxCollumn to support Autocomplete.

To Validate value in list, it has property RestrictAutoComplete.
 
<DebuggerStepThrough()> _
Public NotInheritable Class DgvTextBoxCol
    Inherits DataGridViewTextBoxColumn
    Public AutoCompleteStringCollection As AutoCompleteStringCollection
    Public CharacterCasing As CharacterCasing
    Public RestrictAutoComplete As Boolean
    Public DrowDownWidth As Integer
    Private OldWidth As Integer

    Sub New()
        MyBase.New()
        CellTemplate = New Cell
    End Sub

    Protected Sub New (ByVal Cell As Cell)
        MyBase.New()
        CellTemplate = Cell
    End Sub

    Public Overrides Function Clone() As Object
        Dim c = DirectCast (MyBase.Clone(), DgvTextBoxCol)
        c.CharacterCasing = Me.CharacterCasing
        c.AutoCompleteStringCollection = Me.AutoCompleteStringCollection
        c.ValueType = MyBase.ValueType
'        c.RestrictAutoComplete = Me.RestrictAutoComplete
        Return c
    End Function

    Protected Class Cell
        Inherits DataGridViewTextBoxCell

        Public Overrides Sub InitializeEditingControl (ByVal rowIndex As Integer, _
                                                       ByVal initialFormattedValue As Object, _
                                                       ByVal dataGridViewCellStyle As DataGridViewCellStyle)

            ' Set the value of the editing control to the current cell value.
            MyBase.InitializeEditingControl (rowIndex, initialFormattedValue, dataGridViewCellStyle)
            Dim col = DirectCast (OwningColumn, DgvTextBoxCol), Tb = DirectCast (DataGridView.EditingControl, TextBox)
            Tb.CharacterCasing = col.CharacterCasing
            If col.AutoCompleteStringCollection IsNot Nothing Then
                Autocomplete (Tb, col.AutoCompleteStringCollection)
                If col.DrowDownWidth > 0 Then col.OldWidth = col.Width : col.Width = col.DrowDownWidth
            End If
        End Sub

        Public Overrides Sub DetachEditingControl()
            MyBase.DetachEditingControl()
            DirectCast (DataGridView.EditingControl, TextBox).PasswordChar = Nothing
            Dim Tb = DirectCast (DataGridView.EditingControl, TextBox)
            If Tb.AutoCompleteCustomSource IsNot Nothing Then
                Dim col = DirectCast (OwningColumn, DgvTextBoxCol)
                If col.OldWidth > 0 Then col.Width = col.OldWidth
                Autocomplete (Tb, Nothing)
            End If
            Tb.CharacterCasing = System.Windows.Forms.CharacterCasing.Normal
        End Sub

        <DebuggerStepThrough()> _
        Public Overrides Function ParseFormattedValue (ByVal formattedValue As Object, _
                                                       ByVal cellStyle As DataGridViewCellStyle, _
                                                       ByVal formattedValueTypeConverter As TypeConverter, _
                                                       ByVal valueTypeConverter As TypeConverter) As Object
            Dim c = DirectCast (OwningColumn, DgvTextBoxCol)
            Dim v = MyBase.ParseFormattedValue(formattedValue, cellStyle, formattedValueTypeConverter, _
                                                valueTypeConverter)
            If v IsNot Nothing AndAlso c.RestrictAutoComplete AndAlso TypeOf formattedValue Is String Then
                Dim s = DirectCast (v, String).Trim
                If s.Length = 0 Then Return Nothing
                If c.AutoCompleteStringCollection.Contains (s) = False Then _
                    Throw New FormatException ("Valor no contenido en lista de valores válidos")
                Return s
            End If
            Return v
        End Function
    End Class
End Class

Open in new window


This class supports also CharacterCasing.
You can set also DrowDownWidth.

I use it with list of about 1500 values with no problem.
0
 
LVL 15

Expert Comment

by:x77
ID: 36712218
I missing the Autocomplete, I declare it on a module:

Sub Autocomplete(ByVal Tb As TextBox, ByVal Ac As AutoCompleteStringCollection)
    If Ac Is Nothing Then
        Tb.AutoCompleteMode = Windows.Forms.AutoCompleteMode.None
        Tb.AutoCompleteSource = Windows.Forms.AutoCompleteSource.None
    Else
       Tb.AutoCompleteMode = Windows.Forms.AutoCompleteMode.Suggest
       Tb.AutoCompleteSource = Windows.Forms.AutoCompleteSource.CustomSource
    End If
    Tb.AutoCompleteCustomSource = Ac
End Sub
0
 

Author Comment

by:AntonioRodrigo
ID: 36716023
Is there a way to import ID in AutoCompleteStringCollection?

So, f.e.: I have a data table with column "ID" and column "Name". I want to display a "Name" column in autocomplete, but I also need an ID as information in the background for each row.

WIth DataGridViewComboBoxColumn this is solved as setting 'ValueMember' and 'DisplayMember' property.
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 

Author Comment

by:AntonioRodrigo
ID: 36716548
Is it possible to display drop down pop up with click on the text box?

I mean - I don't type anything in the text box, just click on it and drop down with items is opened.
0
 
LVL 15

Expert Comment

by:x77
ID: 36719573
The advantage of autocomplete is that, you press "A" by sample, then it show members that starts with "A", now you can type more chars and you can see the filtered result.

The combobox is more dificult to use.
It isn´t the best option for a lot of items.

Some times, I build an aditional Dialog to filter with "like" operator ( id like '%value%') or String.Contains.
By sample,  we need a Id and I don´nt know about this key, then I show a Dialog with a DGV or ListView that shows Id and Description with autofilter by id and description..

The user can need a Valve on System C11, the key is like xxC11Gxxx.
You can use DoubleClick on Dgv Field to shows Selection Dialog.
Most intuitive is a Button with "..." at right of your field  to show Selection dialog.

To build an autocomplete string collection, fill a list(of String) with values, then use

   MyAutoCompleteStringCollection.addrange(list.toarray)

You can use LinQ to build the array. I prefer the clasic method.
Note that you can use same collection on more than one field.
0
 

Author Closing Comment

by:AntonioRodrigo
ID: 36813207
The way to solve the problem is correct - use another control instead of painfully slow DataGridViewComboBoxColumn. I've come at the end to use ListBox on top of my DataGridView cell - which is very fast. Your idea was the first step to find solution.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
C# Error - Add Failed 12 78
Getting multiple values from a dataset ASP.NET(VB) 3 37
Runtime Error 2 28
Not showing page correctly 3 31
Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now