针对Datagridview控件装载数据时发生的错误及其解决办法
——以GNSS软件控制点编辑界面为例
2018-05-28赵睿
文/赵睿
1 引言
Datagridview是C#程序中强大的数据控件,可以以表格形式将数据显示给用户,同时允许用户在该控件上进行数据编辑。在GBC开发过程中,应用了许多Datagridview的相关功能。但当绑定数据后,DataGridView在编辑时经常会抛出异常。在此以控制点编辑界面为例,探讨Datagridview控件抛出异常的原因及解决办法。
2 Datagridview绑定数据源后常见问题及解决办法
Datagridview显示数据采用了绑定数据源,然后按照列名将各项数据显示在所需的列的方法。这种方法在绑定数据时简便易行。但是在试图对Datagridview进行编辑或者修改时碰到了诸多问题。因为datagridview占用的线程属于能够与用户交互的线程(简称UI线程)如:按钮、输入框等。这类控件为了可以随时响应用户的操作信息,处在一个类似“一直在线”的状态。为了保证线程安全以及提高代码的运行效率,微软禁止了从非创建这个控件的线程中访问这个控件。
解决该问题的办法主要有两种:一、把控件的CheckForIllegalCrossThreadCalls属性设置为false来允许不同线程对控件进行操作。但是如果采用这种办法,在有两个或多个线程操作这一控件的状态时,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。二、引用命名空间System.Threading,将涉及更新控件的代码封装成一个方法,通过Invoke或者BeginInvoke调用。
System.Threading 命名空间提供了大量可以进行多线程编程的类和接口。可以实现如获取当前进程状态,挂起线程,阻塞调用线程直至某个线程终止等多种功能。包括进度条,指定时间间隔等操作都需要引用该命名空间。这里要用到其中的Invoke()方法。Invoke方法首先检查发出调用的线程(即当前线程)是不是UI线程,如果是,直接执行委托指向的方法,如果不是,它将切换到UI线程,然后执行委托指向的方法。不管当前线程是不是UI线程,Invoke都阻塞直到委托指向的方法执行完毕,然后切换回发出调用的线程,返回。保证程序的正常运行。
3 DataGridView中数据的编辑
在编辑界面加入Datagridview控件,命名为dataGridViewX1。创建一个记录所有控制点相关信息的全局变量DataTable,命名为dt。dataGridViewX1绑定dt作为数据源。在用户对datagridview显示的数据进行编辑、删除、添加等操作时,保证该datatable的数据也进行相同操作。使datagridview与datatable始终保持同步。最后保存数据时,可以直接获得该datatable做最终的数据。
输入以下代码:MyInvoke mi = new MyInvoke(DataGridViewBound);
其中数据绑定(DataGridViewBound)中可以将之前的数据源绑定和列数据绑定添加进来。
之后,如果需要对控制点数据进行编辑修改,只要对dt进行相关修改后引用代码:
就可以实现dataGridViewX1显示的数据与dt的同步,不会因为dataGridViewX1已绑定数据而报错。
3.1 在DataGridView中实现下拉菜单
按照程序需求,在dataGridViewX1中“参考椭球”、“参考框架”和“高程系统”这三个列可以点击后出现下拉菜单,从中选择相应的选项。这三个列要求基本相同,以下以“参考椭球”列为例。
在窗体中添加comboBox控件,命名为cmbellipsoid,
作为控制点基准的“参考椭球”在数据库中是以其ID号记录的。而相关信息显示在数据表格上时则应该显示其名称。这里需要利用数据库中“Ellipsoid”表将“参考椭球”的ID号与名称关联起来。此外“Ellipsoid”表也作为cmbellipsoid的数据源。
下拉控件初始设置为不可见,在鼠标点击相应的单元格时,判断鼠标点击是否为所在列。如果符合要求,则使下拉控件在单元格内可见,大小与单元格相同。
在鼠标点击单元格事件中输入以下代码:
//获取所选单元格的值,保证在显示下拉菜单时,下拉菜单中所选的值与所选单元格的值相同,最后使下拉菜单可见
在离开单元格时,将用户已选则的选项写入dt,并使下拉菜单不可见。在鼠标离开单元格事件中添加以下代码:
如果用户在点开下拉菜单后没有进行选择,直接拖动滚动条,会看见下拉菜单始终保持在初始显示的位置,与所选单元格脱离。
在dataGridViewX1的拖动滚动条事件中添加以下代码:this.cmbellipsoid.Visible = false;保证在拖动滚动条时,下拉菜单是隐藏的。
3.2 右键菜单
在datagridview中点击右键可以显示菜单,以下以“删除”功能为例,讲解实现方法。
首先添加contextMenuStrip1控件,将dataGridViewX1的ContextMenuStrip属性设置为contextMenuStrip1。并在contextMenuStrip1控件中添加“删除”栏。在点击“删除”栏的事件中获取dataGridViewX1当前具有焦点单元格的控制点信息,删除数据库中与之相同的数据。
该方法中获得信息的当前具有焦点单元格可能会与用户实际想要删除的单元格不符。例如:鼠标选中第一行后,在第二行点击右键。第一行仍然是被选中状态,代码获取的控制点信息就是第一行的。因此,应当在dataGridViewX1的CellMouseDown事件中添加代码,保证右键点击时,鼠标所点的单元格即为焦点单元格。
4 结束语
Datagridview数据源绑定datable后按照上文方法进行了编写,程序应用达到了预期效果,界面简单易懂,操作方便。之后也在该GBC程序其他其他界面广泛应用。
物探测量需求推动着GNSS技术与数据处理的不断进步。GNSS的多种测量模式也愈加成熟。该款GNSS软件针对石油物探测量,拥有广大的应用需求。
参考文献
[1]季宇虹,王让会.全球导航定位系统GNSS的技术与应用[J].全球定位系统,2010(05):69-75.
[2]王伟.基于C#技术的对账系统设计与实现[J].科技创新与生产力,2013(09):76-79.
[3]朱瑞芳.DataGridView控件应用示例[J].电脑知识与技术,2015(25):189-191.