【问题标题】:Retrieve Row Index From DataView using LINQ使用 LINQ 从 DataView 检索行索引
【发布时间】:2013-09-06 13:46:19
【问题描述】:

我的 DataView 的 Table 属性分配给我的 DataTables 之一。然后将 DataView 设置为我的 DataGridView 的 DataSource。像这样:

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

我的目标是对某些给定的行执行一些格式化。不幸的是,我发现这样做的唯一方法是使用 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

这是对添加到 DataGridView 中的每一行的单元格做的;它检查我的Standard 列的当前值是否等于是或否。根据结果,它将加粗/取消加粗该行。我的Available 专栏也是如此。如果可用值等于“否”,那么我将浅红色的背景颜色添加到该行。此事件被多次引发(10,000 篇文章,DataTable 大约有 10 列)。

平均约 2.2-2.7 秒


遍历 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

平均约 1.5-1.7 秒


是否可以使用 LINQ 选择 Standard 列等于“是”而 Available 列等于“否”的 RowIndex ?如果是的话,使用索引来应用格式不是比遍历整个 10,000 篇文章要快得多吗?

【问题讨论】:

    标签: vb.net linq datagridview formatting dataview


    【解决方案1】:

    我不知道使用 Link 是否是解决您问题的最佳方法。

    您应该首先尝试简化DataGridView.CellFormatting 事件中的代码。一些可能的方法:

    • 创建一个常规和粗体字体的私有实例以避免在方法中创建多个实例
    • 我猜如果第一个条件通过了,您就不需要测试第二个条件。所以If End If + If End If 可以替换为If Else End If(不需要测试这两个表达式)
    • 使用If x AndAlso y Then 代替If x And y Then:如果第一个表达式为假,则不会测试第二个表达式
    • 我不明白这个If e.RowIndex &lt;= DataSet1.Tables("dtArticles").Rows.Count - 1 Then 的目的。如果目标不是测试该行是否为 NewRowAllowUserToAddRows 属性设置为 True),则更简单

      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
    

    使用链接,你可以做这样的事情(为了你的目的,你不应该迭代到 DataView.Rows 来检索索引,而是直接在 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
    

    【讨论】:

    • 感谢您的回复。我想到了一件非常令人震惊的事情。将行加粗比更改行颜色要耗时得多。所以我稍微调整了一下并开始使用行颜色(1 个粗体行大约需要 0.3 秒......这是相当多的)。此外,当我浏览我的 DataView 时,它已经在内存中,这使得它比 DataGridView 单元格格式更快。无论如何,为单元格格式粘贴的代码是从另一个站点获得的,我没有完全构建它。再次感谢您的回复 - 非常感谢。
    • @Alex 欢迎您。我忘记在我的代码中插入字体 - 已修复。它有什么改变吗?
    • 我测试了你的解决方案,它比我以前的单元格格式略快(平均大约 20 毫秒)。虽然,DataView 解决方案快了近 1 秒。我最初想使用 LINQ 来避免通过 DataView 重新迭代......但我不知道如何做到这一点。如果我弄清楚了,我会发布答案。谢谢克里斯
    • 这正是我想要的。谢谢! :)
    • 顺便说一句...为什么通过 DataGridView 行而不是 DataView 行更好?我想知道...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多