Link to home
Create AccountLog in
Avatar of si2030
si2030

asked on

Datagridviewcombobox ondrawitem works but has over 30 items in dropdown..

Hi Experts,

Not sure how to fix this. I have overloaded the Datagridviewcombobox to make it a multicolumn combobox. It works. I did this through the following site:

http://www.codeguru.com/csharp/csharp/cs_controls/datagrid/article.php/c13571/

However, I cannot reduce the size of the dropdown portion....

I am using the "onDrawItem".

I cannot find where you would or could reduce the number of items in the painted potion.

I have included the subroutine below.  It obtains a row and then paints the row horizontally. Thats fine... but the dropdown is too big.. see picture..

I tried to limit the number of rows actually being painted but it did this and still painted a full rectangle. See the second picture.

Not sure how I can reduce this rectangle while sitll having all the items and a scroll bar to view them all.

Simon
Protected Overloads Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
 
            Dim rec As New Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height) 'e.Bounds.Width
            Dim column As DataGridViewMultiColumnComboColumn = TryCast(ownerCell.OwningColumn, DataGridViewMultiColumnComboColumn)
            Dim valuesTbl As DataTable = column.valuesTbl
            Dim joinByField As String = column.joinFieldName
            Dim NormalText As New SolidBrush(System.Drawing.SystemColors.ControlText)
            Dim currentItem As Object = Items(e.Index)
            Dim currentText As String = GetItemText(currentItem)
 
            'If there is an item
            If (e.Index > -1) Then
 
                'first redraw the normal while background
                Dim normalBack As New SolidBrush(Color.White)          'TODO: fix to be system edit box background
 
                e.Graphics.FillRectangle(normalBack, rec)
 
                If DroppedDown AndAlso Not (Margin.Top = rec.Top) Then
 
                    Dim currentOffset As Integer = rec.Left
                    Dim col As DataColumn = valuesTbl.Columns(0)
 
                    'now find this text in current join field
                    Dim itemRows As DataRow() = valuesTbl.[Select](("[" & joinByField & "]='") + currentText & "'")
 
                    Dim HightlightedBack As New SolidBrush(System.Drawing.SystemColors.Highlight)
 
                    If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
 
                        'draw selected color background
                        e.Graphics.FillRectangle(HightlightedBack, rec)
 
                    End If
 
                    Dim addBorder As Boolean = False
                    Dim currentRow As DataRow = itemRows(0)
 
                    Dim valueItem As Object
 
                    For Each dataRowItem As Object In currentRow.ItemArray
 
                        valueItem = dataRowItem
 
                        Dim value As String = dataRowItem.ToString()  'TODO: support for different types!!!
 
                        'Add the vertical boarder line here...
                        If addBorder Then
 
                            'draw dividing line
                            'currentOffset ++;
 
                            Dim gridBrush As New SolidBrush(Color.Gray)    'TODO: make the border color configurable
 
                            Dim linesNum As Long = lineWidth
 
                            While linesNum > 0
 
                                linesNum -= 1
 
                                Dim first As New Point(rec.Left + currentOffset, rec.Top)
                                Dim last As New Point(rec.Left + currentOffset, rec.Bottom)
                                e.Graphics.DrawLine(New Pen(gridBrush), first, last)
 
                                currentOffset += 1
 
                            End While
                            'currentOffset++;
                        Else
 
                            addBorder = True
 
                        End If
 
                        'measure the string that we are going to draw and cut it with wrapping if too large
                        Dim extent As SizeF = e.Graphics.MeasureString(value, e.Font)
                        Dim textRec As New Rectangle(currentOffset, rec.Y, CInt(extent.Width), rec.Height)
 
                        'now draw the relevant to this column value text
 
                        If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
 
                            'draw selected
                            Dim HightlightedText As New SolidBrush(System.Drawing.SystemColors.HighlightText)
 
                            'now redraw the backgrond in order to wrap the previous field if was too large
                            e.Graphics.FillRectangle(HightlightedBack, currentOffset, rec.Y, fixedAlignColumnSize, extent.Height)
 
                            'draw text as is
                            e.Graphics.DrawString(value, e.Font, HightlightedText, textRec)
 
                        Else
                            'now redraw the backgrond it order to wrap the previous field if was too large
                            e.Graphics.FillRectangle(normalBack, currentOffset, rec.Y, fixedAlignColumnSize, extent.Height)
 
                            'draw text as is
                            e.Graphics.DrawString(value, e.Font, NormalText, textRec)
 
                        End If
 
                        'advance the offset to the next position
                        currentOffset += fixedAlignColumnSize
 
                    Next
 
                End If
 
            End If
 
        End Sub

Open in new window

Dropdown1.jpg
dropdown2.jpg
Avatar of jmfairchild
jmfairchild

Since the control is a combobox, you can set the .MaxDropDownItems value and it should do what you are looking for. I tested a sample app and it worked great for me. If you need a code example, let me know.

- Jim
Avatar of si2030

ASKER

Hi Jim,

I have tried .MaxDropDownItems in a number of different places... where should it be added. This approach replaces the first row with my multi column overload. I have put it straight after the creation and then repoacement of the column. I have put it in the EditingControlShowing sub after applying

Dim cmb As ComboBox = CType(e.Control, ComboBox)

I have also tried placing it in the overload of the DataGridViewComboBoxEditingControl and that hasnt worked and I even tried placing it in the OnDrawItem method... none of these have worked so I thought it might be the way its drawn...

Simon
ASKER CERTIFIED SOLUTION
Avatar of jmfairchild
jmfairchild

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
If it still doesn't work for you, let me take a look at your project code. There my be something else keeping it from working.

- Jim
Avatar of si2030

ASKER

Hi Jim,

I have streamline the test project for you and I was wondering how I can attach my zip file for you... its complaining that it has a file with .SLN in the zip files? Is there a place or procedure for doing this?

Simon

Avatar of si2030

ASKER

Hi Jim/Others

I have uploaded the project to EE-Stuff. see

https://filedb.experts-exchange.com/incoming/ee-stuff/7544-MultiColumnOverRIDE.ziphttps://filedb.experts-exchange.com/incoming/ee-stuff/7545-DataGridViewMultiColumnComboVB.zip


This project is just one form with one DGV in which the first column is the one I am focusing on.

I have replaced my LINQ query with a simple datatable. The code for overwriting the DGVcombobox is in the VB file multiColumnCombobox.vb which also contains the ondrawitem...

Hoping that you might be able to help..

Simon
Only had a little while to look at this today, but one thing I noticed. When I run your code as uploaded, when I hit the DropDown button, it displays 8 items. If I hit it again or any subsequent time, it now shows 2. Do you get the same results? Just ensuring it is not somesort of environment issue.

- Jim
Also, when I try to open the multiColumnCombobox control in designer mode I get designer errors. Just ensuring that there isn't something needed there either.

- Jim
SOLUTION
Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
PS, I did have the same design errors as jmfairchild, but I did not have the strange list (s)he mentions. There were 23 items in the list. Maybe VS2008 + SP1 makes the difference, or do we all have the same versions?
I was actually testing using VB 2008 EXPRESS + SP1. The list has 23 items, but I mentioned only 8 display since that was what Simon was looking for. I tested your code above, but it didn't work for me, so I tried it with full VS 2008 + SP1 same-o same-o. I cut my .NET teeth on VB.NET, but it's been awhile. My language of choice is now C#. I downloaded the demo code that Simon first alluded to which is in C#, and the MaxDropDownItems works as expected. I am losing something in the transalation. His code works funny when I try to run it, like the 8 items display then 2 items display issue. I also can't seem to set any breakpoints in the VB.NET environment that will actually work to debug. My next step is to do a translation myself since that is essentially what he is looking for. I will post it here shortly. Hopefully this will help to give you a start toward your goal.

-Jim
I have translated the original C# code into VB.NET and the MaxDropDownItems seems to work as expected. Hopefully this will get you started.

https://filedb.experts-exchange.com/incoming/ee-stuff/7545-DataGridViewMultiColumnComboVB.zip

Let me know how it goes.
- Jim
Quite a piece of work. Strange that you didn't get the original to work. Like you use MaxDropDownltems (one line? I didn't check your code) the DropDownHeight should work just the same. Strange it doesn't work for you and that you had so much trouble with the breakpoints for OP's code.

If it's just for the effort you pulled I vote for you getting the points ;)
Avatar of si2030

ASKER

If I could I would give you both 500 each... cant see a way though... hope this is OK.

Simon
> If I could I would give you both 500 each... cant see a way though... hope this is OK.

that's not allowed on EE... Tx for the points, glad it worked out. Hope the solution of jmfairchild helped you around, he really pulled something there ;)
Avatar of si2030

ASKER

Yes I would be no where near where I am at the moment if it were not for the ability to ask questions and the time you guys give... I am starting to get it but its a slow process to learn this and the help over those sticky points is invaluable.

Kind Regards to you both.

Simon
Any time.

- Jim