[RESOLVED] Example diffrent color for a specific value in a datagridviewcombobox column
Hi All,
I was trying to show items in a datagridview and couldn't find a complete solution to this problem.
Why? I wanted to visualize to the user the diffrence if they opted for certain values. In mycase certain choises would show phonenumbers on intranet.
To show how I wil leave the control names default. To recreate the the project. Start a windows form application, place a datagridview, and 2 bindingsources on the form
To start we need some data to show and a list to choose from.
To make a simple example I chosen to make a person class containing an Id, Name and PositionId
If the Position is a staff position it should be blue others should remain the default style
But lets start with the colorScheme Interface so we can store the colorscheme we want to show for a certain positionitem in the datagrdview
It wil need back and forecolors but also colors for teh item whilst selected. To show the Displaymember we want to see I've also added the toString property that should shadow the toString of the object.
Code:
Public Interface IDatagridViewColorScheme
Property ForeColor() As Color
Property BackColor() As Color
Property SelectionForeColor() As Color
Property SelectionBackColor() As Color
ReadOnly Property ToString() As String
End Interface
and a person Interface
Code:
Public Interface IPerson
Property Id() As Integer
Property Name() As String
Property PositionId() As Integer
End Interface
We need a interface for the postions as well
I know we can do without interfaces but I won't, and the IDatagridViewColorScheme
will help making this code reusable.
Code:
Public Interface IPosition
Inherits IDatagridViewColorScheme
Property Id() As Integer
Property PositionDesription() As String
Property IsManaging() As Boolean
End Interface
Next step make the objects we need:
Code:
Public Class Person
Implements IPerson
Private _Id As Integer
Private _Name As String
Private _PositionId As Integer
Public Property Id() As Integer Implements IPerson.Id
Get
Return _Id
End Get
Set(ByVal value As Integer)
_Id = value
End Set
End Property
Public Property Name() As String Implements IPerson.Name
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Public Property PositionId() As Integer Implements IPerson.PositionId
Get
Return _PositionId
End Get
Set(ByVal value As Integer)
_PositionId = value
End Set
End Property
End Class
Public Class Position
Implements IPosition
Private _Id As Integer
Private _PositionDesription As String
Private _IsManaging As Boolean
Private _ForeColor As Color
Private _BackColor As Color
Private _SelectionForeColor As Color
Private _SelectionBackColor As Color
Public Property BackColor() As System.Drawing.Color Implements IDatagridViewColorScheme.BackColor
Get
Return _BackColor
End Get
Set(ByVal value As System.Drawing.Color)
_BackColor = value
End Set
End Property
Public Property ForeColor() As System.Drawing.Color Implements IDatagridViewColorScheme.ForeColor
Get
Return _ForeColor
End Get
Set(ByVal value As System.Drawing.Color)
_ForeColor = value
End Set
End Property
Public Property SelectionBackColor() As System.Drawing.Color Implements IDatagridViewColorScheme.SelectionBackColor
Get
Return _SelectionBackColor
End Get
Set(ByVal value As System.Drawing.Color)
_SelectionBackColor = value
End Set
End Property
Public Property SelectionForeColor() As System.Drawing.Color Implements IDatagridViewColorScheme.SelectionForeColor
Get
Return _SelectionForeColor
End Get
Set(ByVal value As System.Drawing.Color)
_SelectionForeColor = value
End Set
End Property
Public Property Id() As Integer Implements IPosition.Id
Get
Return _Id
End Get
Set(ByVal value As Integer)
_Id = value
End Set
End Property
Public Property IsManaging() As Boolean Implements IPosition.IsManaging
Get
Return _IsManaging
End Get
Set(ByVal value As Boolean)
_IsManaging = value
End Set
End Property
Public Property PositionDesription() As String Implements IPosition.PositionDesription
Get
Return _PositionDesription
End Get
Set(ByVal value As String)
_PositionDesription = value
End Set
End Property
Public Shadows ReadOnly Property ToString() As String Implements IDatagridViewColorScheme.ToString
Get
Return _PositionDesription
End Get
End Property
End Class
Continue at my next post....
Re: Example diffrent color for a specific value in a datagridviewcombobox column
Now we need to build the project and do some stuff in the designer.
- Set the datasource property of bindingsource1 to the person class
- Set BindingSource2 to the positionclass.
- Set the datasource for the datagridview to bindingsource1
- choose to edit the datagridview and select the PositionIdColumn.
- Set the Columntype to datagridviewComboboxColumn
- Set the datasource for the column on bindingsource2 and select the Id for the value and the positionDescription for the displaymember of the positionIdColumn and close the columneditor
- Do some other stuff to meke the datagridview look nice (optional)
Now we need to create the data to play with
and set the bindingsources
Code:
Public Class Form1
Private _DefaultCellstyle As DataGridViewCellStyle
Private _PositionList As New List(Of Position)
Private _PersonList As New List(Of Person)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim PositionNames() As String = {"General employee", "Helpdesk employee", "Helpdesk manager", "Financial manager", "finance employee"}
Dim PersonNames() As String = {"John", "Alice", "Joe", "Sue", "Jan"}
Dim Ps As Position
Dim Pers As Person
_DefaultCellStyle = Me.DataGridView1.DefaultCellStyle.Clone
For I As Integer = 0 To 4
Ps = New Position
Ps.PositionDesription = PositionNames(I)
Ps.Id = I + 1
If Ps.PositionDesription.IndexOf("manager") >= 0 Then
Ps.IsManaging = True
'Create a special look for these items
Ps.SelectionBackColor = Color.DarkBlue
Ps.SelectionForeColor = Color.LightSkyBlue
Ps.BackColor = Color.BlanchedAlmond
Ps.ForeColor = Color.Blue
Else
'This is just to make life easy.
Ps.SelectionBackColor = _DefaultCellStyle.SelectionBackColor
Ps.SelectionForeColor = _DefaultCellStyle.SelectionForeColor
Ps.BackColor = _DefaultCellStyle.BackColor
Ps.ForeColor = _DefaultCellStyle.ForeColor
End If
_PositionList.Add(Ps)
Next
For I As Integer = 0 To 4
Pers = New Person
Pers.Name = PersonNames(I)
Pers.Id = I + 1
Pers.PositionId = I + 1
_PersonList.Add(Pers)
Next
Me.BindingSource1.DataSource = _PersonList
Me.BindingSource2.DataSource = _PositionList
End Sub
End Class
Now we need to override the DataGridViewComboBoxColumn with something we make our selves.
Code:
Imports System
Imports System.Windows.Forms
Imports System.ComponentModel
Public Class DropDownListColumn
Inherits DataGridViewComboBoxColumn
Public Sub New()
'Set the type used in the DataGridView
Me.CellTemplate = New DropDownListCell
End Sub
End Class
Public Class DropDownListCell
Inherits DataGridViewComboBoxCell
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing contol that
' the DropDownListCell uses.
Return GetType(DropDownListEditingControl)
End Get
End Property
Protected Overrides Function GetFormattedValue( _
ByVal value As Object, ByVal rowIndex As Integer, _
ByRef cellStyle As System.Windows.Forms.DataGridViewCellStyle, _
ByVal valueTypeConverter As System.ComponentModel.TypeConverter, _
ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, _
ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object
Dim ColorDefinition As IDatagridViewColorScheme
'Get object that is diplayed in the DataGridView cells with default formatting
Dim obj As Object = MyBase.GetFormattedValue( _
value, rowIndex, cellStyle, _
valueTypeConverter, formattedValueTypeConverter, _
context)
'ken de kleuren toe die voor dit item zijn gedefinieerd indien het interface IDatagridviewColumnItemColors wordt ondersteunt
If Not IsNothing(obj) Then
If TypeOf obj Is IDatagridViewColorScheme Then
ColorDefinition = CType(obj, IDatagridViewColorScheme)
cellStyle.ForeColor = ColorDefinition.ForeColor
cellStyle.BackColor = ColorDefinition.BackColor
cellStyle.SelectionBackColor = ColorDefinition.SelectionBackColor
cellStyle.SelectionForeColor = ColorDefinition.SelectionForeColor
ElseIf TypeOf obj Is ICustomTypeDescriptor Then
ColorDefinition = CType(obj.object, IDatagridViewColorScheme)
cellStyle.ForeColor = ColorDefinition.ForeColor
cellStyle.BackColor = ColorDefinition.BackColor
cellStyle.SelectionBackColor = ColorDefinition.SelectionBackColor
cellStyle.SelectionForeColor = ColorDefinition.SelectionForeColor
End If
End If
Return obj
End Function
End Class
Public Class DropDownListEditingControl
Inherits DataGridViewComboBoxEditingControl
Public Sub New()
MyBase.New()
'Set some default properties
'This will cause the DrawItem event to raise,
'allowing changes to be made to the appearance
'at run time
Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
'Make this a DropDownList
Me.DropDownStyle = ComboBoxStyle.DropDownList
End Sub
Protected Overrides Sub OnDrawItem( _
ByVal e As System.Windows.Forms.DrawItemEventArgs)
' Create a rectagle the size of the item container
Dim rec As New Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height)
Dim ColorDefinition As IDatagridViewColorScheme
If Me.Enabled Then
'If the item is being pointed to Selection it
If e.Index > -1 Then
Dim obj As Object = Me.Items(e.Index)
If TypeOf obj Is IDatagridViewColorScheme Then
ColorDefinition = CType(obj, IDatagridViewColorScheme)
If (e.State And DrawItemState.Focus) = DrawItemState.Focus Then
e.Graphics.FillRectangle(New SolidBrush(ColorDefinition.SelectionBackColor), rec)
Else
e.Graphics.FillRectangle(New SolidBrush(ColorDefinition.BackColor), rec)
End If
Else
If (e.State And DrawItemState.Focus) = DrawItemState.Focus Then
e.Graphics.FillRectangle(New SolidBrush(System.Drawing.SystemColors.Highlight), rec)
Else
e.Graphics.FillRectangle(New SolidBrush(System.Drawing.SystemColors.ControlLightLight), rec)
End If
End If
Else
If (e.State And DrawItemState.Focus) = DrawItemState.Focus Then
e.Graphics.FillRectangle(New SolidBrush(System.Drawing.SystemColors.Highlight), rec)
Else
e.Graphics.FillRectangle(New SolidBrush(System.Drawing.SystemColors.ControlLight), rec)
End If
End If
Else
'Grey out the box it is disablbed
e.Graphics.FillRectangle( _
New SolidBrush(System.Drawing.SystemColors.Control), rec)
End If
'If there is an item
If e.Index > -1 Then
Dim obj As Object = Me.Items(e.Index)
If TypeOf obj Is IDatagridViewColorScheme Then
ColorDefinition = CType(obj, IDatagridViewColorScheme)
'If the item is selected Selection it
If (e.State And DrawItemState.Focus) = DrawItemState.Focus Then
Dim SelectionedText As New SolidBrush(ColorDefinition.SelectionForeColor)
e.Graphics.DrawString(ColorDefinition.ToString, e.Font, SelectionedText, rec)
Else
Dim NormalText As New SolidBrush(ColorDefinition.ForeColor)
e.Graphics.DrawString(ColorDefinition.ToString, e.Font, NormalText, rec)
End If
Else
If (e.State And DrawItemState.Focus) = DrawItemState.Focus Then
Dim SelectionedText As New SolidBrush(System.Drawing.SystemColors.HighlightText)
e.Graphics.DrawString(obj.ToString, e.Font, SelectionedText, rec)
Else
Dim NormalText As New SolidBrush(System.Drawing.SystemColors.ControlText)
e.Graphics.DrawString(obj.ToString, e.Font, NormalText, rec)
End If
End If
Else
Dim NormalText As New SolidBrush(System.Drawing.SystemColors.ControlText)
e.Graphics.DrawString("", e.Font, NormalText, rec)
End If
End Sub
End Class
To implement this we need to build project first so intelisense knows out objects.
After these steps we need to go in the designer of the form and adjust it a bit
To implement the DataGridViewTextBoxColumn
We need to alter just 1 line from:
Me.PositionIdDataGridViewTextBoxColumn = New System.Windows.Forms.DropDownListColumn
Me.PositionIdDataGridViewTextBoxColumn = New Tutorial.DropDownListColumn
Where Tutorial should be replaced by the name of your application.
And Now our overriden DropDownListColumn is used
If we now run the application the items in the dropdown are colored the way we want
but we don't see them in the datagridview
continue in my next post
Re: Example diffrent color for a specific value in a datagridviewcombobox column
To make that happen we need to alter the code in the form to this
Code:
Public Class Form1
Private _DefaultCellstyle As DataGridViewCellStyle
Private _Initialized As Boolean
Private _PositionList As New List(Of Position)
Private _PersonList As New List(Of Person)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim PositionNames() As String = {"General employee", "Helpdesk employee", "Helpdesk manager", "Financial manager", "finance employee"}
Dim PersonNames() As String = {"John", "Alice", "Joe", "Sue", "Jan"}
Dim Ps As Position
Dim Pers As Person
_DefaultCellstyle = Me.DataGridView1.DefaultCellStyle.Clone
For I As Integer = 0 To 4
Ps = New Position
Ps.PositionDesription = PositionNames(I)
Ps.Id = I + 1
If Ps.PositionDesription.IndexOf("manager") >= 0 Then
Ps.IsManaging = True
Ps.SelectionBackColor = Color.DarkBlue
Ps.SelectionForeColor = Color.LightSkyBlue
Ps.BackColor = Color.BlanchedAlmond
Ps.ForeColor = Color.Blue
Else
'This is just to make life easy.
Ps.SelectionBackColor = _DefaultCellstyle.SelectionBackColor
Ps.SelectionForeColor = _DefaultCellstyle.SelectionForeColor
Ps.BackColor = _DefaultCellstyle.BackColor
Ps.ForeColor = _DefaultCellstyle.ForeColor
End If
_PositionList.Add(Ps)
Next
For I As Integer = 0 To 4
Pers = New Person
Pers.Name = PersonNames(I)
Pers.Id = I + 1
Pers.PositionId = I + 1
_PersonList.Add(Pers)
Next
Me.BindingSource1.DataSource = _PersonList
Me.BindingSource2.DataSource = _PositionList
End Sub
'Make sure errors while creating the form aren't shown.
Private Sub DatagridView1_DataError(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles DataGridView1.DataError
'To prevent errors
If Not _Initialized Or Me.Disposing Then
e.ThrowException = False
End If
End Sub
'We need to do some work when a row is added
'actually we need to determine what colors the cells need to be.
Private Sub DataGridView_RowsAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewRowsAddedEventArgs) Handles DataGridView1.RowsAdded
Dim RW As DataGridViewRow
Dim Cl As DataGridViewCell
Dim Tel As Person
Try
For I As Integer = e.RowIndex To e.RowIndex + e.RowCount
RW = Me.DataGridView1.Rows(I)
Cl = RW.Cells(PositionIdDataGridViewTextBoxColumn.Name)
Tel = RW.DataBoundItem
If Tel IsNot Nothing Then
Cl.Style.BackColor = _DefaultCellstyle.BackColor
Cl.Style.ForeColor = _DefaultCellstyle.ForeColor
Cl.Style.SelectionBackColor = _DefaultCellstyle.SelectionBackColor
Cl.Style.SelectionForeColor = _DefaultCellstyle.SelectionForeColor
For Each SoortTel As Position In _PositionList
'when Found duplicate the cellstyle colors to this Cell, this Is why I also filled in the default colors
'it saves some time at a crucial moment.
If SoortTel.Id = Tel.PositionId Then
Cl.Style.BackColor = SoortTel.BackColor
Cl.Style.ForeColor = SoortTel.ForeColor
Cl.Style.SelectionBackColor = SoortTel.SelectionBackColor
Cl.Style.SelectionForeColor = SoortTel.SelectionForeColor
Exit For
End If
Next
End If
Next
Catch ex As Exception
'Do whatever you want here, this is just a simple example
End Try
End Sub
'To minimize the amount of statments the validated event will only be used to set the colors
'if a cell is edited in this column, we can not set the cellstyle here as it is going to be edited.
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
Dim EditCtrl As DataGridViewComboBoxEditingControl
If TypeOf (e.Control) Is DataGridViewComboBoxEditingControl Then
'Er word een textbox in het grid geedit.
EditCtrl = e.Control
If EditCtrl.EditingControlDataGridView.CurrentCell.OwningColumn Is PositionIdDataGridViewTextBoxColumn Then
'We are in the right column
'Add a handler to the CellValidated so the cellstyle can be adjust to the value after editting.
AddHandler Me.DataGridView1.CellValidated, AddressOf DataGridView1_CellValidated
End If
End If
End Sub
'And now we set the colors for the cell
'As only the cells in the dropdownboxcolumn will
Private Sub DataGridView1_CellValidated(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)
Dim Cl As DataGridViewCell
Dim RW As DataGridViewRow
Dim Tel As Person
If e.RowIndex >= 0 Then
RW = DataGridView1.Rows(e.RowIndex)
Cl = RW.Cells(e.ColumnIndex)
Tel = RW.DataBoundItem
If Tel IsNot Nothing Then
Cl.Style.ForeColor = _DefaultCellstyle.ForeColor
Cl.Style.BackColor = _DefaultCellstyle.BackColor
Cl.Style.SelectionForeColor = _DefaultCellstyle.SelectionForeColor
Cl.Style.SelectionBackColor = _DefaultCellstyle.SelectionBackColor
For Each SoortTel As Position In _PositionList
If SoortTel.Id = Tel.PositionId Then
Cl.Style.ForeColor = SoortTel.ForeColor
Cl.Style.BackColor = SoortTel.BackColor
Cl.Style.SelectionForeColor = SoortTel.SelectionForeColor
Cl.Style.SelectionBackColor = SoortTel.SelectionBackColor
Exit For
End If
Next
End If
End If
RemoveHandler DataGridView1.CellValidated, AddressOf DataGridView1_CellValidated
End Sub
End Class
Have Fun!