Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Custom DataGridviewColumn
 

Custom DataGridviewColumn

Hi,

I'm having problems with the following code, my mouseenter seems to force a datagridviewcell repaint, however the mouseleave event does not. leaving my two vertical lines on the button instead of repainting without the lines

Can anyone plz help
#Region " DataGridViewDropDownButtonColumn"
<DesignerSerializer(GetType(DataGridViewDropDownButtonSerializer), GetType(CodeDomSerializer))> _
Public Class DataGridViewDropDownButtonColumn
Inherits DataGridViewButtonColumn
#Region " Variables"
Private enabledValue As Boolean = False
Private m_Items As ToolStripMenuItem()
#End Region
#Region " Events"
Public Event Items_Clicked(ByVal sender As Object, ByVal e As DataGridViewDropDownButtonEventArgs)
#End Region
#Region " Properties"
<Browsable(False)> _
Public Property Enabled() As Boolean
Get
Return enabledValue
End Get
Set(ByVal value As Boolean)
enabledValue = value
End Set
End Property
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Property Items() As ToolStripMenuItem()
Get
Return m_Items
End Get
Set(ByVal value As ToolStripMenuItem())
Array.Resize(m_Items, value.Length)
Array.Copy(value, m_Items, value.Length)
For Each tsmi As ToolStripMenuItem In m_Items
AddHandler tsmi.Click, AddressOf DropDown_Clicked
Next
End Set
End Property
#End Region
#Region " Constructor"
Public Sub New()
Me.CellTemplate = New DataGridViewDropDownButtonCell()
enabledValue = False
End Sub
#End Region
#Region " Methods"
Public Overrides Function Clone() As Object
Dim Column As DataGridViewDropDownButtonColumn = CType(MyBase.Clone(), DataGridViewDropDownButtonColumn)
Column.m_Items = m_Items
Column.enabledValue = enabledValue
Return Column
End Function
Public Sub DropDown_Clicked(ByVal sender As Object, ByVal e As System.EventArgs)
'me.DataGridView.CurrentCell.RowIndex
RaiseEvent Items_Clicked(Me, New DataGridViewDropDownButtonEventArgs(sender _
, DataGridView.CurrentCell.ColumnIndex _
, DataGridView.CurrentCell.RowIndex))
End Sub
#End Region
End Class
#End Region
#Region " DataGridViewDropDownButtonCell"
Public Class DataGridViewDropDownButtonCell
Inherits DataGridViewButtonCell
#Region " Variables"
Private Shared m_borderSize As Integer = SystemInformation.Border3DSize.Width * 2
Private m_buttonState As System.Windows.Forms.VisualStyles.PushButtonState = PushButtonState.Normal
Private m_pushButtonWidth As Integer = 20
Dim m_contextmenu As ContextMenuStrip
Dim m_drawSplitLine As Boolean = False
#End Region
#Region " Properties"
Private Property ButtonState() As System.Windows.Forms.VisualStyles.PushButtonState
Get
Return m_buttonState
End Get
Set(ByVal value As System.Windows.Forms.VisualStyles.PushButtonState)
If Not m_buttonState.Equals(value) Then
m_buttonState = value
Me.DataGridView.InvalidateCell(Me.ColumnIndex, Me.RowIndex)
End If
End Set
End Property
#End Region
#Region " Constructor"
Public Sub New()
m_contextmenu = New ContextMenuStrip()
End Sub
#End Region
#Region " Methods"
' Override the Clone method so that the Enabled property is copied.
Public Overrides Function Clone() As Object
Dim Cell As DataGridViewDropDownButtonCell = _
CType(MyBase.Clone(), DataGridViewDropDownButtonCell)
Cell.m_buttonState = m_buttonState
Cell.m_pushButtonWidth = m_pushButtonWidth
Cell.m_contextmenu = m_contextmenu
Cell.m_drawSplitLine = m_drawSplitLine
Return Cell
End Function
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
Dim col As DataGridViewDropDownButtonColumn = CType(Me.OwningColumn, DataGridViewDropDownButtonColumn)
If col.Items IsNot Nothing Then
Dim dropDownButton As Rectangle = New Rectangle(ContentBounds.Right - m_pushButtonWidth - 1, m_borderSize, m_pushButtonWidth, ContentBounds.Height + m_pushButtonWidth * 2)
If dropDownButton.Contains(e.Location) Then
If col.Enabled = False Then
m_contextmenu.Items.AddRange(CType(Me.OwningColumn, DataGridViewDropDownButtonColumn).Items)
Dim d As Rectangle = Me.DataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, False)
m_contextmenu.Show(Me.DataGridView.PointToScreen(New Point(d.X + d.Width, d.Bottom)), ToolStripDropDownDirection.Left)
col.Enabled = True
Else
m_contextmenu.Hide()
col.Enabled = False
End If
Else
ButtonState = PushButtonState.Pressed
DirectCast(Me.OwningColumn, DataGridViewDropDownButtonColumn).DropDown_Clicked(Nothing, Nothing)
End If
End If
End Sub
Protected Overrides Sub OnMouseEnter(ByVal rowIndex As Integer)
MyBase.OnMouseEnter(rowIndex)
ButtonState = PushButtonState.Hot
End Sub
Protected Overrides Sub OnMouseLeave(ByVal rowIndex As Integer)
MyBase.OnMouseLeave(rowIndex)
ButtonState = System.Windows.Forms.VisualStyles.PushButtonState.Normal
End Sub
Protected Overrides Sub Paint(ByVal graphics As Graphics, _
ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
ByVal rowIndex As Integer, _
ByVal elementState As DataGridViewElementStates, _
ByVal value As Object, ByVal formattedValue As Object, _
ByVal errorText As String, _
ByVal cellStyle As DataGridViewCellStyle, _
ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
ByVal paintParts As DataGridViewPaintParts)
MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
' Draw the background of the cell, if specified.
If (paintParts And DataGridViewPaintParts.Background) = _
DataGridViewPaintParts.Background Then
Dim cellBackground As New SolidBrush(cellStyle.BackColor)
graphics.FillRectangle(cellBackground, cellBounds)
cellBackground.Dispose()
End If
' Draw the cell borders, if specified.
If (paintParts And DataGridViewPaintParts.Border) = _
DataGridViewPaintParts.Border Then

PaintBorder(graphics, clipBounds, cellBounds, cellStyle, _
advancedBorderStyle)
End If
' Calculate the area in which to draw the button.
Dim buttonArea As Rectangle = cellBounds
Dim buttonAdjustment As Rectangle = _
Me.BorderWidths(advancedBorderStyle)
buttonArea.X += buttonAdjustment.X
buttonArea.Y += buttonAdjustment.Y
buttonArea.Height -= buttonAdjustment.Height
buttonArea.Width -= buttonAdjustment.Width
' Draw the button.
ButtonRenderer.DrawButton(graphics, buttonArea, _
PushButtonState.Normal)
PaintArrow(graphics, cellBounds)
m_drawSplitLine = (ButtonState = System.Windows.Forms.VisualStyles.PushButtonState.Hot OrElse ButtonState = System.Windows.Forms.VisualStyles.PushButtonState.Pressed OrElse Not Application.RenderWithVisualStyles)
If m_drawSplitLine Then
' draw two lines at the edge of the dropdown button
graphics.DrawLine(SystemPens.ButtonShadow, buttonArea.Right - m_pushButtonWidth, buttonArea.Y + 3, buttonArea.Right - m_pushButtonWidth, buttonArea.Bottom - 3)
graphics.DrawLine(SystemPens.ButtonFace, buttonArea.Right - m_pushButtonWidth - 1, buttonArea.Y + 3, buttonArea.Right - m_pushButtonWidth - 1, buttonArea.Bottom - 3)
End If
If State <> System.Windows.Forms.VisualStyles.PushButtonState.Hot AndAlso (elementState And DataGridViewElementStates.Selected) <> 0 Then
ControlPaint.DrawFocusRectangle(graphics, cellBounds)
End If
End Sub
Private Sub PaintArrow(ByVal g As Graphics, ByVal dropDownRect As Rectangle)
Dim middle As New Point(dropDownRect.Right - ((m_pushButtonWidth + m_borderSize) / 2), dropDownRect.Top + (dropDownRect.Height / 2))
'if the width is odd - favor pushing it over one pixel right.
middle.X += (dropDownRect.Right Mod 2)
Dim arrow As Point() = New Point() {New Point(middle.X - 3, middle.Y - 1), New Point(middle.X + 4, middle.Y - 1), New Point(middle.X, middle.Y + 3)}
g.FillPolygon(SystemBrushes.ControlText, arrow)
End Sub
#End Region
End Class
#End Region

  • Moved byMartin Xie - MSFTMSFTMonday, August 24, 2009 3:04 AMMove it to DataBinding Controls Forum for better support. (From:Visual Basic General)
  • Changed TypeAland LiMSFT, ModeratorFriday, August 28, 2009 3:46 AMNo reply
  •  
garusher  Friday, August 21, 2009 5:04 PM

Hi garusher,

I have tested your code snippet but the two lines are drawing correctly. Did you add a handler to the CellMouseLeave event of the DataGridView? If so, you need to trace and check the code in the handle to figure out whether some code prevent the cell from being repainted.

Without caring that, we can call the InvalidateCell method in the end of the OnMouseEnter method of the DataGridViewDropDownButtonCell to force the cell to be repainted. This is a code snippet:
Protected Overrides Sub OnMouseEnter(ByVal rowIndex As Integer)

MyBase.OnMouseEnter(rowIndex)

ButtonState = PushButtonState.Hot

Me.DataGridView.InvalidateCell(Me)

End Sub

By the way, could you please provide the other code of your project, such as DataGridViewDropDownButtonSerializer and DataGridViewDropDownButtonEventArgs? This can help us test your code and figure out the root cause of the issue.

Let me know if this helps.
Aland Li


Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
Aland Li  Tuesday, August 25, 2009 8:49 AM

Hi,

We are changing the issue type to “General Discussion�because you have not followed up with the necessary information. If you have more time to look at the issue and provide more information, please feel free to change the issue type back to “Question�by opening the Options list at the top of the post window, and changing the type. If the issue is resolved, we will appreciate it if you can share the solution so that the answer can be found and used by other community members having similar questions.

Aland Li


Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
Aland Li  Friday, August 28, 2009 3:45 AM

You can use google to search for other answers

Custom Search

More Threads

• Problems with ListChanged Event
• Lockup with CurrencyManager using multiple child tables
• Regarding placing check boxes in .net 2003 datarid
• insert value to all cells in column
• Drag and drop reordering of rows in databound DataGridView
• DataGridView custom editing control -- larger than bounds of cell
• Uninstalling the Project
• Using one dataset on Multiple Forms
• inserting excel data into sql server through vb.net
• setting default values in datagridview