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:
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
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
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...
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?
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
jmfairchild
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.
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.
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?
jmfairchild
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.
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 ;)
si2030
ASKER
If I could I would give you both 500 each... cant see a way though... hope this is OK.
> 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 ;)
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.
- Jim