我在Windows窗体应用程序中有一个DataGridView控件。有四列包含字符串数据,三列包含DateTime数据。我正在使用Rows.Add()方法以编程方式添加行。所有列都将SortMode设置为Automatic。单击列标题进行排序只是有效,除了一个具有一些空值的DateTime列。当用户单击该列的标题时,它会抛出ArgumentException:Object必须是DateTime类型。
我知道解决这个问题的难点:将所有SortMode设置为NotSortable,处理ColumnHeaderMouseClick事件并手动对整个事件进行排序。我正在寻找简单的方法。
是否有可以设置的属性或其他内容,或者其他一些相对简单的方法允许此列在其中使用空值进行排序?
答案 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);
}