[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

DataGridViewComboBoxColumn very slow

Posted on 2011-09-26
6
Medium Priority
?
1,262 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
6 Comments
 
LVL 15

Accepted Solution

by:
x77 earned 2000 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
Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

 

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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

650 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