I have a few datagridview's, listing different bits and bobs from a mysql database.
One of them has a column called 'outcome'.
This can be either 'Yes', 'Pending' or 'No'.
I need to format this list based on that value.
I'm using the following at the moment...
Private Sub nb_myleads_dgv_CellFormattin(ByVal sender As Object, ByVal e As DataGridViewCellFormattingEventArgs) Handles nb_myleads_dgv.CellFormatting
If e.ColumnIndex = nb_myleads_dgv.Columns("outcome").Index Then
If e.Value.ToString = "Yes" Then
nb_myleads_dgv.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.DarkGreen
ElseIf e.Value.ToString = "Pending" Then
nb_myleads_dgv.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.DarkOrange
ElseIf e.Value.ToString = "No" Then
nb_myleads_dgv.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.DarkRed
End If
End sub
End If
It seem that I have to have my column 'outcome' visible in the DGV for this to work.
I have gotten around this by setting this column width to 3 pixels, but that seems a little dirty. Is it not possible to format cells in a datagridview based on the value of a hidden column?
Thanks in advance
Why not just loop through the rows with a for each and colorize based on the cell value. It won't matter if it's visible or not.
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
Select Case row.Cells(2).Value.ToString
Case "Yes"
row.DefaultCellStyle.BackColor = Color.DarkGreen
Case "Pending"
row.DefaultCellStyle.BackColor = Color.DarkOrange
Case "No"
row.DefaultCellStyle.BackColor = Color.DarkRed
End Select
End If
Next
Where in this case, column 3 (cells(2) is hidden. You would do this after populating the grid instead of in the cellformatting
I believe your problem is that cell has to be visible, otherwise it will never pass if statement.
The CellFormatting event occurs every time each cell is painted, so
you should avoid lengthy processing when handling this event. This
event also occurs when the cell FormattedValue is retrieved or its
GetFormattedValue method is called.
Link
I would get rid off this if statement and do something like this:
Dim str as string = dataGridView1.Rows[e.RowIndex].Cells["outcome"].Value.ToString
If str = "Yes" Then
nb_myleads_dgv.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.DarkGreen
ElseIf str = "Pending" Then
nb_myleads_dgv.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.DarkOrange
ElseIf str = "No" Then
nb_myleads_dgv.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.DarkRed
End If
Related
I am trying to compare two datatables, each datatable will hold a snapshot of a parts list at a point in time. So for example DT1 will show the parts as they were on the 31/3 and DT2 will show as they are on the 15/04. This will eventually need to highlight a datagridview (green is new record, red is deleted record, yellow is changed cell)
I can do (and have) this with nested for next loops but it is slow to process 1000 records.
I am presently adding a dummy field to each row in the parts list "NAAANNAA" where 'N' is field not changed and 'A' is field amended between the two DTs. 'I' for inserted and 'D' for deleted.
The paint method on the cell just has style.backcolor=color.yellow where string.instr(dgv.currentcell.columnindex)="A" (air code, not need pc at the moment)
Is there an easier way to do with Linq?
App is VB in VS2010 but soon to be either VB or C# in VS2019. Winforms with a SQL backend.
From memory elsewhere in the code it does the nested for next loops, this is just the cellformatting
--> Updated with some code
Private Sub dgvDOIssue_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgvDOIssue.CellFormatting
Dim changed_flags As String = ""
Try
If UcDOCompare1.DataGridView1.Rows.Count >= e.RowIndex Then
With UcDOCompare1.DataGridView1
changed_flags = .Rows(e.RowIndex).Cells(.Columns.Count - 1).Value
If Strings.Mid(changed_flags, e.ColumnIndex + 1, 1) = "I" Then
e.CellStyle.BackColor = Color.Green
ElseIf Strings.Mid(changed_flags, e.ColumnIndex + 1, 1) = "A" Then
e.CellStyle.BackColor = Color.Yellow
ElseIf Strings.Mid(changed_flags, e.ColumnIndex + 1, 1) = "G" Then
e.CellStyle.BackColor = Color.Pink
Else
e.CellStyle.BackColor = Color.White
End If
End With
End If
Catch ex As Exception
End Try
End sub
I'm trying to change the image of a cell inside DataGridViewImageColumn when the value of another cell is OK or NO.
I've created the column with this code
Dim NewImageProd As New DataGridViewImageColumn
NewImageProd.Image = My.Resources.Smile1
NewImageProd.Name = "IMAGE"
NewImageProd.ImageLayout = DataGridViewImageCellLayout.Zoom
NewImageProd.DisplayIndex = 0
NewImageProd.Width = 70
DGDati.Columns.Add(NewImageProd)
Later I've done the check with this code
For Idx = 0 To DGDati.RowCount - 1
Select Case DGDati("OTHERVALUE", Idx).Value.ToString
Case "OK"
DGDati.Rows(Idx).Cells("IMAGE").Value = My.Resources.Smile2
Case "NO"
DGDati.Rows(Idx).Cells("IMAGE").Value = My.Resources.Smile3
End Select
Next
Call DGDati.RefreshEdit()
But nothing happen.
What am I doing wrong?
Use DataGridView.CellFormatting event that occurs when the contents of a cell need to be formatted for display. Using this event you don't need to refresh DataGridView or data.
Private Sub DGDati_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DGDati.CellFormatting
If e.ColumnIndex = -1 Or e.RowIndex = -1 Then Exit Sub
With Me.DGDati
If .Columns(e.ColumnIndex).Name = "IMAGE" Then
If .Rows(e.RowIndex).Cells("OTHER_VALUE").Value = "OK" Then
e.Value = My.Resources.Smile2
ElseIf .Rows(e.RowIndex).Cells("OTHER_VALUE").Value = "NO"
e.Value = My.Resources.Smile3
Else
e.Value = My.Resources.Smile1
End If
End If
End With
End Sub
Also follow advice in the comments to never reuse images from Resources like that.
I Have a DataGridView with 6 column.
Column1 = "Product ID" //ReadOnly False
COlumn2 = "Product Name" //ReadOnly True - Auto Fill After Product ID Entered
COlumn3 = "Product Info" //ReadOnly True - Auto Fill After Product ID Entered
Column4 = "Price" //ReadOnly False
Column5 = "Qty" //ReadOnly False
Column6 = "Sub Total" //ReadOnly True - Auto Fill From Price*Qty
How can I only use tab on Cell where the ReadOnly set to False ? I mean, if I aleady input product ID and press "Enter", the cursor / focus move to Column4 and so move to Column5 after I hit "Enter" again in Column4 and add new row after press "Enter" again in Column5.
Allready tried others code but only works for all cell not specific cell.
http://www.vbforums.com/showthread.php?735207-DAtaGridView-move-to-next-column-automatically
Did you try this site? Sorry i cannot post to your comment section because it requires 50 reputation.
I use this so far to make it move to another cell using Enter Keys. Using code from Arsalan Tamiz Blog.
Dim celWasEndEdit As DataGridViewCell
Private _EnterMoveNext As Boolean = True
<System.ComponentModel.DefaultValue(True)>
Public Property OnEnterKeyMoveNext() As Boolean
Get
Return _EnterMoveNext
End Get
Set(ByVal value As Boolean)
_EnterMoveNext = value
End Set
End Property
Private Sub DataGridView_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.SelectionChanged
'if Enter Move Next should work andalso mouse button was NOT down
'we are checking mouse buttons because if select was changed
'by Mouse then we will NOT do our Enter Move Next
If _EnterMoveNext AndAlso MouseButtons = 0 Then
'if selection is changed after Cell Editing
If celWasEndEdit IsNot Nothing AndAlso DataGridView1.CurrentCell IsNot Nothing Then
'if we are currently in the next line of last edit cell
If DataGridView1.CurrentCell.RowIndex = celWasEndEdit.RowIndex + 1 AndAlso DataGridView1.CurrentCell.ColumnIndex = celWasEndEdit.ColumnIndex Then
Dim iColNew As Integer
Dim iRowNew As Integer
'if we at the last column
If celWasEndEdit.ColumnIndex >= DataGridView1.ColumnCount - 2 Then
iColNew = 0 'move to first column
iRowNew = DataGridView1.CurrentCell.RowIndex 'and move to next row
Else 'else it means we are NOT at the last column move to next column
iColNew = celWasEndEdit.ColumnIndex + 1
'but row should remain same
iRowNew = celWasEndEdit.RowIndex
End If
DataGridView1.CurrentCell = DataGridView1(iColNew, iRowNew) ' ok set the current column
End If
End If
celWasEndEdit = Nothing ' reset the cell end edit
End If
End Sub
And for the bypass. I use this (But i don't think its the perfect one, because if i press Left Arrow on Column 4 to move to Column 0, the focus can't move to it, maybe because i put Keys.Sender Right)
Private Sub DataGridView1_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
If DataGridView1.Columns(e.ColumnIndex).ReadOnly = True Then
SendKeys.Send("{Right}")
End If
End Sub
Every other change to the datagrid view works fine but for some reason the row color just wont change.
Ive debugged and my application goes through the loop to change the row color.
Also I have a button that gives the datagrid view a new list and colors the rows accordingly, when I click the button the row colors changes do work!
Public Sub New(measuredValues As List(Of MeasuredValuesModel), valueType As ValueType)
IsFiltered = False
' This call is required by the designer.
InitializeComponent()
MeasuredValuesList = measuredValues
uxGrid.DataSource = MeasuredValuesList
uxGrid.Columns("StepID").Visible = False
uxGrid.Font = New Font("Arial", 10, FontStyle.Bold)
For Each c As DataGridViewColumn In uxGrid.Columns
Dim Column As DataGridViewColumn = c
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
Next
If valueType = StepItem.ValueType.CalculatedValues Then
uxButtonFilter.Visible = False
uxGrid.Columns("DISPOSITION").Visible = False
End If
For Each gridRow As DataGridViewRow In uxGrid.Rows
If gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "Y" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Red
ElseIf gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "N" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Orange
End If
Next
uxStepID.Text = MeasuredValuesList.FirstOrDefault.StepID
' Add any initialization after the InitializeComponent() call.
'TODO binding
End Sub
Here is the button that works for changing row color.
Maybe it works because it's pressed after the grid has been created? Im not too sure.
Private Sub uxButtonFilter_Click(sender As Object, e As EventArgs) Handles uxButtonFilter.Click
If IsFiltered = True Then
uxGrid.DataSource = MeasuredValuesList
For Each gridRow As DataGridViewRow In uxGrid.Rows
If gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "Y" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Red
ElseIf gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "N" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Orange
End If
Next
Its the exact same loop but it seems to work fine when i use the button.
Is it possible that your datagridview isn't loaded fully when you try to recolor the rows?
Since you are setting the datasource, you should put your code that affects the grid after you can make sure that it is finished loading. The column widths change because it is not dependent on the data in the grid, but your colouring is.
Catch the uxGrid.databindingComplete event and try colouring the rows in there
NET Hi I'm new in VB NET and I'm trying to check if all values in the same row of a datagridview are the same.
Exemple :
For Each row In DataGridView1.Rows
If 'all values in row are not the same' Then
row.DefaultCellStyle.BackColor = Color.Red
End if
Next
Tell me if there is anything that you don't understand in my question ^^
Thank you in advance for your help! :P
May be better if you use handler of .RowPrepaint
private sub datagridivew_RowPrepaint(sender as Object, e as DataGridViewRowPrePaintEventArgs) Handles datagridview.RowPrePaint
if e.RowIndex >= 0 then
Dim dgvr as DataGridViewRow = DirectCast(sender, DataGridView).Rows(e.RowIndex)
if IsAllValuesAreSame(dgvr) = True Then
dgvr.DefaultCellStyle.BackColor = Color.Red
End If
End If
End Sub
Then you don't need to loop all rows one more time after all rows initialized.
And function for checking all values of row:
private function IsAllValuesAreSame(dgvr as DataGridViewRow) as Boolean
Dim distinctQnt As Int32 = (From cell As DataGridViewCell In dgvr.Cells
Where cell.ColumnIndex >= 0
Select cell.Value).Distinct().Count()
Return (distinctQnt = 1)
End Function
You need to match the value of all the cells in each row with one cell in that row to know if all cells in that row have the same value. Below, I'm giving you the simplest method to do it and I am choosing the value of the first column of each row to verify if the values of other columns in that row are equal to it. If all the columns/cells of a row don't have the same value, then that row's back color will turn red.
For x = 0 To DataGridView1.RowCount - 1
For y = 0 To DataGridView1.ColumnCount - 1
If DataGridView1.Item(y, x).Value = DataGridView1.Item(0, x).Value Then
'yes
Else
'no
DataGridView1.Rows.Item(x).DefaultCellStyle.BackColor = Color.Red
End If
Next
Next