Solved

DataGridViewComboBoxColumn very slow

Posted on 2011-09-26
6
1,185 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
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

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

Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

Question has a verified solution.

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

It seems a simple enough task, yet I see repeated questions asking how to do it: how to pass data between two forms. In this article, I will show you the different mechanisms available for you to do just that. This article is directed towards the .N…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

685 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