DataGridView中的数据格式失效和排序异常问题

(原创文章·转载请注明来源:http://blog.csdn.net/hulihui)

问题与原因

DataGridView是一个功能强大的Windows Forms控件,常用于数据录入和呈现,既可以作为独立的表格数据容器,也可以绑定到数据集(如:DataSet/DataTable或实现了IBindingList接口的集合)。同时,在数据呈现时提供了单元格、表格列或表格行的格式化功能,如:对齐、字体、颜色、数据格式等,也提供了单击表格列头自动排序的能力。通常,程序中使用DataGridViewTextBoxColumn处理字符与数值型数据。实际应用时却经常碰到如下两个令人困惑的现象:
  1. 在定义表格列时设置了DefaultCellStyle的Format格式,如:两位小数数值的格式是N2,但输入数据时并没有按这个要求显示;
  2. 直接给表格某列的单元赋不同类型的值,如:dataGridView1.Rows[0].Cells[0].Value = 1、dataGridView1.Rows[1].Cells[0].Value = 1.1,此时点该列表头自动排序,将抛出异常。

1)DefaultCellStyle.Format只针对数值型数据

在DataGridView的单元格dataGridView1.Rows[1].Cells[0].Value是Object类型,可以接受任何类型的数据。如果直接录入单元格内容,那么DataGridView认为录入的数据类型为String,就不会按照格式Format的进行数据的自动格式化,也就看不到希望的格式化后的显示结果。

直接给单元格赋值也存在这个问题。如果给的值是整数、实数,可以呈现格式化的结果。如果给的值是字符文本,将保持默认的文本格式。

2)同列单元的数据类型不一致引发排序异常

如果直接给同一列的两个单元格赋不同数据类型的值,例如:整型/实型、整型/字符型,等等:
dataGridView1.Rows.Add(5);
dataGridView1.Rows[0].Cells[0] = 1;
dataGridView1.Rows[1].Cells[0] = 1.1;
上述代码中,当值为1时,单元格的ValueType为int;为1.1时,单元格的ValueType为double。那么,点击该列做自动排序时将抛出异常“对象必须是Double。”或“对象必须是Int32。”,如果赋给的是整型和字符串,则抛出异常:“对象必须是String。”或“对象必须是Int32。”其原因为,排序时要求当前列的数据类型全部相同或值为null,否则使用内置的ICompare做排序操作将抛出异常。

解决的方法

1)使用DataTable数值型字段

如果DataGridView绑定到DataTable,且指定表格列Format的字段是数值型的(Int/Double/Single/Decimal),那么显示数据时将自动格式化,排序等操作也不存在问题。此时,如果输入非数值型数据,例如:12..3,将引发DataGridView异常。

2)编辑单元格后转换为数值型

在DataGridView直接录入单元格值并离开后,将发生一系列的CellXXX事件,顺序依次为:CellLeave、CellValidating、CellParsing、CellValueChanged、CellValidated、CellEndEdit,等等。其中,在单元格的值已经变化(Changed)的情况下,单元格退出编辑模式时发生CellParsing事件,此时可以做数据类型转换和数值转换工作:
private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
decimal cellValue = 0;
string cellContent = e.Value as string; // DataGridViewTextBoxColumn保证是string类型
if (!string.IsNullOrEmpty(cellContent))
{
decimal.TryParse(cellContent, out cellValue);
}
e.Value = cellValue; // 强制转换数据类型为decimal
e.ParsingApplied = true;
}
给事件的e.Value赋值的同时,单元格的ValueType自动获得对应值的类型(上述代码为decimal)。此时,如果定义了列或单元格的数值显示格式Format,DataGridView将按该格式显示。同时,排序也不会出现类型不一致的情况。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在VB,可以使用DataGridView控件读取和写入数据到XML文件。下面是一个示例代码,演示如何实现这一功能: 1. 首先,我们需要引入System.Xml命名空间,以便使用XmlDocument和XmlNode等相关类。 ```vb Imports System.Xml ``` 2. 读取数据:将DataGridView数据读取到XML文件。 ```vb ' 创建一个XmlDocument对象 Dim xmlDoc As New XmlDocument() ' 创建根节点 Dim rootNode As XmlNode = xmlDoc.CreateElement("Data") xmlDoc.AppendChild(rootNode) ' 遍历DataGridView的每一行 For Each row As DataGridViewRow In DataGridView1.Rows ' 创建行节点 Dim rowNode As XmlNode = xmlDoc.CreateElement("Row") rootNode.AppendChild(rowNode) ' 遍历当前行的每一个单元格 For Each cell As DataGridViewCell In row.Cells ' 获取列名作为节点名 Dim columnName As String = DataGridView1.Columns(cell.ColumnIndex).Name ' 创建单元格节点 Dim cellNode As XmlNode = xmlDoc.CreateElement(columnName) cellNode.InnerText = cell.Value.ToString() ' 将单元格节点添加到行节点 rowNode.AppendChild(cellNode) Next Next ' 保存XML文件 xmlDoc.Save("data.xml") ``` 3. 写入数据:将XML文件数据写入到DataGridView。 ```vb ' 加载XML文件 xmlDoc.Load("data.xml") ' 获取根节点 Dim rootNode As XmlNode = xmlDoc.SelectSingleNode("Data") ' 遍历每一个行节点 For Each rowNode As XmlNode In rootNode.ChildNodes ' 创建新行 Dim newRow As DataGridViewRow = New DataGridViewRow() ' 遍历当前行的每一个单元格节点 For Each cellNode As XmlNode In rowNode.ChildNodes ' 获取列名 Dim columnName As String = cellNode.Name ' 获取单元格值 Dim cellValue As String = cellNode.InnerText ' 创建新单元格 Dim newCell As DataGridViewCell = New DataGridViewTextBoxCell() newCell.Value = cellValue ' 将新单元格添加到新行 newRow.Cells.Add(newCell) Next ' 将新行添加到DataGridView DataGridView1.Rows.Add(newRow) Next ``` 这样,我们就可以通过DataGridView控件实现数据的读取和写入到XML文件了。请注意,上述代码只是一个简单的示例,具体实现可能需要根据你的需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值