缩放 Windows 窗体 DataGridView 控件的最佳做法

转自:http://msdn.microsoft.com/zh-cn/library/ha5xt0d9(VS.80).aspx
DataGridView
控件的设计目的是提供最大的伸缩性。如果需要显示大量数据,请遵循本主题中所描述的准则,以避免耗费大量内存或降低用户界面(UI)的响应能力。本主题讨论下列问题:
  • 有效使用单元格样式

  • 有效使用快捷菜单

  • 有效使用自动大小调整

  • 有效使用选定单元格、行和列的集合

  • 使用共享行

  • 防止行成为非共享行

如果有特殊的性能需求,您可以实现虚拟模式并提供自己的数据管理操作。有关更多信息,请参见 Windows 窗体 DataGridView 控件中的数据显示模式

有效使用单元格样式

每一个单元格、行和列都有其自己的样式信息。样式信息存储在 DataGridViewCellStyle 对象中。为许多单个 DataGridView 元素创建单元格样式对象是低效的,特别是处理大量数据时。为避免对性能的影响,请遵循以下准则:

有效使用快捷菜单

每一个单元格、行和列都有其自己的快捷菜单。DataGridView 控件中的快捷菜单由 ContextMenuStrip 控件表示。正如单元格样式对象一样,逐个地为众多 DataGridView 元素创建快捷菜单将会给性能带来负面影响。为了避免这种性能影响,请遵循以下准则:

  • 避免为单个单元格和行创建快捷菜单。这包括行模板,向控件添加新行时行模板与其快捷菜单一起被复制。为了获得最大的伸缩性,仅使用控件的 ContextMenuStrip 属性为整个控件指定同一个快捷菜单。

  • 如果有多个行或单元格需要多个快捷菜单,可处理 CellContextMenuStripNeededRowContextMenuStripNeeded 事件。这些事件使您可以自己管理快捷菜单对象,从而允许您对性能进行调整。

有效使用自动大小调整

如果单元格内容发生更改,行、列和标题可以自动调整大小,以使单元格的整个内容能够完整地显示。更改调整大小模式也可以调整行、列和标题的大小。为了确定正确的大小,DataGridView 控件必须检查每一个单元格所容纳的值。当处理大数据集时,如果发生自动大小调整,这种分析可使控件的性能下降。为了避免性能下降,请遵循以下准则:

有关更多信息,请参见 Windows 窗体 DataGridView 控件中的大小调整选项

有效使用选定单元格、行和列的集合

SelectedCells 集合的执行对于大型选择是低效的。使用 SelectedRowsSelectedColumns 集合执行效率也不高,但是程度要轻一些,因为在一个典型的 DataGridView 控件中行远远少于单元格,列远远少于行。为了避免由于使用以上集合而造成性能下降,请遵循以下准则:

使用共享行

DataGridView 控件中可通过共享行实现内存的高效使用。通过共享 DataGridViewRow 类的实例,行将共享尽可能多的有关自身外观和行为的信息。

虽然共享行实例节省内存,但是行很容易成为非共享行。例如,每当用户直接同单元格进行交互时,单元格的行成为非共享行。由于这是不能避免的,所以仅当处理大量数据,以及仅当用户在运行您的程序时与相对少的部分数据进行交互的情况下,本主题中的准则才是有用的。

如果行中的任意单元格包含值,在未绑定的 DataGridView 控件中不能共享行。当 DataGridView 控件绑定到外部数据源或当您实现虚拟模式并且提供自己的数据源时,单元格的值被存储在控件外而不是单元格对象中,因而允许行共享。

仅当行中所有单元格的状态可以由包含这些单元格的行状态和列状态确定时,行对象才能共享。如果您更改单元格状态以使其不再派生自所处行和列的状态,则不能共享行。

例如,在下列任何情况均不能共享行:

在绑定模式或虚拟模式中,您可以通过处理 CellToolTipTextNeededCellContextMenuStripNeeded 事件为每个单元格提供 工具提示和快捷菜单。

每当向 DataGridViewRowCollection 添加行时,DataGridView 控件将自动尝试使用共享行。为确保行被共享,请遵循以下准则:

  • 避免调用 System.Windows.Forms.DataGridView.Rows 集合的 Add 方法的 Add(Object[]) 重载和 Insert 方法的 Insert(Object[]) 重载。以上重载自动创建非共享行。

  • 请确保在 System.Windows.Forms.DataGridView.RowTemplate 属性中指定的行可以在以下情况中共享:

  • 请确保在调用 System.Windows.Forms.DataGridView.Rows 集合的 AddCopyAddCopiesInsertCopyInsertCopies 方法时可以共享 indexSource 参数指定的行。

  • 请确保在调用 System.Windows.Forms.DataGridView.Rows 集合的 Add 方法的 Add(DataGridViewRow) 重载、AddRange 方法、Insert 方法的 Insert(Int32,DataGridViewRow) 重载以及 InsertRange 方法时可以共享指定的行。

若要确定行是否共享,请使用 System.Windows.Forms.DataGridViewRowCollection.SharedRow(System.Int32) 方法检索行对象,然后检查该对象的 Index 属性。共享行的 Index 属性值始终为 –1。

防止行成为非共享行

共享行可以由于程序代码或用户操作而成为非共享行。为了避免对性能的影响,您应该避免使行成为非共享行。在应用程序开发过程中,可以处理 RowUnshared 事件来确定行何时成为非共享行。这在调试行共享问题时十分有用。

若要防止行成为非共享行,请遵循以下准则:

  • 避免对 Rows 集合进行索引或者避免使用 foreach 循环通过该集合进行迭代。您通常不需要直接访问行。对行进行操作的 DataGridView 方法以行索引而不是行实例作为参数。另外,与行相关的事件的处理程序接收具有行属性的事件参数对象,您可以使用行属性对行执行操作,而不会使行变为非共享行。

  • 如果需要访问行对象,请使用 System.Windows.Forms.DataGridViewRowCollection.SharedRow(System.Int32) 方法并传入行的实际索引。然而,请注意,修改一个通过此方法检索的共享行对象将修改所有共享该对象的行。但是,新记录行不与其他行共享,因此当修改任意其他行时不会影响新记录行。还应该注意到由一个共享行表示的不同的行可能有不同的快捷菜单。若要从一个被共享的行实例中检索正确的快捷菜单,请使用 GetContextMenuStrip 方法并传入行的实际索引。如果您访问共享行的 ContextMenuStrip 属性,它将使用共享行的索引值 -1 并且不检索正确的快捷菜单。

  • 避免对 System.Windows.Forms.DataGridViewRow.Cells 集合进行索引。直接访问单元格将导致其父行成为非共享行,从而实例化一个新的 DataGridViewRow。与单元格相关的事件的处理程序接收具有单元格属性的事件参数对象,您可以使用行属性对行执行操作,而不会使行变为非共享行。也可以使用 CurrentCellAddress 属性,在无需直接访问单元格的情况下检索当前单元格的行和列索引。

  • 避免基于单元格的选择模式。这些模式可导致行成为非共享行。应将 System.Windows.Forms.DataGridView.SelectionMode 属性设置为 System.Windows.Forms.DataGridViewSelectionMode.FullRowSelectSystem.Windows.Forms.DataGridViewSelectionMode.FullColumnSelect

  • 不要处理 System.Windows.Forms.DataGridViewRowCollection.CollectionChangedSystem.Windows.Forms.DataGridView.RowStateChanged 事件。这些事件可导致行成为非共享行。也不要调用引发这些事件的 System.Windows.Forms.DataGridViewRowCollection.OnCollectionChanged(System.ComponentModel.CollectionChangeEventArgs)System.Windows.Forms.DataGridView.OnRowStateChanged(System.Int32,System.Windows.Forms.DataGridViewRowStateChangedEventArgs) 方法。

  • System.Windows.Forms.DataGridView.SelectionMode 属性值是 FullColumnSelectColumnHeaderSelectFullRowSelectRowHeaderSelect 时,不要访问 System.Windows.Forms.DataGridView.SelectedCells 集合。这会导致所有选中行成为非共享行。

  • 不要调用 System.Windows.Forms.DataGridView.AreAllCellsSelected(System.Boolean) 方法。此方法会导致行成为非共享行。

  • System.Windows.Forms.DataGridView.SelectionMode 属性值是 CellSelect 时,不要调用 System.Windows.Forms.DataGridView.SelectAll 方法。这会导致所有行成为非共享行。

  • 当单元格列的相应属性设置为 true 时,不要将单元格的 ReadOnlySelected 属性设置为 false。这会导致所有行成为非共享行。

  • 不要访问 System.Windows.Forms.DataGridViewRowCollection.List 属性。这会导致所有行成为非共享行。

  • 不要调用 Sort 方法的 Sort(IComparer) 重载。使用自定义比较器排序可导致所有行成为非共享行。

请参见

posted @ 2008-05-22 10:54  武广敬  阅读(1904)  评论(1编辑  收藏  举报