1.1 DataError事件
将DataError事件独立出来作为一个主题,是因为在操作数据时,经常会遭遇DataError事件。在操作数据时,DataError主要发生在一下情况:不能读/写或转换单元格的数据;在尝试进行某种编辑操作时发生了异常。= o ns = "urn:schemas-microsoft-com:office:office" />
编辑操作中的DataError 事件
下面的列表列出了可能会引发DataError事件的编辑操作:
§ 取消编辑(Canceling an edit) |
§ 刷新一个编辑 (通过调用RefreshEdit方法) |
|
§ 尝试将单元格的值写入数据源 |
|
§ 初始化编辑控件\单元格的值(通过设置单元格的FormattedValue属性或调用单元格的InitializeEditingControl方法)
|
|
|
DataError的上下文:
下面的列表显示了不同的DataError上下文环境,然后进一步说明了这些上下文环境合适可能发生:
DataErrorContext |
何时发生 |
Formatting |
When attempting to retrieve the cell's formatted value. |
Display |
When attempting to paint the cell or calculate the cell's tooltiptext. Note that these operations usually also require getting the cell's formatted value, so the error context is OR'd together. |
PreferredSize |
When calculating the preferred size of a cell. This |
RowDeletion |
Any exception raised when deleting a row. |
Parsing |
When exceptions occur when committing, ending or canceling an edit. Usually OR'd in with other error contexts |
Commit |
When exceptions occur when committing an edit. Usually OR'd with other error contexts |
InitialValueRestoration |
When exceptions occur while either initializing the editing control/cell's value, or Canceling an edit |
LeaveControl |
When exceptions occur while attempting to validate grid data when the grid is losing focus. Usually OR'd with other error contexts. |
CurrentCellChange |
When exceptions occur while validating\updating\committing\getting cell content when the current cell changes. Usually OR'd with other error contexts. |
Scroll |
When exceptions occur while validating\updating\committing\getting cell content when the current cell changes as a result of scrolling. |
ClipboardContent |
When exceptions occur while attempting to get the formatted value of a cell while creating the clipboard content. |
1.2 数据绑定模式(Databound modes)
1.2.1 非绑定模式(Unbound Mode)
如果你要在程序中管理数量相对较小的数据,那么非绑定模式会比较合适。此时你不是像绑定模式中那样将DataGridView控件直接指向一个数据源,而是手动去生成控件。一般需要用到DataGridViewRowCollection.Add 方法(该方法向DGV中添加行)。
非绑定模式在处理静态、只读的数据时特别有用,也可以用在以自己的方式与外部数据源交互的情况,但实际上,如果你希望你的用户与外部的数据源交互,一般还是用绑定模式(bound mode)更好。
1.2.2 绑定模式(Bound Mode)
如果你在程序中管理一些数据,并希望能与数据源自动进行交互,就应该使用绑定模式。此时你可以设置DataSource属性,将数据源绑定到DataGridView控件。如果控件使用了绑定模式,就不需要你去显式地对数据进行读写了。如果AutoGenerateColumns 属性为true,数据源中的每一列都会在DataGridView中生成一个相应的列(根据列的数据类型),如果你希望创建自己的列,可以将该属性设置为false,使用DataPropertyName属性将一列绑定到数据源的一列,这在你不想用自动生成的列类型时很有用。
1.2.2.1 有效的数据源
将数据绑定到DataGridView非常简单、直观,很多情况下,你只需要设置它的DataSource属性。如果使用的数据源包含多个列表(list)或数据表(table),你还需要设置控件的DataMember属性,该属性为字符串类型,用于指定要绑定的列表或数据表。
DataGridView控件支持标准的WinForm数据绑定模型,因此它可以绑定到下面列表中的类的实例:
· 任意实现了IList接口的类,包括一维数组;
· 任意实现了IListSource接口的类,比如DataTable和DataSet;
· 任意实现了IBindingList 接口的类,比如BindingList ;
· 任意实现了IBindingListView接口的类,比如BindingSource 。
列表更改通知(List Change Notification)
当你将数据绑定到列表时,最重要的功能之一便是支持列表更改通知了。这只有在你希望列表(即数据源)发生变化,如添加、修改和删除,DataGridView能够随之更新的时候,该功能才显得重要。只有实现了IBindingList接口的数据源支持更改通知。像数组和集合这样的列表默认情况下不支持更改通知。
在选择数据源时,BindingSource组件应该作为首选,因为它可以绑定到多种类型的数据源,并且能够自动处理很多数据绑定相关的事务。一般情况下,应该将DataGridView绑定到BindingSource组件,并将BindingSource组件绑定真正的数据源(它的作用就像DGV和数据源间的桥梁)。 BindingList<T>类也可以在一个类的基础上创建自定义列表(list)。
对象更改通知(Object Change Notification)
如果你有了一个数据源,那么数据源中的对象就可以实现对public属性的更改通知。这需要你为相应属性提供一个” PropertyNameChanged”事件,或者实现INotifyPropertyChanged接口。INotifyPropertyChanged 是在VS 2005 中新加的接口,可以与BindingList<T>一起使用来创建可绑定的列表(list)。但当你的数据源是BindingSource ,那就不用再额外实现更改通知了。
1.2.3 虚拟模式
使用虚拟模式,你可以实现自己的数据管理操作。在绑定模式下,如果要使用非绑定列,那么要想在对列排序时能够维护非绑定列的值,就需要虚拟模式。但虚拟模式的最主要的用途还是在操作大量数据时优化性能。
你将DataGridView绑定到缓存的数据,然后用代码控制数据行的存取。要保持使用内存量比较小,缓存的数据量应与当前要显示的行数相当。当用户滚动控件看到了新的行时,你的代码就从缓存中请求新的数据,并从内存中清除旧的数据。
如果你正要实现虚拟模式(Virtual Mode),需要考虑数据模型添加新行和回滚添加操作的情况。该功能准确的实现方式取决于数据模型的实现方式及其事务机制,例如,提交的时候是针对单元格还是行。参看本文档后面关于Virtual Mode的主题。
1.2.4 混合模式 – 绑定与非绑定模式
显示在DataGridView中的数据通常来自于某种类型的数据源,但是你可能也希望显示一个数据源之外的列。这种列称为非绑定列。
你可以在绑定模式下添加非绑定列,在你希望显示一个按钮列或者链接列让用户操作一些特定行时这显得很有用,另外也可以用非绑定列显示一些由绑定列计算而得到的值。你可以在CellFormatting事件处理函数中生成计算列的值。不过如果你使用的数据源是DataSet或DataTable,你可能希望使用DataColumn.Expression 属性来创建一个计算列,在这种情况下,在DGV看来,这一列就跟数据源中其它列是一样的。
在绑定模式下根据非绑定列排序是不受支持的。如果你在绑定模式下创建了非绑定列,你必须实现虚拟模式,这样在根据绑定列排序时可以维护非绑定列的值。
如果添加的非绑定列不能由数据源数据计算得来或者这些数据会频繁更新,你就应该使用虚拟模式。要了解虚拟模式的更多信息,请参看本文档后面的虚拟模式相关章节。
1.2.5 常见问题
2) How do I show data that comes from two tables?(TODO)
3) 如何显示主从表?
5) 如何避免对一列的排序?
6) 如何针对多个列排序?