.net 4.5
控制可以消耗大量的内存开销,除非你仔细地使用它。 在客户有限的内存,你可以避免一些这方面的开销,避免内存成本高的特性。 你也可以管理的部分或全部数据维护和检索任务自己使用虚拟模式为了定制的内存使用情况。
1.最佳实践扩展Windows窗体DataGridView控件
控制的目的是提供最大的可伸缩性。 如果你需要显示大量数据,您应该遵循的指导方针中描述这个话题避免消耗大量内存或有辱人格的用户界面(UI)的响应能力。 本主题讨论以下问题:
-
有效使用单元格样式
-
有效使用快捷菜单
-
有效地使用自动调整
-
使用选定的单元格、行和列的集合
-
使用共享的行
-
防止行成为非共享
。
类。
可以很容易地共享行实例节省内存,行成为非共享。 例如,每当用户直接与细胞相互作用,成为非共享它的行。 因为这无法避免,这一主题的指导方针是有用的只有当处理大量数据,只有当用户将与一个相对较小的数据每次运行你的程序的一部分。
控件绑定到一个外部数据源或当你实现虚拟模式,提供自己的数据源,细胞外的值存储控制,而不是在细胞对象,允许行共享。
对象只能共享一行如果可以确定所有的细胞状态的行和列的状态包含细胞。 如果你改变一个细胞的状态,这样就可以不再是推断从国家的行和列,行不能共享。
例如,一行不能共享在下列情况下:
-
的行包含一个选择单元选择的列。
-
属性集。
-
属性集。
事件。
。 使用以下指南以确保行共享:
-
收集。 这些过载自动创建专有的行。
-
房地产可以共享在下列情况下:
-
收集。
-
财产。
-
财产。
-
-
收集。
-
收集。
属性值为1。
事件确定当行成为非共享。 这是有用的调试row-sharing问题时。
为了防止行成为非共享,使用以下指南:
-
方法,操作行采取行索引参数而不是行实例。 此外,row-related事件接收事件参数处理程序对象与行属性,您可以使用它们来操纵行没有使它们成为非共享。
-
属性相反,它将使用共享的行索引1和不会检索正确的快捷菜单。
-
属性检索当前单元格的行和列索引没有直接访问单元。
-
。
-
方法,提高这些事件。
-
。 这将导致所有选定行成为非共享。
-
方法。 这种方法会导致行成为非共享。
-
。 这将导致所有行成为非共享。
-
。 这将导致所有行成为非共享。
-
财产。 这将导致所有行成为非共享。
-
方法。 排序与一个定制的比较器使所有行成为非共享。
2.虚拟模式的Windows窗体DataGridView控件
事件,使控制查找数据缓存中的值。
事件可能是唯一事件需要处理。 额外的虚拟方式事件让你使特定功能用户编辑、添加和删除行,行级的事务。
事件(如当用户添加或删除行发生的事件,或当细胞值编辑,解析,验证,或格式化的)是有用的在虚拟模式,。 你也可以处理事件,让你保持值不是通常存储在一个绑定数据源,如细胞提示文本,细胞和行错误文本,细胞和行快捷菜单数据,和行高数据。
。
属性引用主题。
。
|
事件 |
描述 |
|---|---|
|
控制使用的检索数据缓存的一个细胞值显示。 这个事件只发生在未绑定列细胞。 |
|
|
使用的控制提交用户输入一个细胞到数据缓存。 这个事件只发生在未绑定列细胞。 事件处理程序,以确保当前值显示在控制和自动分级模式目前在应用任何效果。 |
|
|
使用的控制来表示数据缓存需要一个新行。 |
|
|
连续使用的控制,以确定任何未提交的更改。 |
|
|
控制用于显示一行应该回归其缓存值。 |
属性设置。
|
事件 |
描述 |
|---|---|
|
使用的控制指示当行被删除或添加,让你更新相应数据缓存。 |
|
|
使用的控制格式的单元格值显示,解析和验证用户输入。 |
|
|
。 。 |
|
|
。 方法当你改变细胞或行错误文本,以确保当前值显示在控制。 。 |
|
|
。 |
|
|
事件处理程序,以确保当前值的显示控制。 |
3.介绍:在Windows窗体DataGridView控件中实现虚拟模式
和显式地管理控制的交互数据存储。 这允许您调整控制在这种情况下的性能。
实现虚拟模式的即时数据加载Windows窗体DataGridView控件
。
实现虚拟模式
-
控制。
方法,并提供了一个简单的表单布局在类的构造函数。
using System; using System.Windows.Forms; public class Form1 : Form { private DataGridView dataGridView1 = new DataGridView(); // Declare an ArrayList to serve as the data store. private System.Collections.ArrayList customers = new System.Collections.ArrayList(); // Declare a Customer object to store data for a row being edited. private Customer customerInEdit; // Declare a variable to store the index of a row being edited. // A value of -1 indicates that there is no row currently in edit. private int rowInEdit = -1; // Declare a variable to indicate the commit scope. // Set this value to false to use cell-level commit scope. private bool rowScopeCommit = true; [STAThreadAttribute()] public static void Main() { Application.Run(new Form1()); } public Form1() { // Initialize the form. this.dataGridView1.Dock = DockStyle.Fill; this.Controls.Add(this.dataGridView1); this.Load += new EventHandler(Form1_Load); this.Text = "DataGridView virtual-mode demo (row-level commit scope)"; } ... }
控制和填充数据存储与样本值。
private void Form1_Load(object sender, EventArgs e) { // Enable virtual mode. this.dataGridView1.VirtualMode = true; // Connect the virtual-mode events to event handlers. this.dataGridView1.CellValueNeeded += new DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded); this.dataGridView1.CellValuePushed += new DataGridViewCellValueEventHandler(dataGridView1_CellValuePushed); this.dataGridView1.NewRowNeeded += new DataGridViewRowEventHandler(dataGridView1_NewRowNeeded); this.dataGridView1.RowValidated += new DataGridViewCellEventHandler(dataGridView1_RowValidated); this.dataGridView1.RowDirtyStateNeeded += new QuestionEventHandler(dataGridView1_RowDirtyStateNeeded); this.dataGridView1.CancelRowEdit += new QuestionEventHandler(dataGridView1_CancelRowEdit); this.dataGridView1.UserDeletingRow += new DataGridViewRowCancelEventHandler(dataGridView1_UserDeletingRow); // Add columns to the DataGridView. DataGridViewTextBoxColumn companyNameColumn = new DataGridViewTextBoxColumn(); companyNameColumn.HeaderText = "Company Name"; companyNameColumn.Name = "Company Name"; DataGridViewTextBoxColumn contactNameColumn = new DataGridViewTextBoxColumn(); contactNameColumn.HeaderText = "Contact Name"; contactNameColumn.Name = "Contact Name"; this.dataGridView1.Columns.Add(companyNameColumn); this.dataGridView1.Columns.Add(contactNameColumn); this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; // Add some sample entries to the data store. this.customers.Add(new Customer( "Bon app'", "Laurence Lebihan")); this.customers.Add(new Customer( "Bottom-Dollar Markets", "Elizabeth Lincoln")); this.customers.Add(new Customer( "B's Beverages", "Victoria Ashworth")); // Set the row count, including the row for new records. this.dataGridView1.RowCount = 4; }
当前在编辑对象。
控制细胞需要油漆。
private void dataGridView1_CellValueNeeded(object sender, System.Windows.Forms.DataGridViewCellValueEventArgs e) { // If this is the row for new records, no values are needed. if (e.RowIndex == this.dataGridView1.RowCount - 1) return; Customer customerTmp = null; // Store a reference to the Customer object for the row being painted. if (e.RowIndex == rowInEdit) { customerTmp = this.customerInEdit; } else { customerTmp = (Customer)this.customers[e.RowIndex]; } // Set the cell value to paint using the Customer object retrieved. switch (this.dataGridView1.Columns[e.ColumnIndex].Name) { case "Company Name": e.Value = customerTmp.CompanyName; break; case "Contact Name": e.Value = customerTmp.ContactName; break; } }
4.对象代表行进行编辑。 这个事件发生时只要用户提交一个细胞值变化。
private void dataGridView1_CellValuePushed(object sender, System.Windows.Forms.DataGridViewCellValueEventArgs e) { Customer customerTmp = null; // Store a reference to the Customer object for the row being edited. if (e.RowIndex < this.customers.Count) { // If the user is editing a new row, create a new Customer object. if (this.customerInEdit == null) { this.customerInEdit = new Customer( ((Customer)this.customers[e.RowIndex]).CompanyName, ((Customer)this.customers[e.RowIndex]).ContactName); } customerTmp = this.customerInEdit; this.rowInEdit = e.RowIndex; } else { customerTmp = this.customerInEdit; } // Set the appropriate Customer property to the cell value entered. String newValue = e.Value as String; switch (this.dataGridView1.Columns[e.ColumnIndex].Name) { case "Company Name": customerTmp.CompanyName = newValue; break; case "Contact Name": customerTmp.ContactName = newValue; break; } }