.net DataGridView排序,DateTime列中为空
我在Windows窗体应用程序中有一个DataGridView控件。有四列包含字符串数据,三列包含日期时间数据。我使用rows.Add()方法以编程方式添加行。所有列都将SortMode设置为Automatic。单击列标题进行排序只起作用,只有一个DateTime列有一些空值。当用户单击该列的标题时,它抛出ArgumentException:对象的类型必须为DateTime 我知道解决这个问题的困难方法:将所有SortModes设置为NotSortable,处理ColumnHeaderMouseClick事件并手动对整个事件进行排序。我在寻找简单的方法.net DataGridView排序,DateTime列中为空,.net,winforms,datagridview,.net,Winforms,Datagridview,我在Windows窗体应用程序中有一个DataGridView控件。有四列包含字符串数据,三列包含日期时间数据。我使用rows.Add()方法以编程方式添加行。所有列都将SortMode设置为Automatic。单击列标题进行排序只起作用,只有一个DateTime列有一些空值。当用户单击该列的标题时,它抛出ArgumentException:对象的类型必须为DateTime 我知道解决这个问题的困难方法:将所有SortModes设置为NotSortable,处理ColumnHeaderMouse
是否有一个属性或我可以设置的东西,或者其他相对简单的方法来允许此列使用空值进行排序?如果要动态添加行,我必须假设DataGridView不是数据绑定的。 在这种情况下,为什么不在填充对应的行单元格时检查空值,并实例化某种类型的伪日期(过去的一些有趣的日期,这样就可以清楚地知道它是空值-也可以指定它是默认值),以便在排序时使用它
如果这不好-如何创建与内置DataGridView完全相同的DataGridView(使用继承)但覆盖排序方法以忽略空值?更新的答案: 在查看您发布的答案后,我看到您正在检查单元格中的DBNull.Value。这可能是问题的根源,因为DBNull.Value不能强制转换为DateTime。如果以编程方式添加行,请尝试将DBNull.Value替换为null(Nothing)
原始答案: 最好在加载任何数据之前,对每个保存日期时间数据的列执行此操作:
myDateTimeColumn.ValueType = GetType(DateTime)
根据,ValueType属性“在根据列的单元格内容对列进行筛选或排序时使用”。因此,我会确保为任何允许排序的列设置它
有了这个属性集,网格可以在一个具有空值的列上排序,并将强制插入/更新的单元格转换为DateTime。下面是我提出的解决方案。DataGridView会引发SortCompare事件,您可以使用该事件输入自定义排序。我正在处理该事件,并使空值排序高于非空值(您可以轻松地使空值低于非空值)。下面是VB代码。我假设每个单元格值都是IComparable(如果不是,它将由正常的错误处理逻辑处理)
如果有人对此有任何改进,请随时发布。只是为了给这个问题添加一些代码。。。我执行了以下操作,以使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);
}
一个简单的解决方案是添加一个“tonull”函数,每次进行比较时都运行e.cellvalue1和2。如果该值为“”,则如果希望null值在排序中首先出现,则单元格的值将更改为01/01/1001;如果希望null值在排序中最后出现,则单元格的值将更改为01/01/3001或更高的值
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
你说得对,它不是数据绑定的。这是一个很好的建议,但如果可以的话,我更愿意在显示器上保留空值。我会把它作为B计划。我可以试试看。这可能不会比手动处理排序少多少工作,但至少会更有趣。这可能是一种比处理来自某个客户端对象的排序更干净的方法(WinForm类本身就是这种混乱的一个很好的候选者),谢谢您的帖子。我在设计器中定义列,而不是以编程方式,并且我有多个列。我想知道这两种差异是否可以解释不同的结果。请参阅我的最新答案。如果你发布的内容解决了你的问题,那就酷吧。但我想知道我的建议是否也适用于您。如果DataGridView是数据绑定的..SortCompare不起作用。是否有其他替代方法?如果DataGridView是数据绑定的..SortCompare不起作用。还有其他选择吗?
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