DataGridView在DateTime列中使用null进行排序

时间:2009-05-15 20:37:06

标签: .net winforms datagridview

我在Windows窗体应用程序中有一个DataGridView控件。有四列包含字符串数据,三列包含DateTime数据。我正在使用Rows.Add()方法以编程方式添加行。所有列都将SortMode设置为Automatic。单击列标题进行排序只是有效,除了一个具有一些空值的DateTime列。当用户单击该列的标题时,它会抛出ArgumentException:Object必须是DateTime类型。

我知道解决这个问题的难点:将所有SortMode设置为NotSortable,处理ColumnHeaderMouseClick事件并手动对整个事件进行排序。我正在寻找简单的方法。

是否有可以设置的属性或其他内容,或者其他一些相对简单的方法允许此列在其中使用空值进行排序?

5 个答案:

答案 0 :(得分:4)

一个简单的解决方案是添加一个“tonull”函数,每次进行比较时都会运行e.cellvalue1和2。如果值为“”,那么如果您想要在排序或01/01/3001上首先显示空值,或者如果您希望它们最后出现在某个可笑的高位,则单元格的值将更改为01/01/1001那种。

Private Sub dgvTable_SortCompare(ByVal sender As Object, ByVal e As DataGridViewSortCompareEventArgs) Handles dgvTable.SortCompare

    If e.Column.Index = 4 Then

        e.SortResult = System.DateTime.Compare(todatenull(e.CellValue1), todatenull(e.CellValue2))

    End If

    e.Handled = True
End Sub


Function todatenull(ByVal cellvalue)
    If cellvalue = "" Then
        Return "01/01/1001"
    Else
        Return cellvalue
    End If
End Function

答案 1 :(得分:2)

这是我提出的解决方案。 DataGridView引发了一个SortCompare事件,您可以使用它来输入自定义排序。我正在处理该事件并使空值排序高于非空值(您可以很容易地使空值低于非空值)。这是VB代码。我假设每个单元格值都是IComparable(如果不是,它将由正常的错误处理逻辑处理。)

Try
    If e.CellValue1 Is Nothing OrElse e.CellValue1.Equals(DBNull.Value) Then
        If e.CellValue2 Is Nothing OrElse e.CellValue2.Equals(DBNull.Value) Then
            e.SortResult = 0
        Else
            e.SortResult = 1
        End If
    Else
        If e.CellValue2 Is Nothing OrElse e.CellValue2.Equals(DBNull.Value) Then
            e.SortResult = -1
        Else
            e.SortResult = DirectCast(e.CellValue1, IComparable).CompareTo(DirectCast(e.CellValue2, IComparable))
        End If
    End If
    e.Handled = True
Catch ex As Exception
    HandleError("Error sorting result grid values", ex)
    Close()
End Try

如果有人对此有任何改进,请随时发布。

答案 2 :(得分:1)

如果要动态添加行,我必须假设DataGridView不是数据绑定。 在这种情况下,为什么不在填充对应的行单元格时检查空值并实例化某种虚拟日期(过去一些有趣的日期,以便它显然是空的 - 也可以指定它是默认值)所以当谈到排序时,它会很好。

如果这不好 - 如何创建自己的DataGridView与内置的DataGridView完全相同(使用继承) BUT 覆盖排序方法以忽略空值?

答案 3 :(得分:1)

更新后的答案: 在查看您发布的答案后,我发现您正在检查单元格中的DBNull.Value。这可能是您的问题的根源,因为DBNull.Value无法强制转换为DateTime。如果您以编程方式添加行,请尝试将null替换为DBNull.Value(Nothing)。


原始答案: 尝试对每个包含DateTime数据的列执行此操作,最好在加载任何数据之前执行此操作:

myDateTimeColumn.ValueType = GetType(DateTime)

根据MSDN,ValueType属性“在根据单元格内容过滤或排序列时使用”。所以我一定会为任何允许排序的列设置它。

设置此属性后,网格可以在具有空值的列上排序,并强制插入/更新的单元格转换为DateTime。

答案 4 :(得分:0)

只是为这个问题添加一些代码......我做了以下操作,以便在存在null的情况下使DateTime(以及其他非字符串类型)正确地进行排序:

public MyFormCTor() {
    ...
    m_dataGridView.SortCompare += MySortCompare;
    ...
}

...

static void MySortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
    if (e.CellValue1 == e.CellValue2)
    {
        e.SortResult = 0;
        return;
    }

    if (e.CellValue1 == null)
    {
        e.SortResult = -1;
        return;
    }

    if (e.CellValue2 == null)
    {
        e.SortResult = 1;
        return;
    }

    e.SortResult = ((IComparable)e.CellValue1).CompareTo(e.CellValue2);
}