none
Center vertically Combobox in DataGridViewComboBoxColumn RRS feed

  • Question

  • Hi,

    I have a DataGridViewComboBoxColumn aligned to MiddleRight, the row height is a liitle bit higher than the combobox height, when selecting the item text is correctly aligned, but combobox arrow sticks to the top of the cell:


    How can I center the control vertically?

    Regards


    G.Waters


    Wednesday, April 4, 2018 6:43 PM

Answers

  • Okay, this may not be perfect but it's the best I have for time allotted. So I got the cell to be centered when not in edit mode but in edit mode no, perhaps it needs more paint overrides.

    Custom column and cell

    Public Class kpDataGridViewComboBoxColumn
        Inherits DataGridViewComboBoxColumn
    
        Public Sub New()
            CellTemplate = new kpDataGridViewComboBoxCell
        End Sub
        Public Overrides Property CellTemplate() As DataGridViewCell
            Get
                Return MyBase.CellTemplate
            End Get
            Set
                If Not (value Is Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(kpDataGridViewComboBoxCell)) Then
                    Throw New InvalidCastException("Dang something went wrong :-(")
                End If
    
                MyBase.CellTemplate = value
    
            End Set
        End Property
    
    End Class
    Public Class kpDataGridViewComboBoxCell
        Inherits DataGridViewComboBoxCell
    
        Private enabledValue as Boolean = true
        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)
    
            If Not Me.enabledValue Then
                If (paintParts And DataGridViewPaintParts.Background) = DataGridViewPaintParts.Background Then
                    Dim cellBackground As New SolidBrush(cellStyle.BackColor)
                    graphics.FillRectangle(cellBackground, cellBounds)
                    cellBackground.Dispose()
                End If
    
                If (paintParts And DataGridViewPaintParts.Border) = DataGridViewPaintParts.Border Then
                    PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
                End If
    
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText,
                             cellStyle, advancedBorderStyle, paintParts)
            Else
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText,
                             cellStyle, advancedBorderStyle, paintParts)
            End If
        End Sub
    
    End Class
    

    Code module for extension method

    Module DatagridViewExtensions
        <DebuggerStepThrough()>
        <Runtime.CompilerServices.Extension()>
        Public Function IsComboBoxCell(ByVal sender As DataGridViewCell) As Boolean
            Dim result As Boolean = False
            If sender.EditType IsNot Nothing Then
                If sender.EditType Is GetType(DataGridViewComboBoxEditingControl) Then
                    result = True
                End If
            End If
            Return result
        End Function
    End Module

    Form code. DataGridView has no columns in the designer, all created below.

    Public Class Form1
        Private AutoList As AutoCompleteStringCollection = 
                    New AutoCompleteStringCollection
    
        Private cbo As ComboBox
        Private ComboColumnName As String = "C1"
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Dim source = New String() {"Add", "Subtract", "Divide", "Multiply"}
    
            Dim DataGridViewCellStyle1 As DataGridViewCellStyle = New DataGridViewCellStyle()
            DataGridViewCellStyle1.Alignment = DataGridViewContentAlignment.MiddleCenter
    
            Dim column1 As New kpDataGridViewComboBoxColumn With
                    {
                        .DataSource = source,
                        .DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing,
                        .DefaultCellStyle =  DataGridViewCellStyle1,
                        .Name = ComboColumnName,
                        .HeaderText = "Demo",
                        .SortMode = DataGridViewColumnSortMode.NotSortable
                    }
    
            Dim column2 As New DataGridViewCheckBoxColumn With
                    {
                        .Name = "C2",
                        .HeaderText = "Col 2"
                    }
            Dim column3 As New DataGridViewTextBoxColumn With
                    {
                        .Name = "C3",
                        .HeaderText = "Col 3"
                    }
    
            AutoList.AddRange(source)
    
            DataGridView1.Columns.AddRange(New DataGridViewColumn() {column1, column2, column3})
    
            DataGridView1.Rows.Add(New Object() {"Divide", True, "Karen"})
            DataGridView1.Rows.Add(New Object() {"Add", False, "Kevin"})
            DataGridView1.Rows.Add(New Object() {"Subtract", True, "Anne"})
            DataGridView1.Rows.Add(New Object() {"Add", True, "Joe"})
            DataGridView1.Rows.Add(New Object() {"Multiply", True, "Jean"})
    
        End Sub
        Private Sub DataGridView1_CellLeave(sender As Object, e As DataGridViewCellEventArgs) _ 
            Handles DataGridView1.CellLeave
    
            If cbo IsNot Nothing Then
                If Not String.IsNullOrWhiteSpace(cbo.Text) Then
                    If Not AutoList.Contains(cbo.Text) Then
                        Dim cb = CType(DataGridView1.Columns(0), DataGridViewComboBoxColumn)
                        AutoList.Add(cbo.Text)
                        Dim items As List(Of String) = CType(cb.DataSource, String()).ToList
                        items.Add(cbo.Text)
                        Dim index = items.FindIndex(Function(x) x.ToLower = cbo.Text.ToLower)
                        cb.DataSource = items.ToArray
                        cbo.SelectedIndex = index
                    End If
                End If
            End If
    
        End Sub
        Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) _
            Handles DataGridView1.EditingControlShowing
    
            If DataGridView1.CurrentCell.IsComboBoxCell Then
                If DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex).Name = ComboColumnName Then
                    cbo = TryCast(e.Control, ComboBox)
                    cbo.DropDownStyle = ComboBoxStyle.DropDown
                    cbo.AutoCompleteMode = AutoCompleteMode.SuggestAppend
                    cbo.AutoCompleteSource = AutoCompleteSource.ListItems
                End If
            End If
        End Sub
    End Class


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by George Waters Saturday, April 7, 2018 7:43 AM
    Friday, April 6, 2018 11:52 PM
    Moderator

All replies

  • I don't see any issue with setting the middleright property as nothing happens such as you explain.

    La vida loca

    Thursday, April 5, 2018 4:10 AM
  • Hello,

    Is this dataGridViewComboboxcolumn custom or tripartite? Because I try this on datagridview at my side, and I don't see this issue.

    If it is custom, please provide some code here, it is helpful to us to reproduce your issue.

    Best Regards,

    Cherry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, April 5, 2018 5:39 AM
    Moderator
  • Hi Cherry,

    It is not a third party control, it is a windows form, these are the properties of the DataGridView I use:

            dg.EnableHeadersVisualStyles = False
            dg.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
            dg.BackgroundColor = Color.FromArgb(250, 250, 250)
            dg.ColumnHeadersHeight = 30
            dg.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(240, 240, 240)
            dg.AlternatingRowsDefaultCellStyle.SelectionForeColor = Color.Black
            dg.RowHeadersVisible = False
            dg.RowsDefaultCellStyle.BackColor = Color.FromArgb(250, 250, 250)
            dg.RowsDefaultCellStyle.SelectionForeColor = Color.Black
            dg.RowTemplate.DefaultCellStyle.SelectionBackColor = Color.FromArgb(207, 235, 252)
            dg.RowTemplate.DefaultCellStyle.SelectionForeColor = Color.Black
            dg.RowTemplate.Height = 30
            dg.CellBorderStyle = DataGridViewCellBorderStyle.None
            dg.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.None
    
            dg.ColumnHeadersDefaultCellStyle.ForeColor = Color.Black
            dg.ColumnHeadersDefaultCellStyle.BackColor = Color.White
    
            dg.DefaultCellStyle.ForeColor = Color.Black
            dg.DefaultCellStyle.SelectionForeColor = Color.Black
    
            dg.AutoGenerateColumns = False


    G.Waters

    Thursday, April 5, 2018 5:38 PM
  • Hi George,

    I believe for those trying to assist to show columns to the left or right and include the DataGridViewComboBox along with resizing the height so they can see exactly what you mean e.g. the sticking behavior.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Thursday, April 5, 2018 6:03 PM
    Moderator
  • I updated the image of my problem

    G.Waters

    Friday, April 6, 2018 9:38 PM
  • Okay, this may not be perfect but it's the best I have for time allotted. So I got the cell to be centered when not in edit mode but in edit mode no, perhaps it needs more paint overrides.

    Custom column and cell

    Public Class kpDataGridViewComboBoxColumn
        Inherits DataGridViewComboBoxColumn
    
        Public Sub New()
            CellTemplate = new kpDataGridViewComboBoxCell
        End Sub
        Public Overrides Property CellTemplate() As DataGridViewCell
            Get
                Return MyBase.CellTemplate
            End Get
            Set
                If Not (value Is Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(kpDataGridViewComboBoxCell)) Then
                    Throw New InvalidCastException("Dang something went wrong :-(")
                End If
    
                MyBase.CellTemplate = value
    
            End Set
        End Property
    
    End Class
    Public Class kpDataGridViewComboBoxCell
        Inherits DataGridViewComboBoxCell
    
        Private enabledValue as Boolean = true
        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)
    
            If Not Me.enabledValue Then
                If (paintParts And DataGridViewPaintParts.Background) = DataGridViewPaintParts.Background Then
                    Dim cellBackground As New SolidBrush(cellStyle.BackColor)
                    graphics.FillRectangle(cellBackground, cellBounds)
                    cellBackground.Dispose()
                End If
    
                If (paintParts And DataGridViewPaintParts.Border) = DataGridViewPaintParts.Border Then
                    PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
                End If
    
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText,
                             cellStyle, advancedBorderStyle, paintParts)
            Else
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText,
                             cellStyle, advancedBorderStyle, paintParts)
            End If
        End Sub
    
    End Class
    

    Code module for extension method

    Module DatagridViewExtensions
        <DebuggerStepThrough()>
        <Runtime.CompilerServices.Extension()>
        Public Function IsComboBoxCell(ByVal sender As DataGridViewCell) As Boolean
            Dim result As Boolean = False
            If sender.EditType IsNot Nothing Then
                If sender.EditType Is GetType(DataGridViewComboBoxEditingControl) Then
                    result = True
                End If
            End If
            Return result
        End Function
    End Module

    Form code. DataGridView has no columns in the designer, all created below.

    Public Class Form1
        Private AutoList As AutoCompleteStringCollection = 
                    New AutoCompleteStringCollection
    
        Private cbo As ComboBox
        Private ComboColumnName As String = "C1"
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Dim source = New String() {"Add", "Subtract", "Divide", "Multiply"}
    
            Dim DataGridViewCellStyle1 As DataGridViewCellStyle = New DataGridViewCellStyle()
            DataGridViewCellStyle1.Alignment = DataGridViewContentAlignment.MiddleCenter
    
            Dim column1 As New kpDataGridViewComboBoxColumn With
                    {
                        .DataSource = source,
                        .DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing,
                        .DefaultCellStyle =  DataGridViewCellStyle1,
                        .Name = ComboColumnName,
                        .HeaderText = "Demo",
                        .SortMode = DataGridViewColumnSortMode.NotSortable
                    }
    
            Dim column2 As New DataGridViewCheckBoxColumn With
                    {
                        .Name = "C2",
                        .HeaderText = "Col 2"
                    }
            Dim column3 As New DataGridViewTextBoxColumn With
                    {
                        .Name = "C3",
                        .HeaderText = "Col 3"
                    }
    
            AutoList.AddRange(source)
    
            DataGridView1.Columns.AddRange(New DataGridViewColumn() {column1, column2, column3})
    
            DataGridView1.Rows.Add(New Object() {"Divide", True, "Karen"})
            DataGridView1.Rows.Add(New Object() {"Add", False, "Kevin"})
            DataGridView1.Rows.Add(New Object() {"Subtract", True, "Anne"})
            DataGridView1.Rows.Add(New Object() {"Add", True, "Joe"})
            DataGridView1.Rows.Add(New Object() {"Multiply", True, "Jean"})
    
        End Sub
        Private Sub DataGridView1_CellLeave(sender As Object, e As DataGridViewCellEventArgs) _ 
            Handles DataGridView1.CellLeave
    
            If cbo IsNot Nothing Then
                If Not String.IsNullOrWhiteSpace(cbo.Text) Then
                    If Not AutoList.Contains(cbo.Text) Then
                        Dim cb = CType(DataGridView1.Columns(0), DataGridViewComboBoxColumn)
                        AutoList.Add(cbo.Text)
                        Dim items As List(Of String) = CType(cb.DataSource, String()).ToList
                        items.Add(cbo.Text)
                        Dim index = items.FindIndex(Function(x) x.ToLower = cbo.Text.ToLower)
                        cb.DataSource = items.ToArray
                        cbo.SelectedIndex = index
                    End If
                End If
            End If
    
        End Sub
        Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) _
            Handles DataGridView1.EditingControlShowing
    
            If DataGridView1.CurrentCell.IsComboBoxCell Then
                If DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex).Name = ComboColumnName Then
                    cbo = TryCast(e.Control, ComboBox)
                    cbo.DropDownStyle = ComboBoxStyle.DropDown
                    cbo.AutoCompleteMode = AutoCompleteMode.SuggestAppend
                    cbo.AutoCompleteSource = AutoCompleteSource.ListItems
                End If
            End If
        End Sub
    End Class


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by George Waters Saturday, April 7, 2018 7:43 AM
    Friday, April 6, 2018 11:52 PM
    Moderator
  • Thanks Karen, this sample gives me a light in my path

    G.Waters

    Saturday, April 7, 2018 7:44 AM