【问题标题】:How do you sort a column in a DataGridView control that contains DBNull values? VB.NET如何对包含 DBNull 值的 DataGridView 控件中的列进行排序? VB.NET
【发布时间】:2013-01-08 15:55:44
【问题描述】:

我正在尝试按包含 DBNull 值的列对 DataGridView 控件进行排序。此 DataGridView 控件绑定到 SQL Server 2012 数据库。

当我单击标题单元格(按升序排序)时,DBNull 值排在其余整数值之前,因此列中的顶部行都是空白的,然后是整数值 1 ,2,3 等按升序排列。

我该如何解决这个问题?我宁愿 DataGridView 控件对值在顶部的行进行排序,然后是 DBNulls。

我尝试在空白单元格中插入更高的值,然后对它们进行正确排序,但是当我将这些值返回给 System.DBNull.value 时,排序顺序会恢复为上述方式。

我的代码如下:

If dgv.Columns(e.ColumnIndex).Name.EndsWith("Position") Then
    intSortingRunningPosition = 1000
    dgv.Sort(baseColumn, System.ComponentModel.ListSortDirection.Ascending)
    newColumn.HeaderCell.SortGlyphDirection = Windows.Forms.SortOrder.Ascending
    For Each dr As DataGridViewRow In dgv.Rows
        If dr.Cells(e.ColumnIndex).Value Is System.DBNull.Value Then 
            dr.Cells(e.ColumnIndex).Value = intSortingRunningPosition
            intSortingRunningPosition += 1
        End If
    Next
    dgv.Sort(newColumn, System.ComponentModel.ListSortDirection.Ascending)
    For Each dr As DataGridViewRow In dgv.Rows
        If dr.Cells(e.ColumnIndex).Value >= 1000 Then
            dr.Cells(e.ColumnIndex).Value = System.DBNull.Value
        End If
    Next
End If

对不起,如果这令人困惑。谢谢!

更新:

我已修改我的代码以使用 IComparer 方法,并提出以下建议:

 Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
     Implements System.Collections.IComparer.Compare

     Dim DataGridViewRow1 As DataGridViewRow = CType(x, DataGridViewRow)
     Dim DataGridViewRow2 As DataGridViewRow = CType(y, DataGridViewRow)
     Dim CompareResult As Integer
     Dim intDGV1Cell0Value As Integer = Nothing
     Dim intDGV1Cell1Value As Integer = Nothing
     Dim intDGV2Cell0Value As Integer = Nothing
     Dim intDGV2Cell1Value As Integer = Nothing

     Try
         intDGV1Cell0Value = CInt(DataGridViewRow1.Cells(0).Value)
     Catch ex As Exception
         intDGV1Cell0Value = Int32.MaxValue
     End Try
     Try
         intDGV1Cell1Value = CInt(DataGridViewRow1.Cells(1).Value)
     Catch ex As Exception
         intDGV1Cell1Value = Int32.MaxValue
     End Try
     Try
         intDGV2Cell0Value = CInt(DataGridViewRow2.Cells(0).Value)
     Catch ex As Exception
         intDGV2Cell0Value = Int32.MaxValue
     End Try
     Try
         intDGV2Cell1Value = CInt(DataGridViewRow2.Cells(1).Value)
     Catch ex As Exception
         intDGV2Cell1Value = Int32.MaxValue
     End Try

     ' Try to sort based on the Last Name column.
     CompareResult = System.String.Compare(intDGV1Cell1Value, intDGV2Cell1Value)

     ' If the Last Names are equal, sort based on the First Name. 
         If CompareResult = 0 Then
             CompareResult = System.String.Compare(intDGV1Cell0Value, intDGV2Cell0Value)
         End If

     Return CompareResult * sortOrderModifier
 End Function

null 值现在根本不排序。关于我在这里做错了什么的任何想法?我敢肯定我有点不合时宜……

【问题讨论】:

  • 您可以使用自定义排序器,请查看 MSDN 上的示例:msdn.microsoft.com/en-us/library/ms171608.aspx
  • 我认为这条路线会导致我遇到与现在相同的问题。我已经使用了自定义排序器,但 DBNull 值似乎计数为零或小于 1,因此它们按升序排列在列表顶部(DBNull、DBNull、1、2、3),并且在列表底部按降序排列 (3,2,1,DBNull,DBNull)。
  • 如果在客户端进行排序(不是使用 SQL 查询),您可以使用 SortCompare 事件或自定义 IComparer 实现。只需将 DBNull 作为特殊情况处理(如果 lhs 是 DBNull 返回 Int32.MinValue,如果 rhs 是 DBNull 返回 Int32.MaxValue)。查看该排序方法的示例。
  • 我仍在了解如何以及在何处处理 DBNull。如果我使用 IComparer 方法,我会在公共函数比较中这样做吗?
  • 是的,看看这个帖子:stackoverflow.com/questions/4852432/…(并根据需要交换 -1 和 1)。

标签: sql-server vb.net datagridview


【解决方案1】:

您可以将bit 字段添加到名为NullValue 的数据集,对于不为空的数据列的任何条目,该字段将是0,对于任何为空的条目将是1

然后作为排序操作的一部分,按数据列本身和这个附加位列进行排序,这样空值自然会出现在排序中的非空值之后。

【讨论】:

    【解决方案2】:

    我使用 Sort(ICompare) 方法对该数据库进行排序相当不成功,因为它已绑定到外部数据集。我最终修改了我的连接字符串并重新填充了数据表。

    我的代码如下:

    If DataType = "Integer" Then
        If Column = "Vehicle Number" Then
            strConnectionStringCase = "Select * From Timing ORDER BY CAST([Class] AS NVARCHAR(MAX)) " & Direction & ", CONVERT(int, RTRIM(CAST([" & Column & "] AS NVARCHAR(MAX)))) " & Direction
        End If        
    ElseIf DataType = "DateTime" Then
        strConnectionStringCase = "Select * From Timing ORDER BY CASE WHEN [" & Column & "] is NULL THEN 1 ELSE 0 END, [" & Column & "] " & Direction
    ElseIf DataType = "String" Then
        If Column = "Vehicle Number" Then
            strConnectionStringCase = "Select * From Timing ORDER BY LEN(CAST([" & Column & "] AS NVARCHAR(MAX))) " & Direction & ", CAST([Class] AS NVARCHAR(MAX)) " & Direction & ", CAST([" & Column & "] AS NVARCHAR(MAX)) " & Direction
        End If
    End If
    

    我在标题单元格单击事件上调用此子例程。我将列名、排序方向和数据类型发送到此子例程。

    此代码还允许我根据数据类型对列进行排序。如果有字母数字字符串,我可以按照类似的顺序对它们进行排序,就好像它们只是整数一样。 DBNull 值始终放在排序的末尾。

    感谢您的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-05
      • 2021-04-26
      • 2020-02-07
      • 2015-10-12
      • 2021-09-24
      • 2020-01-24
      • 2013-10-22
      • 2015-03-23
      相关资源
      最近更新 更多