Question

My DataView's Table attribute is assigned to one of my DataTables. The DataView is then set as my DataGridView's DataSource. Like so:

View.Table = DataSet1.Tables("dtArticles")
dgvArticles.DataSource = View

My goal is to perform some formatting on some given rows. Unfortunately, the only way I've found to do so is using the CellFormatting event. This is quite long since it must go through each row and verify if the row needs some formatting (bold font, backcolor).

CellFormatting

Private Sub dgvArticles_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgvArticles.CellFormatting
    Dim drv As DataRowView
    If e.RowIndex >= 0 Then
        If e.RowIndex <= DataSet1.Tables("dtArticles").Rows.Count - 1 Then
            drv = View.Item(e.RowIndex)
            Dim c As Color

            'Bolds if it is standard, makes it regular if it's not standard and already bold
            If drv.Item("Standard").ToString = "Yes" Then
                dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font = New Font("Microsoft Sans Sherif", 8, FontStyle.Bold)
            End If

            'Test if Standard is "No" and if the row is currently bold, if it is, put it back to regular
            If drv.Item("Standard").ToString = "No" And Not dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font Is Nothing Then
                If dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font.Bold Then
                    dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font = New Font("Microsoft Sans Sherif", 8, FontStyle.Regular)
                End If
            End If

            'Puts a red color to the rows who are not available
            If drv.Item("Available").ToString = "No" Then
                'Change back color
                c = Color.LightSalmon
                e.CellStyle.BackColor = c
            End If
        End If
    End If
End Sub

What this does is for each row's cells added to the DataGridView; it checks if my Standard column's current value is equal to Yes or No. Depending on the result, it will bold / un bold the row. The same principal goes for my Available column. If the Available value is equal to "No" then I put a light red back color to the row. This event is raised many times (10,000 articles with a DataTable of 10 or so columns).

About 2.2-2.7 seconds on average


Iterating through the DataView

Dim i As Integer = 0
For Each dt As BillMat.dtArticlesRow In View.Table.Rows
    If dt.Standard = "Oui" Then dgvArticles.Rows(i).DefaultCellStyle.Font = New Font("Microsoft Sans Sherif", 8, FontStyle.Bold)
    If dt.Available = "Non" Then dgvArticles.Rows(i).DefaultCellStyle.BackColor = Color.LightSalmon
    i += 1
Next

About 1.5-1.7 seconds on average


Is it possible to use LINQ to select the RowIndex of which Standard column is equal to "Yes" and which Available column is equal to "No" ? If it is, wouldn't using the index to apply the formatting be much quicker than iterating through the whole 10,000 articles?

Was it helpful?

Solution

I don't know if using Link is the best solution for your problem.

You should first try to simplify the code in DataGridView.CellFormatting event. Some possibles ways:

  • Create one private instance of regular and bold Font to avoid to create multiples instance in the method
  • I guess you don't need to test the second condition if first is passed. So If End If + If End If could be replaced to If Else End If (don't need to test the two expressions)
  • Use If x AndAlso y Then instead of If x And y Then : if first expression is false, the second won't be tested
  • I don't understand the purpose of this If e.RowIndex <= DataSet1.Tables("dtArticles").Rows.Count - 1 Then. If the goal is not test if the row is the NewRow (with AllowUserToAddRows property set to True), simplier would be this

    If DataGridView1.Rows(e.RowIndex).IsNewRow then
    

Private _RegularFont As New Font("Microsoft Sans Sherif", 8, FontStyle.Regular)
Private _BoldFont As New Font("Microsoft Sans Sherif", 8, FontStyle.Bold)

Private Sub dgvArticles_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgvArticles.CellFormatting
    Dim drv As DataRowView
    If e.RowIndex >= 0 Then
        If Not dgvArticles.Rows(e.RowIndex).IsNewRow Then
            drv = View.Item(e.RowIndex)

            'Bolds if it is standard, makes it regular if it's not standard and already bold
            If drv.Item("Standard").ToString = "Yes" Then
                dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font = _BoldFont
            Else 'First condition tested, test second 

                'Test if Standard is "No" and if the row is currently bold, if it is, put it back to regular
                If drv.Item("Standard").ToString = "No" AndAlso Not dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font Is Nothing Then
                    If dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font.Bold Then
                        dgvArticles.Rows(e.RowIndex).DefaultCellStyle.Font = _RegularFont
                    End If
                End If
            End If

            'Puts a red color to the rows who are not available
            If drv.Item("Available").ToString = "No" Then
                'Change back color
                Dim c As Color
                c = Color.LightSalmon
                e.CellStyle.BackColor = c
            End If
        End If
    End If
 End Sub

Using link, you could do something like this (for your purpose, you should not iterate into DataView.Rows to retrieve index, but directly in DataGridView.Rows):

Dim _BoldFont As New Font("Microsoft Sans Sherif", 8, FontStyle.Regular)

Dim q = From r In Me.DataGridView1.Rows 
        Where CType(r, DataGridViewRow).Cells("Standard").Value.ToString = "Oui" 
        Select r
For Each item In q
        CType(item, DataGridViewRow).DefaultCellStyle.Font = _BoldFont
Next

Dim q = From r In Me.DataGridView1.Rows 
        Where CType(r, DataGridViewRow).Cells("Available").Value.ToString = "Non" 
        Select r
For Each item In q
        CType(item, DataGridViewRow).DefaultCellStyle.BackColor = Color.LightSalmon
Next
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top