DataGridView控件使用大全目录DataGridView控件使用大全1DataGridView控件41何为DataGridView5 1.1DataGridView和DataGrid之间的区别51.2DataGridView的亮点62DataGridVie w的结构62.1结构元素(ArchitectureElements)72.2单元格和组(CellsandBands)72 .3DataGridView的单元格(DataGridViewCell)72.3.1DataGridViewCell的工作机 制72.3.2常见问题82.4DataGridView的列(DataGridViewColumn)92.5DataGridV iew的编辑控件(EditingControls)92.6DataGridViewRow92.6.1常见问题103列/单元 格类型揭密(column/celltypes)103.1DataGridViewTextBoxColumn113.1.1常见 问题113.2DataGridViewCheckBoxColumn113.3DataGridViewImageColumn11 3.3.1常见问题113.4?DataGridViewButtonColumn123.5DataGridViewComboBo xColumn123.5.1DataError事件和ComboBox列123.5.2常见问题123.6DataGridVie wLinkColumn124操作数据(WorkingwithData)134.1数据输入和验证的相关事件134.1.1数 据验证相关事件的顺序134.1.2验证数据144.1.3在新行中的数据输入(DataEntryintheNewRow )144.2关于Null值164.2.1NullValue属性164.2.2DataSourceNullValue属性164 .3DataError事件17DataError的上下文:174.4数据绑定模式(Databoundmodes)184.4. 1非绑定模式(UnboundMode)184.4.2绑定模式(BoundMode)184.4.3虚拟模式194.4.4 混合模式–绑定与非绑定模式194.4.5?常见问题195特性综览(Overviewoffeatures)205.1样式( Styling)205.1.1TheDataGridViewCellStyleClass205.1.2UsingData GridViewCellStyleObjects215.1.3StyleInheritance225.1.4Setting StylesDynamically245.2Custompainting245.2.1PaintParts255.2. 2RowPrePaintandPostPaint265.3Autosizing265.3.1?SizingOpti onsintheWindowsFormsDataGridViewControl275.3.2Resizingwit htheMouse295.3.3AutomaticSizing295.3.4ProgrammaticResizing3 05.3.5CustomizingContent-basedSizingBehavior315.3.6Content-b asedSizingOptions315.4Selectionmodes315.4.1ProgrammaticSele ction325.5滚动(Scrolling)335.5.1Scrollevent335.5.2Scrollbars33 5.5.3ScrollingProperties335.6Sorting335.6.1ProgrammaticSorti ng345.6.2CustomSorting355.6.3?Commonquestionsandscenarios355 .7Borderstyles365.7.1StandardBorderStyles365.7.2AdvancedBo rderStyles365.8Enter-Editmodes375.9Clipboardcopymodes385.10 Frozencolumns/rows395.11ImplementingCustomcellsandediting controls/cells395.11.1IDataGridViewEditingControl395.11.2IDataG ridViewEditingCell395.12Virtualmode395.12.1BoundModeandVirt ualMode405.12.2SupplementingBoundMode405.12.3Commonquestion sandscenarios405.12.4ReplacingBoundMode405.12.5Virtual-Mode Events405.12.6BestPracticesinVirtualMode425.13容量(Capacity) 426最佳实践(BestPractices)426.1UsingCellStylesEfficiently426.2U singShortcutMenusEfficiently436.3UsingAutomaticResizingEff iciently436.4UsingtheSelectedCells,Rows,andColumnsCollect ionsEfficiently446.5UsingSharedRows446.6PreventingRowsfrom BecomingUnshared455.1.3样式继承471。DataGridViewCell.Style485.1.4设置 样式动态495.2风俗画495.2.1油漆件495.3Autosizing505.3.2用鼠标调整大小525.3.3自动调整大小 525.3.5自定义基于内容的调整大小行为535.3.6基于内容的调整大小选项535.4选择模式545.4.1编程选择545.5滚 动(滚动)545.5.1Scroll事件545.5.2滚动条555.5.3滚动属性555.6排序55DataGridViewCo lumnSortMode值描述555.6.2自定义排序565.7.1标准边框样式565.10冻结的列/行585.11实现自定义和编 辑控制细胞/细胞585.11.1IDataGridViewEditingControl595.11.2IDataGridVie wEditingCell595.12虚拟模式595.12.1绑定模式和虚拟模式595.12.2补充绑定模式595.12.5虚拟模式 事件59CellContextMenuStripNeeded60RowHeightInfoNeeded605.12.6在虚拟模式下 的最佳实践615.13容量(容量)616个最佳实践(最佳做法)616.1使用高效单元格样式616.2使用高效快捷菜单616.3使用 自动调整大小高效616.5使用共享行626.6防止行成为非共享63附录A–FAQ641.如何使指定的单元格不可编辑?642 .如何让一个单元格不可用(disable)?64DataGridViewDisableButtonCellcell=65So lidBrushcellBackground=663.如何避免用户将焦点设置到指定的单元格?674.如何使所有单元格总是显 示控件(不论它是否处于编辑状态)?675.Whydoesthecelltextshowupwith“square ”characterswheretheyshouldbenewlines(TODO,未能实现该效果)?676.如何 在单元格内同时显示图标和文本?677.如何隐藏一列?718.如何避免用户对列排序?719.如何针对多个列排序?71Compa reResult=System.String.Compare(7810.如何为编辑控件添加事件处理函数?7811.应在何时 移除编辑控件的事件处理函数?7812.如何处理ComboBox列中控件的SelectIndexChanged事件?7813.如 何通过拖放调整行的顺序?7914.如何调整最后一列的宽度使其占据网格的剩余客户区?8115.如何让TextBox类型的单元格支 持换行?8116.如何使Image列不显示任何图像(字段值为null时)?8217.如何能够在ComboBox类型的单元格中输 入数据?8218.HowdoIhaveacomboboxcolumndisplayasubsetofd atabaseduponthevalueofadifferentcomboboxcolumn(TODO)?83 19.如何在用户编辑控件的时候(而不是在验证时)就显示错误图标?8420.如何同时显示绑定数据和非绑定数据?8721.How doIshowdatathatcomesfromtwotables(TODO)?8922.如何显示主从表?89 MessageBox.Show("Torunthisexample,replacethevalueofthe" +9223.如何在同一DataGridView中显示主从表?9224.如何避免用户对列排序?9225.如何在点击工具栏按钮的 时候将数据提交到数据库?9226.如何在用户删除记录时显示确认对话框?92DataGridView控件DataGridView是 用于WindowsFroms2.0的新网格控件。它可以取代先前版本中DataGrid控件,它易于使用并高度可定制,支持很多我们 的用户需要的特性。关于本文档:本文档不准备面面俱到地介绍DataGridView,而是着眼于深入地介绍一些技术点的高级特性。本文档 按逻辑分为5个章节,首先是结构和特性的概览,其次是内置的列/单元格类型的介绍,再次是数据操作相关的内容,然后是主要特性的综述,最后 是最佳实践。大部分章节含有一个“Q&A”部分,来回答该章节相关的一些常见问题。注意,某些问题会由于知识点的关联性重复出现在多个 章节。这些问题、答案及其附带的示例代码都包含在本文档的附录部分。?1何为DataGridView通过DataGridView控件, 可以显示和编辑表格式的数据,而这些数据可以取自多种不同类型的数据源。DataGridView控件具有很高的的可配置性和可扩展性,提 供了大量的属性、方法和事件,可以用来对该控件的外观和行为进行自定义。当你需要在WinForm应用程序中显示表格式数据时,可以优先考 虑DataGridView(相比于DataGrid等其它控件)。如果你要在小型网格中显示只读数据,或者允许用户编辑数以百万计的记录 ,DataGridView将为你提供一个易于编程和良好性能的解决方案。DataGridView用来替换先前版本中的DataGri d,拥有较DataGrid更多的功能;但DataGrid仍然得到保留,以备向后兼容和将来使用。如果你要在两者中选择,可以参考下面给 出的DataGrid和DataGridView之间区别的细节信息。1.1DataGridView和DataGrid之间的区别 DataGridView提供了大量的DataGrid所不具备的基本功能和高级功能。此外,DataGridView的结构使得它较之 DataGrid控件更容易扩展和自定义。下表描述了DataGridView提供而DataGrid未提供的几个主要功能。DataGr idView功能描述多种列类型与DataGrid相比,DataGridView提供了更多的内置列类型。这些列类型能够满足大部分常 见需要,而且比DataGrid中的列类型易于扩展或替换。多种数据显示方式DataGrid仅限于显示外部数据源的数据。而DataGr idView则能够显示非绑定的数据,绑定的数据源,或者同时显示绑定和非绑定的数据。你也可以在DataGridView中实现virt ualmode,实现自定义的数据管理。用于自定义数据显示的多种方式DataGridView提供了很多属性和事件,用于数据的格式化 和显示。比如,你可以根据单元格、行和列的内容改变其外观,或者使用一种类型的数据替代另一种类型的数据。用于更改单元格、行、列、表头外 观和行为的多个选项DataGridView使你能够以多种方式操作单个网格组件。比如,你可以冻结行和列,避免它们因滚动而不可见;隐藏 行、列、表头;改变行、列、表头尺寸的调整方式;为单个的单元格、行和列提供工具提示(ToolTip)和快捷菜单。唯一的一个DataG rid提供而DataGridView未提供的特性是两个相关表中数据的分层次显示(比如常见的主从表显示)。你必须使用两个DataGr idView来显示具有主从关系的两个表的数据。1.2DataGridView的亮点下表着重显示了DataGridView的主要特 性,稍后会介绍它们的详细信息。DataGridView控件特性描述多种列类型DataGridView提供有TextBox、Chec kBox、Image、Button、ComboBox和Link类型的列及相应的单元格类型。多种数据显示方式DataGrid仅限于显 示外部数据源的数据。而DataGridView则能够显示非绑定的数据,绑定的数据源,或者同时显示绑定和非绑定的数据。你也可以在Da taGridView中实现virtualmode,实现自定义的数据管理。自定义数据的显示和操作的多种方式DataGridView 提供了很多属性和事件,用于数据的格式化和显示。此外,DataGridView提供了操作数据的多种方式,比如,你可以:对数据排序,并 显示相应的排序符号(带方向的箭头表示升降序)对行、列和单元格的多种选择模式;多项选择和单项选择以多种格式将数据拷贝到剪贴板,包括t ext,CSV(以逗号隔开的值)和HTML改变用户编辑单元格内容的方式用于更改单元格、行、列、表头外观和行为的多个选项Dat aGridView使你能够以多种方式操作单个网格组件。比如,你可以:冻结行和列,避免它们因滚动而不可见;隐藏行、列、表头;改变行、 列、表头尺寸的调整方式;改变用户对行、列、单元格的选择模式;为单个的单元格、行和列提供工具提示(ToolTip)和快捷菜单。自定义 单元格、行和列的边框样式。提供丰富的可扩展性的支持DataGridView提供易于对网格进行扩展和自定义的基础结构,比如:处理自定 义的绘制事件可以为单元格、列和行提供自定义的观感;继承一个内置的单元格类型以为其提供更多的行为;实现自定义的接口以提供新的编辑体验 。2DataGridView的结构DataGridView及其相关类被设计为用于显示和编辑表格数据式数据的灵活的、可扩展的体系。 这些类都位于system.Windows.Forms命名空间,它们的名称也都有共同的前缀"DataGridView"。2.1结构 元素(ArchitectureElements)主要的DataGridView相关类继承自DataGridViewElement 类。DataGridViewElement类有两个属性,一是DataGridView,该属性提供了对其所属的DataGridVie w的引用;二是State,该属性表示当前的状态,其值为DataGridViewElementStates枚举,该枚举支持位运算,这 意味着可以设置组合状态。2.2单元格和组(CellsandBands)DataGridView由两种基本的对象组成:单元格( cell)和组(band)。所有的单元格都继承自DataGridViewCell基类。两种类型的组(或称集合)DataGridV iewColumn和DataGridViewRow都继承自DataGridViewBand基类,表示一组结合在一起的单元格。Da taGridView会与一些类进行互操作,但最常打交道的则是如下三个:DataGridViewCell,DataGridView Column,DataGridViewRow。2.3DataGridView的单元格(DataGridViewCell)单元格 (cell)是操作DataGridView的基本单位。Displayiscenteredoncells,anddata entryisoftenperformedthroughcells。可以通过DataGridViewRow类的Cel ls集合属性访问一行包含的单元格,通过DataGridView的SelectedCells集合属性访问当前选中的单元格,通过Da taGridView的CurrentCell属性访问当前的单元格。DataGridViewCell?类图Cell?相关类和属性Da taGridViewCell是一个抽象基类,所有的单元格类型都继承于此。DataGridViewCell及其继承类型并不是Wind owsForms控件,但其中一些宿主于WindowsForms控件。单元格支持的编辑功能通常都由其宿主控件来处理。DataGr idViewCell对象不会像WindowsForms控件那样控制自己的外观和绘制(painting)特征,相反的,DataGr idView会负责其包含的单元格的外观。通过DataGridView控件的属性和事件,你可以深刻地影响单元格的外观和行为。如果你 对单元格定制有特殊要求,超出了DataGridView提供的功能,可以继承DataGridViewCell或者它的某个子类来满足这 些要求。2.3.1DataGridViewCell的工作机制理解DataGridView结构的一个重要部分是理解DataGrid ViewCell的工作机制:单元格的值(ACell’sValue)单元格的值是其根本所在。如果单元格所在列不是绑定列,并且所在 的DataGridView也不是VirtualMode,那么它的值就由它本身所持有并维护。对于那些由绑定产生的单元格,它们压根儿 就不“知道”该持有什么值,当然也就不会去维护了;当DataGridView需要单元格的值的时候,它会到数据源中查询该单元格应当显示 的值。在VirtualMode下,除了会触发CellValueNeeded事件以获取相应单元格的值外,与数据绑定方式非常相似。在 单元格级,所有这些由DataGridViewCell.GetValue()方法来控制。默认情况下,单元格的值的类型为object 。当一个列被绑定后,会设置它的ValueType属性,它包含的单元格的ValueType也随之更新。而单元格的ValueType对 于下一步的格式化非常重要。格式化显示(FormattingforDisplay)注意:当DataGridView需要了解“如何 显示这个单元格”时,它需要的是单元格的FormattedValue?,而不是Value。这是一个复杂的过程,因为格式化屏幕上的一些 内容通常需要将它转换为字符串。例如,尽管你将单元格的值(Value)设置为整型值155,在显示它的时候仍需要将其格式化。单元格和其 所在的列的FormattedValueType属性决定了显示它时所用的类型。多数列使用字符串类型,而Image和CheckBox 类型的单元格/列则使用其它类型。Image类型的单元格和列使用Image作为默认的FormattedValueType,它的内置实 现了解如何去显示一个Image。CheckBox类型的单元格/列的FormattedValueType属性则取决于属性ThreeS tate的值。在单元格级,所有这些由DataGridViewCell.GetFormattedValue()控制。默认情况下,Da taGridView使用TypeConverter将单元格的值(Value)转换为格式化的值(FormattedValue)。Da taGridView会基于单元格的ValueType和FormattedValueType属性来获取合时的TypeConverte r。对于一个单元格,FormattedValue会得到多次请求(即会在多个地方用到):绘制单元格的时候,所在列根据单元格内容自动调 整大小的时候,甚至是在判断鼠标是否经过单元格内容时。每次需要FormattedValue的时候,DataGridView会触发Ce llFormatting事件,这时你就有机会修改单元格的格式化显示了。如果单元格不能获取它的格式化值,它会触发DataError事 件。格式化显示单元格还包含以怎样的首选尺寸显示它。这个首选尺寸是由单元格的FormattedValue,填充区域(padding) ,附加显示和边框合并而成。绘制单元格的显示(PaintingtheDisplay)在获得FormattedValue后,单元 格将负责绘制它的内容。单元格决定了绘制过程所使用的正确样式(参见本文档第五章的样式部分)并进行绘制。记住:如果单元格不去绘制自己, 那么该单元格将不会有任何内容得到绘制(即单元格的绘制只由它自己负责),行、列不会负责绘制任何内容,因此要确保至少要绘制单元格的背景 (background),否则单元格所在的矩形区域仍然是无效的(即未经绘制)。解析单元格的显示(ParsingtheDispl ay)用户开始与单元格交互后,可能会编辑单元格的值。有一件事要记住,用户编辑的实际上是单元格的FormattedValue。用户提 交所编辑的值时,FormattedValue需要转换回单元格的值(Value),这个过程称为解析(parsing)。在单元格级上, 所有这些工作由单元格的DataGridViewCell.ParseFormattedValue(int?rowIndex)方法控 制。默认情况下,会再次使用TypeConverter来将FormattedValue解析为单元格的真实值,这时会触发DataGri dView的CellParsing事件,这时你就有机会修改单元格的解析方式了。.如果单元格不能得到正确地解析,会触发DataErr or事件。2.3.2常见问题1)?http://www.cnblogs.cc2/如何使指定的单元格不可编辑?2)?http:// www.cnblogs.cc2/如何让一个单元格不可用(disable)?3)?http://www.cnblogs.cc2/如何 避免用户将焦点设置到指定的单元格?4)?http://www.cnblogs.cc2/如何使所有单元格总是显示控件(不论它们是否处 于编辑状态)?5)?http://www.cnblogs.cc2/Whydoesthecelltextshowupw ith“square”characterswheretheyshouldbenewlines?6)?http:// www.cnblogs.cc2/如何在单元格内同时显示图标和文本?2.4DataGridView的列(DataGridViewC olumn)DataGridView所附带的数据(这些数据可以通过绑定或非绑定方式附加到控件)的结构表现为DataGridView 的列。你可以使用DataGridView的Columns集合属性访问DataGridView所包含的列,使用SelectedCol umns集合属性访问当前选中的列。DataGridViewColumn?类图Column?相关类和属性一些主要的单元格类型拥有相 应的列类型,这些列类型继承自DataGridViewColumn基类。常见问题:1)?http://www.cnblogs.cc2 /如何隐藏一列?2)?http://www.cnblogs.cc2/如何避免用户对列排序?3)?http://www.cnblog s.cc2/如何针对多个列排序?2.5DataGridView的编辑控件(EditingControls)支持高级编辑功能的单 元格一般都使用一个继承自WindowsForms控件的宿主控件,这些控件同时也实现了IDataGridViewEditingCo ntrol接口。DataGridViewEditingControlClassdiagramClassesthatim plementEditingControls下表说明了单元格类型、列类型、编辑控件间的关系:单元格类型宿主控件列类型DataG ridViewButtonCelln/aDataGridViewButtonColumnDataGridViewCheckBoxC elln/aDataGridViewCheckBoxColumnDataGridViewComboBoxCellDataGridV iewComboBoxEditingControlDataGridViewComboBoxColumnDataGridViewIm ageCelln/aDataGridViewImageColumnDataGridViewLinkCelln/aDataGridV iewLinkColumnDataGridViewTextBoxCellDataGridViewTextBoxEditingCon trolDataGridViewTextBoxColumn常见问题(FAQ)1)?http://www.cnblogs.cc2/如 何为编辑控件添加事件处理函数?2)?http://www.cnblogs.cc2/应在何时移除编辑控件的事件处理函数?3)?htt p://www.cnblogs.cc2/如何处理ComboBox列中Combox控件的SelectIndexChanged事件?4 )?http://www.cnblogs.cc2/如何使所有单元格总是显示控件(不论它是否处于编辑状态)?2.6DataGrid ViewRowDataGridViewRow类用于显示数据源的一行数据。可以通过DataGridView控件的Rows集合属性来访 问其包含的行,通过SelectedRows集合属性访问当前选中的行。DataGridViewRow类图Row相关的类和属性你可以继 承DataGridViewRow类来实现自己的行类型,虽然多数情况下这并不必要。DataGridView有几个行相关的事件和属性 ,用以自定义其包含的DataGridViewRow对象的行为。如果你将DataGridView的AllowUserToAddRow s属性设为true,一个专用于添加新行的特殊行会出现在最后一行的位置上,这一行也属于Rows集合,但它有一些需要你提起注意的特殊功 能,要获得这方面的更多信息,请参看4.1.3节。2.6.1常见问题1)?http://www.cnblogs.cc2/如何通过拖 放调整行的顺序?3列/单元格类型揭密(column/celltypes)DataGridView控件提供了几种列类型用以显示数 据,并允许用户修改和添加数据。当你对DataGridView进行了绑定,并将它的AutoGenerateColumns属性设置为t rue,它会根据数据源中列的数据类型自动生成列,这些列都使用相应的默认类型(与数据源列数据类型相适应)。你也可以自行创建列的实例, 将它们加入DataGridView的Columns集合中,这些列可用作非绑定列,也可以以手动方式让它们用于绑定数据。手动绑定的列非 常有用,比如,自动生成的列都采用与数据源的列相应的默认类型,而你不想用默认列类型。下表描述了DataGridView的各种列对应 的类:列类型描述DataGridViewTextBoxColumn用于基于文本的值。绑定到数字和字符串值时会自动生成这种类型的列。 DataGridViewCheckBoxColumn用于显示Boolean和CheckState类型的值,绑定到上述类型值时会自动 生成这种类型的列。DataGridViewImageColumn用于显示图像。绑定到byte数组,Image对象,图标对象时会自动 生成这种类型的列。DataGridViewButtonColumn用于在单元格内显示按钮。在绑定时不会自动生成,一般用于非绑定列。 DataGridViewComboBoxColumn用于在单元格内显示下拉列表。在绑定时不会自动生成,一般地需要手工绑定。Data GridViewLinkColumn用于在单元格内显示链接。在绑定时不会自动生成,一般地需要手工绑定。自定义列类型通过继承Data GridViewColumn类或其子类,你可以创建自己的列类型,以提供自定义的外观、行为和宿主控件。常见问题(FAQ)1)?ht tp://www.cnblogs.cc2/如何隐藏一列?2)?http://www.cnblogs.cc2/如何使特定的单元格不可 编辑?3)?http://www.cnblogs.cc2/如何避免用户将焦点设置到指定的单元格?4)?http://www.cnb logs.cc2/如何调整最后一列的宽度使其占据网格的剩余客户区?3.1DataGridViewTextBoxColumnDat aGridViewTextBoxColumn是一种通用的列类型,用于表示基于文本的值,比如数字和字符串。在编辑模式下,会有一个Te xtBox控件出现在当前活动单元格,用户可以修改单元格的值。单元格的值在显示时会自动转换为字符串。用户输入或修改的值在提交时则被自 动解析为合适的数据类型以创建一个单元格的值。通过处理CellFoamatting和CellParsing事件,你可以自定义这些转换 的方式。比如将数据源的日期字段以特定的形式显示,对某些特殊单元格作出特殊的标记。对一列来说,它包含的单元格值的数据类型由该列的Va lueType属性指定。3.1.1常见问题1)?http://www.cnblogs.cc2/如何让TextBox类型的单元格支 持换行?2)?http://www.cnblogs.cc2/Whydoesthecelltextshowupwith “square”characterswheretheyshouldbenewlines?3)?http://www .cnblogs.cc2/如何在单元格内同时显示图标和文本?4)?http://www.cnblogs.cc2/如何避免用户将焦点 设置到指定的单元格?3.2DataGridViewCheckBoxColumnDataGridViewCheckBoxColum n用于显示Boolean或CheckState类型的值。Boolean值显示为二元(two-state)或三元(three-s tate)的CheckBox,而这取决于该列的ThreeState属性的值。如果该类型的列绑定到CheckState类型的值, ThreeState属性的默认值为true。一般情况下,CheckBox类型的单元格要么用于存储数据,就像其它类型的数据一样,要么 用于进行一些重要操作。用户点击CheckBox单元格时,如果你希望对此立即做出反应,可以处理CellClick事件,但该事件发生在 单元格的值更新之前。如果点击之时就希望获得新值,一种选择是根据当前值计算点击后的值;另一种方法是立即提交值的变化,然后在CellV alueChanged事件处理函数中对此作出反应,而要在用户点击单元格时立即提交值的变化,你必须处理CurrentCellDirt yStateChanged事件,在这里,调用CommitEnd方法提交新值。3.3DataGridViewImageColumn DataGridViewImageColumn类型的列用于显示图像。这种类型的列有三种方法生成:绑定到数据源时自动生成;为非绑定 列手动生成;在CellFormatting事件处理函数(该事件发生在单元格显示前)中动态生成。绑定到数据源时自动生成Image列的 方法适用于大量的图像格式,包括.NET中Image类支持的各种格式,还有Access数据库及Northwind范例数据库使用的OL E图片格式。如果你想提供DataGridViewButtonColumn列的功能,又希望显示自定义的外观,手动生成Image列会很 有用。在显示后,你可以处理CellClick事件以处理用户对单元格的点击(模拟按钮列)。如果你要为计算值或非图片的值提供图片显示, 在CellFormatting事件处理函数中动态生成Image列的方法会很有用。比如,你有一个表示风险值的列,它的值可能是”hig h”、”middle”或”low”,可以为它们显示不同的图标作为警示;或者你有一个名为”Image”的列,它的值时图片文件的位置而 不是真实的图片内容,也可以用这种方法。3.3.1常见问题1)?http://www.cnblogs.cc2/如何使Image列不 显示任何图像(字段值为null时)?3.4?DataGridViewButtonColumn使用DataGridViewButto nColumn列,可以在单元格内显示按钮。如果你要为用户操作特定行提供一种简单的方式,Button列会很有用,比如排序或在另一个 窗体中显示子表记录。在对DataGridView进行数据绑定时不会自动生成Button列,所以你必须手动创建它们,然后把它们添加到 DataGridView控件的Columns集合中。你可以处理CellClick事件以响应用户的点击动作。3.5DataGrid ViewComboBoxColumn在DataGridViewComboBoxColumn类型的列中,你可以显示包含下拉列表的单元 格。这在仅允许用户输入一些特定值的时候显得很有用,比如在SQLServer示例数据库Northwind中Products表的Ca tegory列,它表示产品的种类,这个应只允许选择现有的产品种类,此时就可以使用ComboBox列。如果你了解如何为ComboBo x控件生成下拉列表,就可以用相同的方式为ComboBox列中的所有单元格生成下拉列表。要么通过列的Items集合手动添加,要么通过 DataSource,DisplayMember和ValueMember属性绑定到一个数据源。要了解其中的更多信息,可以参考Wi nForms中ComboBox空间的用法。你可以将ComboBox列的单元格的实际值绑定到DataGridView控件本身的数据源 (注意不是ComboBox列的数据源),这需要设置该列的DataPropertyName属性(设置某个列的名称)。ComboBox 列不会在数据绑定时自动生成,所以你必须手动创建它们,然后将其添加到Columns集合属性中。另外,你也可以使用设计器,在设计时设置 相应的属性,这个过程类似于在设计器中ComboBox控件的使用。3.5.1DataError事件和ComboBox列在使用Dat aGridViewComboBoxColumn时,有时会修改单元格的值或启动ComboBox控件的Items集合,这样可能会引发 DataError事件。这是ComboBox列的设计使然,ComboBox列的单元格会进行数据验证。在ComboBox列的单元格尝 试绘制包含的内容时,它需要将包含的值进行格式化(见第二章第三节),在此转换过程中,它会在ComboBox的Items集合中查找对应 的值,如果查找失败,就会引发DataError事件。忽略了DataError事件可能会使单元格不能进行正确的格式化。3.5.2常 见问题1)?http://www.cnblogs.cc2/如何能够在ComboBox类型的单元格中输入数据?2)?http://w ww.cnblogs.cc2/HowdoIhandletheSelectedIndexChangedevent?3)? http://www.cnblogs.cc2/HowdoIhaveacomboboxcolumndisplaya subsetofdatabaseduponthevalueofadifferentcomboboxco lumn?3.6DataGridViewLinkColumn使用DataGridViewLinkColumn列,你可以显示一列包 含超链接的单元格。在显示数据源中的URL值,或者替代按钮列进行一些特殊行为,如打开另一个子记录窗体时会很有用。Link列也不会在D ataGridView数据绑定时自动生成。要使用它,你还得手动创建,然后将它添加到DataGridView控件的Columns集合 中。你可以处理CellContentClick事件来相应用户的点击动作。这个事件不同于CellClick和CellMouseCl ick事件,后两者在用户点击单元格任何位置(而不仅仅时链接)时都会触发。DataGridViewLinkColumn类提供了几 个属性,用来修改链接的外观,包括点击前,点击时和点击后(类似于网页中的超链接)。4操作数据(WorkingwithData) 多数情况下,使用DataGridView的时候都需要跟数据打交道,这时有很多事情可能需要你去做。你需要验证用户输入的数据,或者需要 对数据进行格式化。DataGridView能够以三种模式显示数据:bound、unboundand和virtual。每种模式都有 自己的特性和存在的理由。不管是否是数据绑定模式,在操作数据时,如果发生错误,DataGridView通常会触发DataError事 件,理解该事件发生的原因能让你更好地利用它。4.1数据输入和验证的相关事件用户输入数据时-对其所在的行或单元格,你可能希望验证这 些数据,在遇到无效数据时通知用户。就像常见的WindowsForms控件,DataGridView的行和单元格也有Validat ing和Validated事件,验证事件可被取消。用户在单元格/行间移动时会触发Enter和Leave事件。最后,用户在开始编辑单 元格时也会触发事件。了解所有这些程序的发生顺序会对你很有帮助。4.1.1数据验证相关事件的顺序下面列出validation,en ter/leave和begin/end这些事件的顺序(当EditMode为EditOnEnter时):当从一个单元格移动至另一单元 格(在同一行内):1)??????CellLeave(原来的单元格)2)??????CellValidating/ed (原来的单元格)3)??????CellEndEdit(原来的单元格)4)??????CellEnter(新的单元格) 5)??????CellBeginEdit(新的单元格)当从一行移动到另一行:1)??????CellLeave(原来 的单元格),Rowleave(原来的行)2)??????CellValidating/ed(原来的单元格)3)????? ?CellEndEdit(原来的单元格)4)??????RowValidating/ed(原来的行)5)?????? RowEnter(新的行)6)??????CellEnter(新的单元格)7)??????CellBeginEdit (新的单元格)4.1.2验证数据验证用户输入时,如果DataGridView采用非数据绑定模式,通常会对单元格进行验证;而如果 采用数据绑定模式,则一般会对行进行验证。这与数据的组织方式密切相关,非数据绑定模式下,一行的单元格间关系一般比较“散”,而绑定模式 下,数据源的数据一般以行来组织。但有时在数据绑定模式下会同时进行单元格级和行级的验证。4.1.2.1显示错误信息一旦遭遇了无效的 输入数据,你通常需要通知用户。这时有多种方式可以选择,传统的方式是使用信息对话框。DataGridView还能够为行或单元格显示一 个错误图标来通知用户输入了无效数据。错误图标带有一个工具提示,它提供了该错误的相关信息:4.1.2.2常见问题(FAQ)1)?h ttp://www.cnblogs.cc2/如何在用户编辑单元格的时候显示错误图标?4.1.3在新行中的数据输入(DataEn tryintheNewRow)当在程序中使用DataGridView来编辑数据时,你往往希望提供让用户添加新行数据的功能。 DataGridView控件支持这个功能,提供了一个用于添加新记录的行,而这一行总是显示为最后一行,并在该行的标题单元格标以星号( )。下面的几个小节会讨论一些在程序中使用这个新行时需要考虑的内容。(下面总是以新行表示用于添加新记录的行)4.1.3. 1显示新行使用AllowUserToAddRows属性以指示是否显示新行,其默认值为true。新行处于网格的最后一行,标题带有星 号:在数据绑定的情况下,当DataGridView控件的AllowUserToAddRows属性和数据源的IBindingList .AllowNew属性都为true时,新行才会显示,只要两者有一个为false,新行就不会显示。4.1.3.2为生成的新行添加 默认值当用户选择新行作为当前行,DataGridView会触发DefaultValuesNeeded事件。在该事件中可以访问新行, 并为其生成默认值,为用户输入提供方便。下面这段代码演示了如何在DefaultValuesNeeded事件中为新行指定默认值。pri vatevoiddataGridView1_DefaultValuesNeeded(objectsender,?DataGr idViewRowEventArgs?e){e.Row.Cells["Region"].Value="WA";e.Row. Cells["City"].Value="Redmond";e.Row.Cells["PostalCode"].Value ="98052-6399";e.Row.Cells["Region"].Value="NA";e.Row.Cells[" Country"].Value="USA";e.Row.Cells["CustomerID"].Value=NewCus tomerId();}4.1.3.3Rows集合与新行的关系新行包含在DataGridView控件的Rows集合中,又因其总是处 于最后一行,下面这行代码会返回新行:DataGridViewRow?row=dataGridView1.Rows[dataGr idView1.Rows.Count-1];尽管新行也包含在Rows集合中,它与Rows集合中其它行的行为却不相同,表现在两点 :不能以编程的方式将新行从Rows集合中移除,如果你尝试这么做,会抛出InvalidOperationException类型的异常 。用户也不能删除新行。DataGridViewRowCollection.Clear()方法也不能将新行从Rows集合中移除。不能 在新行之后添加行。如果你尝试这么做,会抛出InvalidOperationException类型的异常。这种特性的结果是,新行总 处于DataGridView的最后一行。当新行显示的时候,DataGridViewRowCollection类中用于添加行的方法 -Add,AddCopy以及AddCopies-在内部都调用用于插入的方法。4.1.3.4在新行中输入数据用户开始在新行输入数据 之前,新行的IsNewRow属性值为true;一旦用户开始输入,这一行就不再是新行了,DataGridView中会产生一个“新”的 新行,看下面示意图:在添加“新”的新行时,会触发UserAddedRow事件,它的事件处理函数的第二个参数有属性Row,指定了这个 “新”的新行。如果用户此时按下Escape键,“新”的新行会被移除,这会触发UserDeletingRow事件,它的事件处理函数的 第二个参数的属性Row指定了“新”的新行。4.1.3.5自定义新行的可视化效果新行是基于RowTemplate模板创建的,如果没 有指定它的单元格的样式,它们会采用继承的样式。要了解样式继承的更多信息,请参看第五章第一节的内容。新行中单元格的初始值是由每个单元 格的DefaultNewRowValue属性决定的。对于DataGridViewImageCell类型的单元格,其初始值为一个占位 图片,其它类型的则为null。你可以重写这个属性以返回自定义值。但也可以在DefaultValuesNeeded事件处理函数中对默 认值进行替换,该事件在焦点进入新行时触发。新行标题的标准图标是箭头或者星号,并没有得到暴露。如果你要自定义这个图标,就需要创建一个 自定义的DataGridViewRowHeaderCell类。新行的标题的标准图标使用标题单元格DataGridViewCell Style的ForeColor属性。注意:如果没有足够的空间,图标就不会再显示。如果为标题单元格设置了字符串值(通过Value属性 ),但没有足够的控件同时显示文本和图标,那么图标会被首先截掉。4.1.3.6新行的排序在非绑定模式下,新行总是添加在DataGr idView的最后一行,即使已经对数据排序。用户需要在添加新行后再次进行排序,以将新记录放在合适的位置;这种行为方式类似于List View控件。在绑定模式或虚拟模式(VirtualMode)下,如果已对数据排序,那么插入数据时的行为取决于数据模型的实现方式。 对于ADO.NET,新加的行会被自动排序至合适的位置。4.1.3.7关于新行,还要注意:你不能将新行的Visible属性值设置为 false,否则会触发一个InvalidOperationException类型的异常。新行在创建时总是处于非选中(unselec ted)状态。4.1.3.8VirtualMode下的新行如果你正要实现虚拟模式(VirtualMode),需要考虑数据模型 添加新行和回滚添加操作的情况。该功能准确的实现方式取决于数据模型的实现方式及其事务机制,例如,提交的时候是针对单元格还是行。参看本 文档后面关于VirtualMode的主题。4.2关于Null值在使用数据源的时候,比如数据库或业务对象,经常需要处理null值 。null值可能是一个实际的null(VB中为Nothing),也可能是一个数据库的”null”值(DBNull.Value),当 你遭遇了这些值,就需要考虑如何显示它们。另一方面,很多时候,你还需要向数据源写入null值。使用单元格Style的NullValu e属性和DataSourceNullValue属性,你可以改变DataGridView处理null值的方式。4.2.1Null Value属性DataGridViewCellStyle.NullValue属性本来要被命名为FormattedNullValu e的,但是后来没来得及作出这个更改。但它能给我们带来一点提示——顾名思义,在格式化时会用到它。如果一个单元格的值为”null”( 等于null或DBNull.Value),它会使用你设置的NullValue属性来显示。该属性的默认值取决于所在列的类型,见下图: DataGridView列类型列的DefaultCellStyle.NullValue值TextBoxColumnString.E mpty(“”)ImageColumn空的图像()ComboBoxColumnString.Empty(“”)ButtonC olumnString.Empty(“”)LinkColumnString.Empty(“”)CheckBoxColumn默认 值取决于ThreeState属性的值,如果为true,默认值为CheckState.Indeterminate,否则为unche cked。有一点要了解,在用户输入数据时也会用到NullValue。例如,若用户向TextBox类型单元格输入了string.Em pty,那么会将null作为该单元格的值。查看下面的DataSourceNullValue属性以了解究竟是输入了什么作为单元格的 值。4.2.2DataSourceNullValue属性DataGridViewCellStyle.DataSourceNull Value属性要被命名为ParseNullValue的,如果NullValue属性被命名为FormattedNullValue的话 ,但最后还是采用了DataSourceNullValue,这样更直观准确。在将null值写入单元格的值时,就会用到DataSour ceNullValue属性。在数据绑定情形下,这个null值将被写入数据库或业务对象,此处需要进行控制,因为对于数据库和业务对象来 说,null的概念不尽相同。通常你会期望,使用业务对象时将DataSourceNullValue设置为null,而使用数据库时则 将其设置为DBNullValue。DataSourceNullValue的默认值为DBNull.Value。4.3DataErr or事件将DataError事件独立出来作为一个主题,是因为在操作数据时,经常会遭遇DataError事件。在操作数据时,Data Error主要发生在一下情况:不能读/写或转换单元格的数据;在尝试进行某种编辑操作时发生了异常。编辑操作中的DataError?事 件下面的列表列出了可能会引发DataError事件的编辑操作:取消编辑(Cancelinganedit)刷新一个编辑(通过调 用RefreshEdit方法)尝试将单元格的值写入数据源初始化编辑控件\单元格的值(通过设置单元格的FormattedValue属 性或调用单元格的InitializeEditingControl方法)结束编辑(Endinganedit)提交编辑(Commi ttinganedit)删除一行(Deletingarow)?DataError的上下文:下面的列表显示了不同的DataE rror上下文环境,然后进一步说明了这些上下文环境合适可能发生:DataErrorContext何时发生FormattingWhe nattemptingtoretrievethecell''sformattedvalue.DisplayWhena ttemptingtopaintthecellorcalculatethecell''stooltiptext. Notethattheseoperationsusuallyalsorequiregettingthecell'' sformattedvalue,sotheerrorcontextisOR''dtogether.Preferre dSizeWhencalculatingthepreferredsizeofacell.This?usually alsorequiresgettingthecell''sformattedvaluealso.RowDeletion Anyexceptionraisedwhendeletingarow.ParsingWhenexceptionso ccurwhencommitting,endingorcancelinganedit.UsuallyOR''di nwithothererrorcontextsCommitWhenexceptionsoccurwhencommi ttinganedit.UsuallyOR''dwithothererrorcontextsInitialValue RestorationWhenexceptionsoccurwhileeitherinitializingtheed itingcontrol/cell''svalue,orCancelinganeditLeaveControlWhen exceptionsoccurwhileattemptingtovalidategriddatawhenthe gridislosingfocus.UsuallyOR''dwithothererrorcontexts.Curr entCellChangeWhenexceptionsoccurwhilevalidating\updating\comm itting\gettingcellcontentwhenthecurrentcellchanges.Usuall yOR''dwithothererrorcontexts.ScrollWhenexceptionsoccurwhil evalidating\updating\committing\gettingcellcontentwhenthecu rrentcellchangesasaresultofscrolling.ClipboardContentWhen exceptionsoccurwhileattemptingtogettheformattedvalueofa cellwhilecreatingtheclipboardcontent.4.4数据绑定模式(Databoundm odes)4.4.1非绑定模式(UnboundMode)如果你要在程序中管理数量相对较小的数据,那么非绑定模式会比较合适。此时 你不是像绑定模式中那样将DataGridView控件直接指向一个数据源,而是手动去生成控件。一般需要用到DataGridViewR owCollection.Add方法(该方法向DGV中添加行)。非绑定模式在处理静态、只读的数据时特别有用,也可以用在以自己的方 式与外部数据源交互的情况,但实际上,如果你希望你的用户与外部的数据源交互,一般还是用绑定模式(boundmode)更好。4.4. 2绑定模式(BoundMode)如果你在程序中管理一些数据,并希望能与数据源自动进行交互,就应该使用绑定模式。此时你可以设置D ataSource属性,将数据源绑定到DataGridView控件。如果控件使用了绑定模式,就不需要你去显式地对数据进行读写了。如 果AutoGenerateColumns属性为true,数据源中的每一列都会在DataGridView中生成一个相应的列(根据列 的数据类型),如果你希望创建自己的列,可以将该属性设置为false,使用DataPropertyName属性将一列绑定到数据源的一 列,这在你不想用自动生成的列类型时很有用。4.4.2.1有效的数据源将数据绑定到DataGridView非常简单、直观,很多情况 下,你只需要设置它的DataSource属性。如果使用的数据源包含多个列表(list)或数据表(table),你还需要设置控件的D ataMember属性,该属性为字符串类型,用于指定要绑定的列表或数据表。DataGridView控件支持标准的WinForm数据 绑定模型,因此它可以绑定到下面列表中的类的实例:任意实现了IList接口的类,包括一维数组;任意实现了IListSource接口的 类,比如DataTable和DataSet;任意实现了IBindingList接口的类,比如BindingList;任意实现了 IBindingListView接口的类,比如BindingSource。列表更改通知(ListChangeNotifica tion)当你将数据绑定到列表时,最重要的功能之一便是支持列表更改通知了。这只有在你希望列表(即数据源)发生变化,如添加、修改和删 除,DataGridView能够随之更新的时候,该功能才显得重要。只有实现了IBindingList接口的数据源支持更改通知。像数 组和集合这样的列表默认情况下不支持更改通知。在选择数据源时,BindingSource组件应该作为首选,因为它可以绑定到多种类型的 数据源,并且能够自动处理很多数据绑定相关的事务。一般情况下,应该将DataGridView绑定到BindingSource组件,并 将BindingSource组件绑定真正的数据源(它的作用就像DGV和数据源间的桥梁)。BindingList类也可以在一 个类的基础上创建自定义列表(list)。对象更改通知(ObjectChangeNotification)如果你有了一个数据源, 那么数据源中的对象就可以实现对public属性的更改通知。这需要你为相应属性提供一个”PropertyNameChanged”事 件,或者实现INotifyPropertyChanged接口。INotifyPropertyChanged是在VS2005中 新加的接口,可以与BindingList一起使用来创建可绑定的列表(list)。但当你的数据源是BindingSource ,那就不用再额外实现更改通知了。4.4.3虚拟模式使用虚拟模式,你可以实现自己的数据管理操作。在绑定模式下,如果要使用非绑定列, 那么要想在对列排序时能够维护非绑定列的值,就需要虚拟模式。但虚拟模式的最主要的用途还是在操作大量数据时优化性能。你将DataGri dView绑定到缓存的数据,然后用代码控制数据行的存取。要保持使用内存量比较小,缓存的数据量应与当前要显示的行数相当。当用户滚动控 件看到了新的行时,你的代码就从缓存中请求新的数据,并从内存中清除旧的数据。如果你正要实现虚拟模式(VirtualMode),需要 考虑数据模型添加新行和回滚添加操作的情况。该功能准确的实现方式取决于数据模型的实现方式及其事务机制,例如,提交的时候是针对单元格还 是行。参看本文档后面关于VirtualMode的主题。4.4.4混合模式–绑定与非绑定模式显示在DataGridView中 的数据通常来自于某种类型的数据源,但是你可能也希望显示一个数据源之外的列。这种列称为非绑定列。你可以在绑定模式下添加非绑定列,在你 希望显示一个按钮列或者链接列让用户操作一些特定行时这显得很有用,另外也可以用非绑定列显示一些由绑定列计算而得到的值。你可以在Cel lFormatting事件处理函数中生成计算列的值。不过如果你使用的数据源是DataSet或DataTable,你可能希望使用Da taColumn.Expression属性来创建一个计算列,在这种情况下,在DGV看来,这一列就跟数据源中其它列是一样的。在绑定 模式下根据非绑定列排序是不受支持的。如果你在绑定模式下创建了非绑定列,你必须实现虚拟模式,这样在根据绑定列排序时可以维护非绑定列的 值。如果添加的非绑定列不能由数据源数据计算得来或者这些数据会频繁更新,你就应该使用虚拟模式。要了解虚拟模式的更多信息,请参看本文档 后面的虚拟模式相关章节。4.4.5?常见问题1)?http://www.cnblogs.cc2/如何同时显示绑定数据和非绑定数据? 2)?http://www.cnblogs.cc2/HowdoIshowdatathatcomesfromtwo tables?(TODO)3)?http://www.cnblogs.cc2/如何显示主从表?4)?http://www.cnbl ogs.cc2/如何在同一DataGridView内显示主从表?5)?http://www.cnblogs.cc2/如何避免对一列 的排序?6)?http://www.cnblogs.cc2/如何针对多个列排序?7)?http://www.cnblogs.cc2 /HowdoIhaveacomboboxcolumndisplayasubsetofdatabased uponthevalueofadifferentcomboboxcolumn?(TODO)8)?http://w ww.cnblogs.cc2/如何在点击工具栏按钮的时候将数据提交到数据库?9)?http://www.cnblogs.cc2/如 何在用户删除记录时显示确认对话框?5特性综览(Overviewoffeatures)5.1样式(Styling)DataGr idView使得定义单元格的基本外观和格式化单元格显示变得简单。您可以定义的外观和在特定的列和行,或在通过各种设置DataGrid View控件属性访问的DataGridViewCellStyle对象的属性控制所有细胞的单个单元格的格式样式。此外,您可以修改,如 通过处理CellFormatting事件的单元格值因素的基础上动态这些样式。DataGridView控件中的每一个细胞都可以拥有如 文本格式,背景色,前景色和字体自己的风格。但是,通常多个单元格将分享独特的风格特点。细胞群体共享样式可能包括在特定行或列的所有单元 格包含特定值,或控件中的所有细胞的所有细胞。由于这些群体重叠,每个单元可能会从多个位置的样式??信息。例如,您可能会希望每个在Da taGridView控件使用相同的字体细胞,只有细胞货币列,但使用货币格式,负数和货币细胞只使用红色前景色。Youcandef ineappearanceandformattingstylesforindividualcells,force llsinspecificcolumnsandrows,orforallcellsinthecontrol bysettingthepropertiesoftheDataGridViewCellStyleobjectsa ccessedthroughvariousDataGridViewcontrolproperties.Addition ally,youcanmodifythesestylesdynamicallybasedonfactorssu chasthecellvaluebyhandlingtheCellFormattingevent.Eachce llwithintheDataGridViewcontrolcanhaveitsownstyle,sucha stextformat,backgroundcolor,foregroundcolor,andfont.Typi cally,however,multiplecellswillshareparticularstylecharac teristics.Groupsofcellsthatsharestylesmayincludeallcells withinparticularrowsorcolumns,allcellsthatcontainpartic ularvalues,orallcellsinthecontrol.Becausethesegroupsov erlap,eachcellmaygetitsstylinginformationfrommorethano neplace.Forexample,youmaywanteverycellinaDataGridView controltousethesamefont,butonlycellsincurrencycolumns tousecurrencyformat,andonlycurrencycellswithnegativenum berstousearedforegroundcolor.5.1.1TheDataGridViewCellStyl eClassTheDataGridViewCellStyleclasscontainsthefollowingpro pertiesrelatedtovisualstyle:BackColorandForeColor,Selectio nBackColorandSelectionForeColor,FontThisclassalsocontainst hefollowingpropertiesrelatedtoformatting:FormatandFormatPr ovider,NullValueandDataSourceNullValue,WrapMode,Alignment,P addingDataGridViewCellStyle类包含以下有关视觉样式属性:背景色和前景色,SelectionBackCol or和SelectionForeColor,字体此类还包含了相关的格式如下属性:格式和FormatProvider,并DataSo urceNullValue的NullValue,的WrapMode,对齐,填充5.1.2UsingDataGridViewCe llStyleObjectsYoucanretrieveDataGridViewCellStyleobjectsfro mvariouspropertiesoftheDataGridView,DataGridViewColumn,Dat aGridViewRow,andDataGridViewCellclassesandtheirderivedclas ses.Ifoneofthesepropertieshasnotyetbeenset,retrieving itsvaluewillcreateanewDataGridViewCellStyleobject.Youcan alsoinstantiateyourownDataGridViewCellStyleobjectsandassi gnthemtotheseproperties.Youcanavoidunnecessaryduplication ofstyleinformationbysharingDataGridViewCellStyleobjectsam ongmultipleDataGridViewelements.Becausethestylessetatthe control,column,androwlevelsfilterdownthrougheachlevelt othecelllevel,youcanalsoavoidstyleduplicationbysetting onlythosestylepropertiesateachlevelthatdifferfromthel evelsabove.ThisisdescribedinmoredetailintheStyleInheri tancesectionthatfollows.Thefollowingtableliststheprimary propertiesthatgetorsetDataGridViewCellStyleobjects.Property ClassesDescriptionDefaultCellStyleDataGridView,DataGridViewColum n,DataGridViewRow,andderivedclassesGetsorsetsdefaultstyle susedbyallcellsintheentirecontrol(includingheadercells ),inacolumn,orinarow.RowsDefaultCellStyleDataGridViewGets orsetsdefaultcellstylesusedbyallrowsinthecontrol.This doesnotincludeheadercells.AlternatingRowsDefaultCellStyleDat aGridViewGetsorsetsdefaultcellstylesusedbyalternatingrow sinthecontrol.Usedtocreatealedger-likeeffect.RowHeadersD efaultCellStyleDataGridViewGetsorsetsdefaultcellstylesused bythecontrol''srowheaders.Overriddenbythecurrentthemeif visualstylesareenabled.ColumnHeadersDefaultCellStyleDataGridVi ewGetsorsetsdefaultcellstylesusedbythecontrol''scolumnh eaders.Overriddenbythecurrentthemeifvisualstylesareenab led.StyleDataGridViewCellandderivedclassesGetsorsetsstyles specifiedatthecelllevel.Thesestylesoverridethoseinherite dfromhigherlevels.InheritedStyleDataGridViewCell,DataGridView Row,DataGridViewColumn,andderivedclassesGetsallthestylesc urrentlyappliedtothecell,row,orcolumn,includingstylesin heritedfromhigherlevels.Asmentionedabove,gettingthevalue ofastylepropertyautomaticallyinstantiatesanewDataGridView CellStyleobjectifthepropertyhasnotbeenpreviouslyset.To avoidcreatingtheseobjectsunnecessarily,therowandcolumncl asseshaveaHasDefaultCellStylepropertythatyoucanchecktod eterminewhethertheDefaultCellStylepropertyhasbeenset.Simi larly,thecellclasseshaveaHasStylepropertythatindicatesw hethertheStylepropertyhasbeenset.Eachofthestyleproperti eshasacorrespondingPropertyNameChangedeventontheDataGridV iewcontrol.Forrow,column,andcellproperties,thenameofth eeventbeginswith"Row","Column",or"Cell"(forexample,RowD efaultCellStyleChanged).Eachoftheseeventsoccurswhenthecor respondingstylepropertyissettoadifferentDataGridViewCellS tyleobject.TheseeventsdonotoccurwhenyouretrieveaDataGr idViewCellStyleobjectfromastylepropertyandmodifyitsprope rtyvalues.Torespondtochangestothecellstyleobjectsthems elves,handletheCellStyleContentChangedevent.5.1.3StyleInher itanceEachDataGridViewCellgetsitsappearancefromitsInherite dStyleproperty.TheDataGridViewCellStyleobjectreturnedbythi spropertyinheritsitsvaluesfromahierarchyofpropertiesof typeDataGridViewCellStyle.Thesepropertiesarelistedbelowin theorderinwhichtheInheritedStylefornon-headercellsobtain sitsvalues.DataGridViewCell.StyleDataGridViewRow.DefaultCellSty leAlternatingRowsDefaultCellStyle(onlyforcellsinrowswithod dindexnumbers)RowsDefaultCellStyleDataGridViewColumn.DefaultCel lStyleDefaultCellStyleForrowandcolumnheadercells,theInheri tedStylepropertyispopulatedbyvaluesfromthefollowinglist ofsourcepropertiesinthegivenorder.DataGridViewCell.StyleCol umnHeadersDefaultCellStyleorRowHeadersDefaultCellStyleDefaultCe llStyleThefollowingdiagramillustratesthisprocess.Youcanals oaccessthestylesinheritedbyspecificrowsandcolumns.Thec olumnInheritedStylepropertyinheritsitsvaluesfromthefollow ingproperties.DataGridViewColumn.DefaultCellStyleDefaultCellStyl eTherowInheritedStylepropertyinheritsitsvaluesfromthefol lowingproperties.DataGridViewRow.DefaultCellStyleAlternatingRows DefaultCellStyle(onlyforcellsinrowswithoddindexnumbers)R owsDefaultCellStyleDefaultCellStyleForeachpropertyinaDataGri dViewCellStyleobjectreturnedbyanInheritedStyleproperty,the propertyvalueisobtainedfromthefirstcellstyleintheappr opriatelistthathasthecorrespondingpropertysettoavalueo therthantheDataGridViewCellStyleclassdefaults.Thefollowing tableillustrateshowtheForeColorpropertyvalueforanexample cellisinheritedfromitscontainingcolumn.PropertyoftypeDa taGridViewCellStyleExampleForeColorvalueforretrievedobjectDa taGridViewCell.StyleColor.EmptyDataGridViewRow.DefaultCellStyleCo lor.RedAlternatingRowsDefaultCellStyleColor.EmptyRowsDefaultCellS tyleColor.EmptyDataGridViewColumn.DefaultCellStyleColor.DarkBlueD efaultCellStyleColor.BlackInthiscase,theSystem.Drawing.Color. Redvaluefromthecell''srowisthefirstrealvalueonthelist .ThisbecomestheForeColorpropertyvalueofthecell''sInherit edStyle.ThefollowingdiagramillustrateshowdifferentDataGridV iewCellStylepropertiescaninherittheirvaluesfromdifferentp laces.Bytakingadvantageofstyleinheritance,youcanprovidea ppropriatestylesfortheentirecontrolwithouthavingtospecif ythesameinformationinmultipleplaces.Althoughheadercellsp articipateinstyleinheritanceasdescribed,theobjectsreturne dbytheColumnHeadersDefaultCellStyleandRowHeadersDefaultCellS tylepropertiesoftheDataGridViewcontrolhaveinitialproperty valuesthatoverridethepropertyvaluesoftheobjectreturned bytheDefaultCellStyleproperty.Ifyouwantthepropertiesset fortheobjectreturnedbytheDefaultCellStylepropertytoapply torowandcolumnheaders,youmustsetthecorrespondingproper tiesoftheobjectsreturnedbytheColumnHeadersDefaultCellStyle andRowHeadersDefaultCellStylepropertiestothedefaultsindica tedfortheDataGridViewCellStyleclass.Note:?Ifvisualstylesar eenabled,therowandcolumnheaders(exceptfortheTopLeftHead erCell)areautomaticallystyledbythecurrenttheme,overriding anystylesspecifiedbytheseproperties.SettheEnableHeadersV isualStylepropertytofalseifyouwantheaderstonotuseXP’s visualstyles.TheDataGridViewButtonColumn,DataGridViewImageColu mn,andDataGridViewCheckBoxColumntypesalsoinitializesomeval uesoftheobjectreturnedbythecolumnDefaultCellStylepropert y.Formoreinformation,seethereferencedocumentationforthes etypes.5.1.4SettingStylesDynamicallyTocustomizethestyleso fcellswithparticularvalues,implementahandlerfortheCellF ormattingevent.Handlersforthiseventreceiveanargumentoft heDataGridViewCellFormattingEventArgstype.Thisobjectcontains propertiesthatletyoudeterminethevalueofthecellbeingfo rmattedalongwithitslocationintheDataGridViewcontrol.This objectalsocontainsaCellStylepropertythatisinitializedto thevalueoftheInheritedStylepropertyofthecellbeingforma tted.Youcanmodifythecellstylepropertiestospecifystylei nformationappropriatetothecellvalueandlocation.Note:?TheR owPrePaintandRowPostPainteventsalsoreceiveaDataGridViewCel lStyleobjectintheeventdata,butintheircase,itisacopy oftherowInheritedStylepropertyforread-onlypurposes,andch angestoitdonotaffectthecontrol.Youcanalsodynamicallymo difythestylesofindividualcellsinresponsetoeventssuchas theCellMouseEnterandCellMouseLeaveevents.Forexample,ina handlerfortheCellMouseEnterevent,youcouldstorethecurrent valueofthecellbackgroundcolor(retrievedthroughthecell''s Styleproperty),thensetittoanewcolorthatwillhighlight thecellwhenthemousehoversoverit.InahandlerfortheCell MouseLeaveevent,youcanthenrestorethebackgroundcolortoth eoriginalvalue.Note:?Cachingthevaluesstoredinthecell''sSt ylepropertyisimportantregardlessofwhetheraparticularstyl evalueisset.Ifyoutemporarilyreplaceastylesetting,resto ringittoitsoriginal"notset"stateensuresthatthecellwil lgobacktoinheritingthestylesettingfromahigherlevel.If youneedtodeterminetheactualstyleineffectforacellrega rdlessofwhetherthestyleisinherited,usethecell''sInherite dStyleproperty.5.2CustompaintingTheDataGridViewcontrolprovi desseveralpropertiesthatyoucanusetoadjusttheappearance andbasicbehavior(lookandfeel)ofitscells,rows,andcolumn s.Ifyouhaverequirementsthatgobeyondthecapabilitiesofth eDataGridViewCellStyleclass,youcanperformcustomdrawingof thecellorrowcontent.Topaintcellsandrowsyourself,youca nhandlevariousDataGridViewpaintingeventssuchasRowPrePaint ,CellPaintingandRowPostPaint.5.2.1PaintPartsOneimportantpa rtofcustompaintingistheconceptofpaintparts.TheDataGrid ViewPainPartsenumerationisusedtospecifywhatpartsacellpa ints.Enumvaluescanbecombinedtogethertohaveacellpainto rnotpaintspecificparts.Herearethedifferentparts:PaintPar tExampleForeColorvalueforretrievedobjectAllAllpartsarepai ntedBackgroundThebackgroundofthecellispaintedusingthecel l’sbackgroundcolor(1)BorderThebordersarepaintedContentBackg roundThebackgroundpartofthecell’scontentispainted.(2)Con tentForegroundTheforegroundpartofthecell’scontentispainte d(2)ErrorIconTheerroriconispaintedFocusThefocusrectanglef orthecellispaintedNoneNopartsarepainted(1)SelectionBackgr oundThebackgroundispaintedselectedifthecellisselected.No tes1)??????Ifacelldoesnotpaintitsbackgroundthennothing ispainted.Aroworcolumnperformsnopainting,soensurethat atleastthecell’sbackgroundispaintedoryouperformyourown custombackgroundpainting;otherwisetherectangleremainsinva lidated(unpainted).2)??????Eachcelldetermineswhatitpaints ascontentforegroundandcontentbackgroundasdescribedbythe followinglist:CellTypeContentForegroundContentBackgroundText boxCelltextispaintedNothingpaintedButtonCelltextispaintedB uttonispaintedComboboxCelltextispaintedComboboxispainted CheckboxCheckboxispaintedNothingpaintedLinkCelltextispain tedasalinkNothingispaintedImageCellimageispaintedNothing paintedColumnHeaderColumnheadertextSortGlyphispaintedRowHe aderRowheadertextCurrentrowtriangle,editpencilandnewrow indicatorispainted5.2.2RowPrePaintandPostPaintYoucancon troltheappearanceofDataGridViewrowsbyhandlingoneorboth oftheDataGridView.RowPrePaintandDataGridView.RowPostPainteve nts.Theseeventsaredesignedsothatyoucanpaintonlywhatyo uwanttowhilelettingtheDataGridViewcontrolpainttherest. Forexample,ifyouwanttopaintacustombackground,youcanha ndletheDataGridView.RowPrePainteventandlettheindividualce llspainttheirownforegroundcontent.IntheRowPrePaintevent youcansetthePaintPartseventargspropertytoeasilycustomiz ehowthecellspaint.Forexample,ifyouwanttokeepcellsfro mpaintinganyselectionorfocus,yourRowPrePainteventwoulds etthePaintPartspropertylikeso:e.PaintParts=?DataGridViewPai ntParts.All&?~(DataGridViewPaintParts.Focus|???DataGridViewPai ntParts.SelectionBackground);Whichcouldalsobewrittenas:e.Pai ntParts=(DataGridViewPaintParts.Background|?DataGridViewPaintP arts.Border|??DataGridViewPaintParts.ContentBackground|??DataGr idViewPaintParts.ContentForeground|??DataGridViewPaintParts.Erro rIcon);Alternately,youcanletthecellspaintthemselvesandad dcustomforegroundcontentinahandlerfortheDataGridView.Row PostPaintevent.Youcanalsodisablecellpaintingandpainteve rythingyourselfinaDataGridView.RowPrePainteventhandler5.3A utosizingTheDataGridViewcontrolprovidesnumerousoptionsforc ustomizingthesizingbehaviorofitscolumnsandrows.Typically ,DataGridViewcellsdonotresizebasedontheircontents.Inste ad,theyclipanydisplayvaluethatislargerthanthecell.If thecontentcanbedisplayedasastring,thecelldisplaysitin aToolTip.Bydefault,userscandragrow,column,andheaderdiv iderswiththemousetoshowmoreinformation.Userscanalsodou ble-clickadividertoautomaticallyresizetheassociatedrow,c olumn,orheaderbandbasedonitscontents.Columnssharetheav ailablewidthofthecontrolbydefault,soifuserscanresizet hecontrol—forexample,ifitisdockedtoaresizableform—they canalsochangetheavailabledisplayspaceforallcolumns.TheD ataGridViewcontrolprovidesproperties,methods,andeventsthat enableyoutocustomizeordisablealloftheseuser-directedbe haviors.Additionally,youcanprogrammaticallyresizerows,colu mns,andheaderstofittheircontents,oryoucanconfigurethem toautomaticallyresizethemselveswhenevertheircontentschang e.常见问题:1)?http://www.cnblogs.cc2/如何调整最后一列的宽度使其占据网格的剩余客户区?5.3.1?Si zingOptionsintheWindowsFormsDataGridViewControl?DataGridVi ewrows,columns,andheaderscanchangesizeasaresultofmany differentoccurrences.Thefollowingtableshowstheseoccurrenc es.OccurrenceDescriptionUserresizeUserscanmakesizeadjustment sbydraggingordouble-clickingrow,column,orheaderdividers. ControlresizeIncolumnfillmode,columnwidthschangewhenthe controlwidthchanges;forexample,whenthecontrolisdockedto itsparentformandtheuserresizestheform.CellvaluechangeI ncontent-basedautomaticsizingmodes,sizeschangetofitnewd isplayvalues.MethodcallProgrammaticcontent-basedresizinglets youmakeopportunisticsizeadjustmentsbasedoncellvaluesat thetimeofthemethodcall.PropertysettingYoucanalsosetspec ificheightandwidthvalues.Bydefault,userresizingisenabled ,automaticsizingisdisabled,andcellvaluesthatarewiderth antheircolumnsareclipped.Thefollowingtableshowsscenarios thatyoucanusetoadjustthedefaultbehaviorortousespecifi csizingoptionstoachieveparticulareffects.ScenarioImplementa tionUsecolumnfillmodefordisplayingsimilarlysizeddataina relativelysmallnumberofcolumnsthatoccupytheentirewidth ofthecontrolwithoutdisplayingthehorizontalscrollbar.Sett heAutoSizeColumnsModepropertytoFill.Usecolumnfillmodewith displayvaluesofvaryingsizes.Setthe?AutoSizeColumnsMode?prop ertyto?Fill.Initializerelativecolumnwidthsbysettingtheco lumnFillWeightpropertiesorbycallingthecontrolAutoResizeCo lumnsmethodafterfillingthecontrolwithdata.Usecolumnfill modewithvaluesofvaryingimportance.Setthe?AutoSizeColumnsMod e?propertyto?Fill.SetlargeMinimumWidthvaluesforcolumnstha tmustalwaysdisplaysomeoftheirdataoruseasizingoptiono therthanfillmodeforspecificcolumns.Usecolumnfillmodeto avoiddisplayingthecontrolbackground.SettheAutoSizeModeprop ertyofthelastcolumntoFillanduseothersizingoptionsfor theothercolumns.Displayafixed-widthcolumn,suchasanicono rIDcolumn.Set?AutoSizeMode?toNoneandResizabletoFalsefort hecolumn.InitializeitswidthbysettingtheWidthpropertyor bycallingthecontrolAutoResizeColumnmethodafterfillingthe controlwithdata.Adjustsizesautomaticallywhenevercellconten tschangetoavoidclippingandtooptimizetheuseofspace.Set anautomaticsizingpropertytoavaluethatrepresentsacontent -basedsizingmode.Toavoidaperformancepenaltywhenworkingw ithlargeamountsofdata,useasizingmodethatcalculatesdisp layedrowsonly.Adjustsizestofitvaluesindisplayedrowstoa voidperformancepenaltieswhenworkingwithmanyrows.Usetheap propriatesizing-modeenumerationvalueswithautomaticorprogra mmaticresizing.Toadjustsizestofitvaluesinnewlydisplayed rowswhilescrolling,callaresizingmethodinaScrolleventh andler.Tocustomizeuserdouble-clickresizingsothatonlyvalu esindisplayedrowsdeterminethenewsizes,callaresizingmet hodinaRowDividerDoubleClickorColumnDividerDoubleClickevent handler.Adjustsizestofitcellcontentsonlyatspecifictimes toavoidperformancepenaltiesortoenableuserresizing.Calla content-basedresizingmethodinaneventhandler.Forexample,u setheDataBindingCompleteeventtoinitializesizesafterbindin g,andhandletheCellValidatedorCellValueChangedeventtoadju stsizestocompensateforusereditsorchangesinabounddata source.Adjustrowheightsformultilinecellcontents.Ensurethat columnwidthsareappropriatefordisplayingparagraphsoftext anduseautomaticorprogrammaticcontent-basedrowsizingtoadj usttheheights.Alsoensurethatcellswithmultilinecontentar edisplayedusingaWrapModecellstylevalueofTrue.Typically, youwilluseanautomaticcolumnsizingmodetomaintaincolumnw idthsorsetthemtospecificwidthsbeforerowheightsareadjus ted.5.3.2ResizingwiththeMouseBydefault,userscanresizerow s,columns,andheadersthatdonotuseanautomaticsizingmode basedoncellvalues.Topreventusersfromresizingwithotherm odes,suchascolumnfillmode,setoneormoreofthefollowing DataGridViewproperties:AllowUserToResizeColumnsAllowUserToResize RowsColumnHeadersHeightSizeModeRowHeadersWidthSizeModeYoucanals opreventusersfromresizingindividualrowsorcolumnsbysetti ngtheirResizableproperties.Bydefault,theResizableproperty valueisbasedontheAllowUserToResizeColumnspropertyvaluefo rcolumnsandtheAllowUserToResizeRowspropertyvalueforrows. IfyouexplicitlysetResizabletoTrueorFalse,however,thesp ecifiedvalueoverridesthecontrolvalueisforthatroworcolu mn.SetResizabletoNotSettorestoretheinheritance.BecauseNo tSetrestoresthevalueinheritance,theResizablepropertywill neverreturnaNotSetvalueunlesstheroworcolumnhasnotbeen addedtoaDataGridViewcontrol.Ifyouneedtodeterminewhethe rtheResizablepropertyvalueofaroworcolumnisinherited,e xamineitsStateproperty.IftheStatevalueincludestheResiza bleSetflag,theResizablepropertyvalueisnotinherited.5.3.3 AutomaticSizingTherearetwokindsofautomaticsizingintheDa taGridViewcontrol:columnfillmodeandcontent-basedautomatic sizing.Columnfillmodecausesthevisiblecolumnsinthecontrol tofillthewidthofthecontrol''sdisplayarea.Formoreinform ationaboutthismode,seetheColumnFillModesectionbelow.You canalsoconfigurerows,columns,andheaderstoautomaticallya djusttheirsizestofittheircellcontents.Inthiscase,size adjustmentoccurswhenevercellcontentschange.Note:?Ifyoumain taincellvaluesinacustomdatacacheusingvirtualmode,autom aticsizingoccurswhentheusereditsacellvaluebutdoesnot occurwhenyoualteracachedvalueoutsideofaCellValuePushed eventhandler.Inthiscase,calltheUpdateCellValuemethodtof orcethecontroltoupdatethecelldisplayandapplythecurrent automaticsizingmodes.Ifcontent-basedautomaticsizingisenab ledforonedimensiononly—thatis,forrowsbutnotcolumns,or forcolumnsbutnotrows—andWrapModeisalsoenabled,sizeadjus tmentalsooccurswhenevertheotherdimensionchanges.Forexamp le,ifrowsbutnotcolumnsareconfiguredforautomaticsizinga ndWrapModeisenabled,userscandragcolumndividerstochange thewidthofacolumnandrowheightswillautomaticallyadjusts othatcellcontentsarestillfullydisplayed.Ifyouconfigureb othrowsandcolumnsforcontent-basedautomaticsizingandWrapM odeisenabled,theDataGridViewcontrolwilladjustsizeswhenev ercellcontentschangedandwilluseanidealcellheight-to-wid thratiowhencalculatingnewsizes.Toconfigurethesizingmode forheadersandrowsandforcolumnsthatdonotoverridethecon trolvalue,setoneormoreofthefollowingDataGridViewpropert ies:ColumnHeadersHeightSizeModeRowHeadersWidthSizeModeAutoSizeCol umnsModeAutoSizeRowsModeTooverridethecontrol''scolumnsizingm odeforanindividualcolumn,setitsAutoSizeModepropertytoa valueotherthanNotSet.Thesizingmodeforacolumnisactually determinedbyitsInheritedAutoSizeModeproperty.Thevalueoft hispropertyisbasedonthecolumn''sAutoSizeModepropertyvalue unlessthatvalueisNotSet,inwhichcasethecontrol''sAutoSiz eColumnsModevalueisinherited.Usecontent-basedautomaticresiz ingwithcautionwhenworkingwithlargeamountsofdata.Toavoi dperformancepenalties,usetheautomaticsizingmodesthatcalc ulatesizesbasedonlyonthedisplayedrowsratherthananalyzin geveryrowinthecontrol.Formaximumperformance,useprogramm aticresizinginsteadsothatyoucanresizeatspecifictimes,s uchasimmediatelyafternewdataisloaded.Content-basedautomat icsizingmodesdonotaffectrows,columns,orheadersthatyou havehiddenbysettingtheroworcolumnVisiblepropertyorthe controlRowHeadersVisibleorColumnHeadersVisiblepropertiestof alse.Forexample,ifacolumnishiddenafteritisautomaticall ysizedtofitalargecellvalue,thehiddencolumnwillnotcha ngeitssizeiftherowcontainingthelargecellvalueisdelete d.Automaticsizingdoesnotoccurwhenvisibilitychanges,soch angingthecolumnVisiblepropertybacktotruewillnotforceit torecalculateitssizebasedonitscurrentcontents.Programmat iccontent-basedresizingaffectsrows,columns,andheadersrega rdlessoftheirvisibility.5.3.4ProgrammaticResizingWhenautoma ticsizingisdisabled,youcanprogrammaticallysettheexactwi dthorheightofrows,columns,orheadersthroughthefollowing properties:RowHeadersWidthColumnHeadersHeightDataGridViewRow.Heig htDataGridViewColumn.WidthYoucanalsoprogrammaticallyresizero ws,columns,andheaderstofittheircontentsusingthefollowin gmethods:AutoResizeColumnAutoResizeColumnsAutoResizeColumnHeader sHeightAutoResizeRowAutoResizeRowsAutoResizeRowHeadersWidthThese methodswillresizerows,columns,orheadersonceratherthanco nfiguringthemforcontinuousresizing.Thenewsizesareautomat icallycalculatedtodisplayallcellcontentswithoutclipping. WhenyouprogrammaticallyresizecolumnsthathaveInheritedAutoS izeModepropertyvaluesofFill,however,thecalculatedcontent- basedwidthsareusedtoproportionallyadjustthecolumnFillWei ghtpropertyvalues,andtheactuallycolumnwidthsarethencalc ulatedaccordingtothesenewproportionssothatallcolumnsfil ltheavailabledisplayareaofthecontrol.Programmaticresizing isusefultoavoidperformancepenaltieswithcontinuousresizin g.Itisalsousefultoprovideinitialsizesforuser-resizable rows,columns,andheaders,andforcolumnfillmode.Youwilltyp icallycalltheprogrammaticresizingmethodsatspecifictimes. Forexample,youmightprogrammaticallyresizeallcolumnsimmedi atelyafterloadingdata,oryoumightprogrammaticallyresizea specificrowafteraparticularcellvaluehasbeenmodified.5.3. 5CustomizingContent-basedSizingBehaviorYoucancustomizesizi ngbehaviorswhenworkingwithderivedDataGridViewcell,row,an dcolumntypesbyoverridingtheDataGridViewCell.GetPreferredSiz e(),DataGridViewRow.GetPreferredHeight(),orDataGridViewColumn. GetPreferredWidth()methodsorbycallingprotectedresizingmeth odoverloadsinaderivedDataGridViewcontrol.Theprotectedres izingmethodoverloadsaredesignedtoworkinpairstoachievea nidealcellheight-to-widthratio,avoidingoverlywideortall cells.Forexample,ifyoucalltheAutoResizeRows(DataGridViewAu toSizeRowsMode,Boolean)overloadoftheAutoResizeRowsmethodand passinavalueoffalsefortheBooleanparameter,theoverload willcalculatetheidealheightsandwidthsforcellsintherow ,butitwilladjusttherowheightsonly.Youmustthencallthe AutoResizeColumnsmethodtoadjustthecolumnwidthstothecalc ulatedideal.5.3.6Content-basedSizingOptionsTheenumerationsu sedbysizingpropertiesandmethodshavesimilarvaluesforcont ent-basedsizing.Withthesevalues,youcanlimitwhichcellsar eusedtocalculatethepreferredsizes.Forallsizingenumerati ons,valueswithnamesthatrefertodisplayedcellslimittheir calculationstocellsindisplayedrows.Excludingrowsisuseful toavoidaperformancepenaltywhenyouareworkingwithalarge quantityofrows.Youcanalsorestrictcalculationstocellval uesinheaderornonheadercells.5.4SelectionmodesTheDataGridV iewcontrolprovidesyouwithavarietyofoptionsforconfigurin ghowuserscanselectcells,rows,andcolumns.Forexample,you canenablesingleormultipleselection,selectionofwholerows orcolumnswhenusersclickcells,orselectionofwholerowsor columnsonlywhenusersclicktheirheaders,whichenablescell selectionaswell.Ifyouwanttoprovideyourownuserinterface forselection,youcandisableordinaryselectionandhandleall selectionprogrammatically.Additionally,youcanenableuserst ocopytheselectedvaluestotheClipboard.Sometimesyouwantyo urapplicationtoperformactionsbasedonuserselectionswithin aDataGridViewcontrol.Dependingontheactions,youmaywantt orestrictthekindsofselectionthatarepossible.Forexample, supposeyourapplicationcanprintareportforthecurrentlyse lectedrecord.Inthiscase,youmaywanttoconfiguretheDataGr idViewcontrolsothatclickinganywherewithinarowalwayssele ctstheentirerow,andsothatonlyonerowatatimecanbesel ected.YoucanspecifytheselectionsallowedbysettingtheSelec tionModepropertytooneofthefollowingDataGridViewSelectionMo deenumerationvalues.DataGridViewSelectionModevalueDescriptionC ellSelect单击单元格以选中它,行列标题不能用于选择。ColumnHeaderSelect单击单元格以选中它,单击列标题选中 整列。此时列标题不能用于排序。FullColumnSelect单击单元格或列标题会选中它们所在的列,此时列标题不能用于排序。Ful lRowSelect单击单元格或行标题会选中它们所在的行。RowHeaderSelectDGV的默认选择模式,单击单元格选中该单元 格,单击行标题则选中整行。注意:在运行时改变选择模式会自动清除当前选择的内容。Bydefault,userscansel ectmultiplerows,columns,orcellsbydraggingwiththemouse, pressingCTRLorSHIFTwhileselectingtoextendormodifyasele ction,orclickingthetop-leftheadercelltoselectallcellsi nthecontrol.Topreventthisbehavior,settheMultiSelectprop ertytofalse.TheFullRowSelectandRowHeaderSelectmodesallowu serstodeleterowsbyselectingthemandpressingtheDELETEkey .Userscandeleterowsonlywhenthecurrentcellisnotinedit mode,theAllowUserToDeleteRowspropertyissettotrue,andthe underlyingdatasourcesupportsuser-drivenrowdeletion.Notet hatthesesettingsdonotpreventprogrammaticrowdeletion.5.4.1 ProgrammaticSelectionThecurrentselectionmoderestrictstheb ehaviorofprogrammaticselectionaswellasuserselection.You canchangethecurrentselectionprogrammaticallybysettingthe Selectedpropertyofanycells,rows,orcolumnspresentintheD ataGridViewcontrol.Youcanalsoselectallcellsinthecontrol throughtheSelectAllmethod,dependingontheselectionmode.T ocleartheselection,usetheClearSelectionmethod.IftheMulti Selectpropertyissettotrue,youcanaddDataGridViewelements toorremovethemfromtheselectionbychangingtheSelectedpr opertyoftheelement.Otherwise,settingtheSelectedpropertyt otrueforoneelementautomaticallyremovesotherelementsfrom theselection.注意:改变CurrentCell属性的值不会改变当前选择的内容。通过SelectedCells、Sel ectedRows和SelectedColumns属性你可以访问当前选中的单元格、行和列。不过当所有单元格都被选中的时候,使用这些 属性效率会比较低,为此可首先使用AreAllCellsSelected方法查看是否已选中全部单元格。此外,访问这些属性来查看选中单 元格、行和列的数目效率也比较低,此时应该使用GetCellCount、GetRowCount和GetColumnCount方法,传 给它们的参数为DataGridViewElementStates.Selected。5.5滚动(Scrolling)DataGr idView毫无疑问地会提供对水平和垂直滚动条的支持,它同时也支持使用鼠标滚轮进行垂直滚动。水平方向的滚动基于像素值,而垂直方向的 滚动则基于行的索引,DataGridView不支持垂直方向的基于像素值的滚动。5.5.1ScrolleventAsyous crolltheDataGridViewraisestheScrolleventthatallowsyouto benotifiedthatscrollingisoccurring.TheOrientationpropert yonthescrolleventargsletsyouknowthescrolldirection.5.5 .2ScrollbarsTheDataGridViewprovidesaccesstothescrollbars thatitdisplaysviatheprotectedHorizontalScrollBarandVertic alScrollBarproperties.AccessingtheseScrollBarcontrolsdirect lyallowyoutohavefinercontroloverscrolling.5.5.3Scrolling PropertiesThereareasetofpropertiesthatprovidegreaterlev elofdetailsonhowtheDataGridViewisscrolled.Thediagramhi ghlightsthesepropertiesandtheirvaluesatthisstate.Thepro pertiesareread/writeexceptfortheFirstDisplayedScrollingColu mnHiddenWidthandVerticalScrollingOffsetproperties.5.6SortingB ydefault,userscansortthedatainaDataGridViewcontrolbyc lickingtheheaderofatextboxcolumn.YoucanmodifytheSortM odepropertyofspecificcolumnstoallowuserstosortbyother columntypeswhenitmakessensetodoso.Youcanalsosortthe dataprogrammaticallybyanycolumn,orbymultiplecolumns.DataG ridViewcolumnshavethreesortmodes.Thesortmodeforeachcol umnisspecifiedthroughtheSortModepropertyofthecolumn,whi chcanbesettooneofthefollowingDataGridViewColumnSortMode enumerationvalues.DataGridViewColumnSortModevalueDescriptionAut omaticDefaultfortextboxcolumns.Unlesscolumnheadersareuse dforselection,clickingthecolumnheaderautomaticallysortst he?DataGridView?bythiscolumnanddisplaysaglyphindicatingth esortorder.NotSortableDefaultfornon–textboxcolumns.Youcan sortthiscolumnprogrammatically;however,itisnotintendedf orsorting,sonospaceisreservedforthesortingglyph.Program maticYoucansortthiscolumnprogrammatically,andspaceisrese rvedforthesortingglyph.Youmightwanttochangethesortmode foracolumnthatdefaultstoNotSortableifitcontainsvalues thatcanbemeaningfullyordered.Forexample,ifyouhaveadata basecolumncontainingnumbersthatrepresentitemstates,youca ndisplaythesenumbersascorrespondingiconsbybindinganimag ecolumntothedatabasecolumn.Youcanthenchangethenumerica lcellvaluesintoimagedisplayvaluesinahandlerfortheCell Formattingevent.Inthiscase,settingtheSortModepropertyto Automaticwillenableyouruserstosortthecolumn.Automaticso rtingwillenableyouruserstogroupitemsthathavethesamest ateevenifthestatescorrespondingtothenumbersdonothavea naturalsequence.Checkboxcolumnsareanotherexamplewhereau tomaticsortingisusefulforgroupingitemsinthesamestate.Yo ucansortaDataGridViewprogrammaticallybythevaluesinanyc olumnorinmultiplecolumns,regardlessoftheSortModesettings .Programmaticsortingisusefulwhenyouwanttoprovideyourow nuserinterface(UI)forsortingorwhenyouwanttoimplementc ustomsorting.ProvidingyourownsortingUIisuseful,forexamp le,whenyousettheDataGridViewselectionmodetoenablecolumn headerselection.Inthiscase,althoughthecolumnheaderscann otbeusedforsorting,youstillwanttheheaderstodisplaythe appropriatesortingglyph,soyouwouldsettheSortModepropert ytoProgrammatic.Columnssettoprogrammaticsortmodedonotau tomaticallydisplayasortingglyph.Forthesecolumns,youmust displaytheglyphyourselfbysettingtheDataGridViewColumnHeade rCell.SortGlyphDirectionproperty.Thisisnecessaryifyouwant flexibilityincustomsorting.Forexample,ifyousorttheDataG ridViewbymultiplecolumns,youmightwanttodisplaymultiples ortingglyphsornosortingglyph.Althoughyoucanprogrammatical lysortaDataGridViewbyanycolumn,somecolumns,suchasbutto ncolumns,mightnotcontainvaluesthatcanbemeaningfullyorde red.Forthesecolumns,aSortModepropertysettingofNotSortabl eindicatesthatitwillneverbeusedforsorting,sothereisn oneedtoreservespaceintheheaderforthesortingglyph.When aDataGridViewissorted,youcandetermineboththesortcolumn andthesortorderbycheckingthevaluesoftheSortedColumnand SortOrderproperties.Thesevaluesarenotmeaningfulafteracu stomsortingoperation.Formoreinformationaboutcustomsorting ,seetheCustomSortingsectionlaterinthistopic.WhenaDataG ridViewcontrolcontainingbothboundandunboundcolumnsissort ed,thevaluesintheunboundcolumnscannotbemaintainedautoma tically.Tomaintainthesevalues,youmustimplementvirtualmod ebysettingtheVirtualModepropertytotrueandhandlingtheCe llValueNeededandCellValuePushedevents.5.6.1ProgrammaticSorti ngYoucansortaDataGridViewprogrammaticallybycallingitsSor tmethod.TheSort(DataGridViewColumn,ListSortDirection)overload oftheSortmethodtakesaDataGridViewColumnandaListSortDirec tionenumerationvalueasparameters.Thisoverloadisusefulwhe nsortingbycolumnswithvaluesthatcanbemeaningfullyordered ,butwhichyoudonotwanttoconfigureforautomaticsorting.W henyoucallthisoverloadandpassinacolumnwithaSortModep ropertyvalueofDataGridViewColumnSortMode.Automatic,theSorted ColumnandSortOrderpropertiesaresetautomaticallyandtheapp ropriatesortingglyphappearsinthecolumnheader.Note:?Whenth eDataGridViewcontrolisboundtoanexternaldatasourcebyset tingtheDataSourceproperty,theSort(DataGridViewColumn,ListSor tDirection)methodoverloaddoesnotworkforunboundcolumns.Ad ditionally,whentheVirtualModepropertyistrue,youcancallt hisoverloadonlyforboundcolumns.Todeterminewhetheracolum nisdata-bound,checktheIsDataBoundpropertyvalue.Sortingun boundcolumnsinboundmodeisnotsupported.5.6.2CustomSorting YoucancustomizeDataGridViewbyusingtheSort(IComparer)overl oadoftheSortmethodorbyhandlingtheSortCompareevent.TheS ort(IComparer)methodoverloadtakesaninstanceofaclassthat implementstheIComparerinterfaceasaparameter.Thisoverload isusefulwhenyouwanttoprovidecustomsorting;forexample,w henthevaluesinacolumndonothaveanaturalsortorderorwh enthenaturalsortorderisinappropriate.Inthiscase,youcan notuseautomaticsorting,butyoumightstillwantyourusersto sortbyclickingthecolumnheaders.Youcancallthisoverload inahandlerfortheColumnHeaderMouseClickeventifyoudonotu secolumnheadersforselection.Note:?TheSort(IComparer)method overloadworksonlywhentheDataGridViewcontrolisnotboundto anexternaldatasourceandtheVirtualModepropertyvalueisfa lse.Tocustomizesortingforcolumnsboundtoanexternaldatas ource,youmustusethesortingoperationsprovidedbythedatas ource.Invirtualmode,youmustprovideyourownsortingoperati onsforunboundcolumns.TousetheSort(IComparer)methodoverloa d,youmustcreateyourownclassthatimplementstheICompareri nterface.ThisinterfacerequiresyourclasstoimplementtheICo mparer.Compare(Object)method,towhichtheDataGridViewpassesD ataGridViewRowobjectsasinputwhentheSort(IComparer)methodo verloadiscalled.Withthis,youcancalculatethecorrectrowo rderingbasedonthevaluesinanycolumn.TheSort(IComparer)met hodoverloaddoesnotsettheSortedColumnandSortOrderproperti es,soyoumustalwayssettheDataGridViewColumnHeaderCell.SortG lyphDirectionpropertytodisplaythesortingglyph.Asanalterna tivetotheSort(IComparer)methodoverload,youcanprovidecust omsortingbyimplementingahandlerfortheSortCompareevent.T hiseventoccurswhenusersclicktheheadersofcolumnsconfigur edforautomaticsortingorwhenyoucalltheSort(DataGridViewCo lumn,ListSortDirection)overloadoftheSortmethod.Theeventoc cursforeachpairofrowsinthecontrol,enablingyoutocalcul atetheircorrectorder.Note:?TheSortCompareeventdoesnotoccu rwhentheDataSourcepropertyissetorwhentheVirtualModepro pertyvalueistrue.5.6.3?Commonquestionsandscenarios1)?http:/ /www.cnblogs.cc2/如何避免用户对列排序?2)?http://www.cnblogs.cc2/如何针对多个列排序?5 .7BorderstylesWiththeDataGridViewcontrol,youcancustomize theappearanceofthecontrol''sborderandgridlinestoimprovet heuserexperience.Youcanmodifythegridlinecolorandthecon trolborderstyleinadditiontotheborderstylesforthecells withinthecontrol.ThegridlinecoloriscontrolledviatheGrid Colorproperty.Youcanalsoapplydifferentcellborderstylesf orordinarycells,rowheadercells,andcolumnheadercells.For advancedborderstylestheDataGridViewprovidestheadvancedbo rderstylepropertiesaswell.?Note:?Thegridlinecolorisusedo nlywiththeSingle,SingleHorizontal,andSingleVerticalvalues oftheDataGridViewCellBorderStyleenumerationandtheSingleval ueoftheDataGridViewHeaderBorderStyleenumeration.Theotherva luesoftheseenumerationsusecolorsspecifiedbytheoperating system.Additionally,whenvisualstylesareenabledonWindowsX Pandabove,theGridColorpropertyvalueisnotused.5.7.1Stand ardBorderStylesStandardborderstylesarecontrolledviatheCe llBorderStyle,RowHeadersBorderStyle,andColumnHeadersBorderStyl eproperties.Thefollowingtableidentifiesthestandardborders tylesavailableviathe:BorderStylevalueDescriptionFixed3DAthr ee-dimensionalborder.FixedSingleAsingle-lineborder.NoneNobord er.5.7.2AdvancedBorderStylesTheDataGridViewcontrolallowsyo utofullycustomizeitsappearance,includingthebordersofthe cellsandheaders.TheDataGridViewhasCellBorderStyle,ColumnH eadersBorderStyle,andRowHeadersBorderStylepropertiesthatallo wyoutosettheappearanceofthecellborder.However,ifyoun eedtofurthercustomizetheborders,theDataGridViewAdvancedBor derStyleclassallowsyoutosetthestyleoftheborderonthei ndividualsidesofthecells.TheLeft,Right,Top,andBottompr opertiesofDataGridViewAdvancedBorderStylerepresenttheleft,r ight,top,andbottomborderofacell,respectively.Youcanset thesepropertiesontheAdvancedCellBorderStyle,AdvancedColumnH eadersBorderStyle,AdvancedRowHeadersBorderStylepropertiesofth eDataGridViewtoproducevariousappearancesforthebordersbet weenthecells.Thefollowingtableidentifiestheadvancedborder stylesavailablethatcanbesetfortheleft,right,topandbo ttomparts.Notethatsomecombinationsarenotvalid.BorderStyle valueDescriptionInsetAthree-dimensionalborder.InsetDoubleAsin gle-lineborder.NoneNoborder.NotSetTheborderisnotsetOutsetA single-lineraisedborderOutsetDoubleAdouble-lineraisedborderO utsetPartialAsingle-linebordercontainingaraisedportionSingl eAsingle-lineborder5.8Enter-EditmodesBydefault,userscaned itthecontentsofthecurrentDataGridViewtextboxcellbytypi nginitorpressingF2.Thisputsthecellineditmodeifallo fthefollowingconditionsaremet:Theunderlyingdatasourcesup portsediting.TheDataGridViewcontrolisenabled.TheEditModepr opertyvalueisnotEditProgrammatically.TheReadOnlyproperties ofthecell,row,column,andcontrolareallsettofalse.Inedi tmode,theusercanchangethecellvalueandpressENTERtocom mitthechangeorESCtorevertthecelltoitsoriginalvalue.Yo ucanconfigureaDataGridViewcontrolsothatacellentersedit modeassoonasitbecomesthecurrentcell.Thebehaviorofthe ENTERandESCkeysisunchangedinthiscase,butthecellremai nsineditmodeafterthevalueiscommittedorreverted.Youcan alsoconfigurethecontrolsothatcellsentereditmodeonlywh enuserstypeinthecelloronlywhenuserspressF2.Finally,y oucanpreventcellsfromenteringeditmodeexceptwhenyoucall theBeginEditmethod.Thefollowingtabledescribesthedifferent editmodesavailable:EditModevalueDescriptionEditOnEnterEditing beginswhenthecellreceivesfocus.Thismodeisusefulwhenpr essingtheTABkeytoentervaluesacrossarow,orwhenpressing theENTERkeytoentervaluesdownacolumn.EditOnF2Editingbegi nswhenF2ispressedwhilethecellhasfocus.Thismodeplaces theselectionpointattheendofthecellcontents.EditOnKeystro keEditingbeginswhenanyalphanumerickeyispressedwhilethec ellhasfocus.EditOnKeystrokeOrF2Editingbeginswhenanyalphanum erickeyorF2ispressedwhilethecellhasfocus.EditProgrammat icallyEditingbeginsonlywhentheBeginEditmethodiscalled.5.9 ClipboardcopymodesWhenyouenablecellcopying,youmakethed atainyourDataGridViewcontroleasilyaccessibletootherappli cationsthroughtheClipboard.TheDataGridViewcontrolcopiesth etextrepresentationofeachselectedcelltotheClipboard.Thi svalueisthecellvalueconvertedtoastringor,forimagecel ls,thevalueoftheDescriptionproperty.Thecontentisthenad dedtotheClipboardastab-delimitedtextvaluesforpastingint oapplicationslikeNotepadandExcel,andasanHTML-formattedt ableforpastingintoapplicationslikeWord.Youcanconfigurece llcopyingtocopycellvaluesonly,toincluderowandcolumnhe adertextintheClipboarddata,ortoincludeheadertextonlyw henusersselectentirerowsorcolumns.Thefollowingtableident ifiesthedifferentclipboardcopymodes:ClipboardCopymodesDesc riptionDisableCopyingtotheClipboardisdisabled.EnableAlwaysIn cludeHeaderTextThetextvaluesofselectedcellscanbecopiedto theClipboard.Headertextisincludedforrowsandcolumnsthat containselectedcells.EnableWithAutoHeaderTextThetextvalueso fselectedcellscanbecopiedtotheClipboard.Roworcolumnhe adertextisincludedforrowsorcolumnsthatcontainselectedc ellsonlywhentheSelectionModepropertyissettoRowHeaderSele ctorColumnHeaderSelectandatleastoneheaderisselected.Enab leWithoutHeaderTextThetextvaluesofselectedcellscanbecopie dtotheClipboard.Headertextisnotincluded.Dependingonthe selectionmode,userscanselectmultipledisconnectedgroupsof cells.WhenausercopiescellstotheClipboard,rowsandcolumn swithnoselectedcellsarenotcopied.Allotherrowsorcolumn sbecomerowsandcolumnsinthetableofdatacopiedtotheClip board.Unselectedcellsintheserowsorcolumnsarecopiedasbl ankplaceholderstotheClipboard.Whenuserscopycontent,theDa taGridViewcontroladdsaDataObjecttotheClipboard.Thisdata objectisretrievedfromtheGetClipboardContent()method.Youca ncallthismethodwhenyouwanttoprogrammaticallyaddthedata objecttotheClipboard.TheGetClipboardContent()methodretrie vesvaluesforindividualcellsbycallingtheDataGridViewCell.G etClipboardContent()method.Youcanoverrideeitherorbothoft hesemethodsinderivedclassestocustomizethelayoutofcopied cellsortosupportadditionaldataformats.5.10Frozencolumns/ rowsWhenusersviewdatasometimestheyneedtorefertoasingle columnorsetofcolumnsfrequently.Forexample,whendisplayin gatableofcustomerinformationthatcontainsmanycolumns,it isusefultodisplaythecustomernameatalltimeswhileenablin gothercolumnstoscrolloutsidethevisibleregion.Toachievet hisbehavior,youcanfreezecolumnsinthecontrol.Thisisdone viasettingtheFrozenpropertyonthecolumnorrow.Whenyouf reezeacolumn,allthecolumnstoitsleft(ortoitsrightinr ight-to-leftlanguagescripts)arefrozenaswell.Frozencolumns remaininplacewhileallothercolumnscanscroll.Rowsactin similarfashion:allrowsbeforethefrozenrowarefrozenaswel landremaininplacewhilethenonfrozenrowscanscroll.5.11I mplementingCustomcellsandeditingcontrols/cellsYoucanimplem enttheIDataGridViewEditingCellinterfaceinyourderivedcellc lasstocreateacelltypethathaseditingfunctionalitybutdoe snothostacontrolineditingmode.Tocreateacontrolthatyo ucanhostinacellineditingmode,youcanimplementtheIData GridViewEditingControlinterfaceinaclassderivedfromControl. 5.11.1IDataGridViewEditingControlCellsthatsupportadvancededi tingfunctionalitytypicallyuseahostedcontrolthatisderived fromaWindowsFormscontrol.Thisinterfaceisimplementedbye ditingcontrols,suchasDataGridViewComboBoxEditingControlandD ataGridViewTextBoxEditingControl,thatarehostedbythecorrespo ndingDataGridViewcells,suchasDataGridViewComboBoxCellandDa taGridViewTextBoxCell,whentheyareineditmode.Celltypesthat canthathosteditingcontrolssettheirEditTypepropertytoa Typerepresentingtheeditingcontroltype.5.11.2IDataGridViewEd itingCellThisinterfaceisimplementedbyclassestoprovideaus erinterface(UI)forspecifyingvalueswithouthostinganeditin gcontrol.TheUIinthiscaseisdisplayedregardlessofwhether thecellisineditmode.TheDataGridViewCheckBoxCellisanexa mpleofacellthatimplementstheIDataGridViewEditingCellinter face.Othercelltypes,suchasDataGridViewButtonCell,providea UIbutdonotstoreuser-specifiedvalues.Inthiscase,thecell typedoesnotimplementIDataGridViewEditingCellorhostanedit ingcontrol.5.12VirtualmodeWithvirtualmode,youcanmanageth einteractionbetweentheDataGridViewcontrolandacustomdata cache.Toimplementvirtualmode,settheVirtualModepropertyto trueandhandleoneormoreoftheeventsdescribedinthistopi c.YouwilltypicallyhandleatleasttheCellValueNeededevent, whichenablesthecontrollookupvaluesinthedatacache.5.12.1 BoundModeandVirtualModeVirtualmodeisnecessaryonlywheny ouneedtosupplementorreplaceboundmode.Inboundmode,yous ettheDataSourcepropertyandthecontrolautomaticallyloadsth edatafromthespecifiedsourceandsubmitsuserchangesbackto it.Youcancontrolwhichoftheboundcolumnsaredisplayed,an dthedatasourceitselftypicallyhandlesoperationssuchassor ting.5.12.2SupplementingBoundModeYoucansupplementboundmode bydisplayingunboundcolumnsalongwiththeboundcolumns.This issometimescalled"mixedmode"andisusefulfordisplayingth ingslikecalculatedvaluesoruser-interface(UI)controls.Becau seunboundcolumnsareoutsidethedatasource,theyareignored bythedatasource''ssortingoperations.Therefore,whenyouenab lesortinginmixedmode,youmustmanagetheunbounddatainal ocalcacheandimplementvirtualmodetolettheDataGridViewcon trolinteractwithit.5.12.3Commonquestionsandscenarios1)?htt p://www.cnblogs.cc2/HowdoIshowunbounddataalongwithboundd ata?2)?http://www.cnblogs.cc2/HowdoIshowdatathatcomesfrom twotables?5.12.4ReplacingBoundModeIfboundmodedoesnotmeet yourperformanceneeds,youcanmanageallyourdatainacustom cachethroughvirtual-modeeventhandlers.Forexample,youcan usevirtualmodetoimplementajust-in-timedataloadingmechani smthatretrievesonlyasmuchdatafromanetworkeddatabaseas isnecessaryforoptimalperformance.Thisscenarioisparticular lyusefulwhenworkingwithlargeamountsofdataoveraslownet workconnectionorwithclientmachinesthathavealimitedamoun tofRAMorstoragespace.5.12.5Virtual-ModeEventsIfyourdata isread-only,theCellValueNeededeventmaybetheonlyeventyou willneedtohandle.Additionalvirtual-modeeventsletyouenab lespecificfunctionalitylikeuseredits,rowadditionanddelet ion,androw-leveltransactions.SomestandardDataGridViewevents (suchaseventsthatoccurwhenusersaddordeleterows,orwhe ncellvaluesareedited,parsed,validated,orformatted)areus efulinvirtualmode,aswell.Youcanalsohandleeventsthatle tyoumaintainvaluesnottypicallystoredinabounddatasource ,suchascellToolTiptext,cellandrowerrortext,cellandro wshortcutmenudata,androwheightdata.Thefollowingeventsoc curonlywhentheVirtualModepropertyissettotrue.EventDescri ptionCellValueNeededUsedbythecontroltoretrieveacellvalue fromthedatacachefordisplay.Thiseventoccursonlyforcells inunboundcolumns.CellValuePushedUsedbythecontroltocommit userinputforacelltothedatacache.Thiseventoccursonlyf orcellsinunboundcolumns.CalltheUpdateCellValuemethodwhen changingacachedvalueoutsideofa?CellValuePushed?eventhandle rtoensurethatthecurrentvalueisdisplayedinthecontrolan dtoapplyanyautomaticsizingmodescurrentlyineffect.NewRowN eededUsedbythecontroltoindicatetheneedforanewrowinth edatacache.RowDirtyStateNeededUsedbythecontroltodetermine whetherarowhasanyuncommittedchanges.CancelRowEditUsedbyth econtroltoindicatethatarowshouldreverttoitscachedvalu es.Thefollowingeventsareusefulinvirtualmode,butcanbeus edregardlessoftheVirtualModepropertysetting.EventsDescripti onUserDeletingRowUserDeletedRowRowsRemovedRowsAddedUsedbytheco ntroltoindicatewhenrowsaredeletedoradded,lettingyouupd atethedatacacheaccordingly.CellFormattingCellParsingCellValid atingCellValidatedRowValidatingRowValidatedUsedbythecontrolto formatcellvaluesfordisplayandtoparseandvalidateuserin put.CellToolTipTextNeededUsedbythecontroltoretrievecellToo lTiptextwhenthe?DataSource?propertyissetorthe?VirtualMode? propertyis?true.CellToolTipsaredisplayedonlywhentheShowCe llToolTipspropertyvalueis?true.CellErrorTextNeededRowErrorText NeededUsedbythecontroltoretrievecellorrowerrortextwhen the?DataSource?propertyissetorthe?VirtualMode?propertyis?tr ue.CalltheUpdateCellErrorTextmethodortheUpdateRowErrorText methodwhenyouchangethecellorrowerrortexttoensurethat thecurrentvalueisdisplayedinthecontrol.Cellandrowerror glyphsaredisplayedwhentheShowCellErrorsandShowRowErrorspr opertyvaluesare?true.CellContextMenuStripNeededRowContextMenuSt ripNeededUsedbythecontroltoretrieveacellorrowContextMen uStripwhenthecontrol?DataSource?propertyissetorthe?Virtual Mode?propertyis?true.RowHeightInfoNeededRowHeightInfoPushedUsed bythecontroltoretrieveorstorerowheightinformationinthe datacache.CalltheUpdateRowHeightInfomethodwhenchangingth ecachedrowheightinformationoutsideofa?RowHeightInfoPushed? eventhandlertoensurethatthecurrentvalueisusedinthedis playofthecontrol.5.12.6BestPracticesinVirtualModeIfyoua reimplementingvirtualmodeinordertoworkefficientlywithla rgeamountsofdata,youwillalsowanttoensurethatyouarewo rkingefficientlywiththeDataGridViewcontrolitself.Seebelow formoreinformationonbestpractices5.13容量(Capacity)Ingenera l,theDataGridViewdoesnothaveanyhard-codedcapacitylimits. Thegridwasdesignedsothatmoreandmorecontentcanbeadded asmachinesbecomefasterandhavemorememory.Thatsaid,theg ridwasnotdesignedtodealwithlargenumberofcolumns.Ifyou addmorethan300columnsyouwillstarttonoticeadegradation inperformanceasourperformancetuningofthegridwasnotdes ignedforthis.Ifyouneedagridwithlargeamountsofcolumns thentheDataGridViewmightnotmeetyourneeds.Regardingthenu mberofrowssupported,theDataGridViewisboundbymemoryconst raints.WhenusingVirtualmodeyoucaneasilysupportover2mil lionrows.Checkoutthebestpracticessectionbelowforinforma tiononthingsyoucando(andnotdo)toimprovememoryusagean dperformance.6最佳实践(BestPractices)TheDataGridViewcontrolisde signedtoprovidemaximumscalability.Ifyouneedtodisplaylar geamountsofdata,youshouldfollowtheguidelinesdescribedin thistopictoavoidconsuminglargeamountsofmemoryordegradi ngtheresponsivenessoftheuserinterface(UI).6.1UsingCellS tylesEfficientlyEachcell,row,andcolumncanhaveitsownstyl einformation.StyleinformationisstoredinDataGridViewCellSty leobjects.CreatingcellstyleobjectsformanyindividualDataG ridViewelementscanbeinefficient,especiallywhenworkingwith largeamountsofdata.Toavoidaperformanceimpact,usethefo llowingguidelines:Avoidsettingcellstylepropertiesforindivi dualDataGridViewCellorDataGridViewRowobjects.Thisincludest herowobjectspecifiedbytheRowTemplateproperty.Eachnewrow thatisclonedfromtherowtemplatewillreceiveitsowncopyo fthetemplate''scellstyleobject.Formaximumscalability,set cellstylepropertiesattheDataGridViewlevel.Forexample,set theDefaultCellStylepropertyratherthantheDataGridViewCell.S tyleproperty.Ifsomecellsrequireformattingotherthandefault formatting,usethesameDataGridViewCellStyleinstanceacrossg roupsofcells,rows,orcolumns.Avoiddirectlysettingproperti esoftypeDataGridViewCellStyleonindividualcells,rows,andc olumns.Foranexampleofcellstylesharing,seeHowto:SetDef aultCellStylesfortheWindowsFormsDataGridViewControl.You canalsoavoidaperformancepenaltywhensettingcellstylesind ividuallybyhandlingtheCellFormattingeventhandler.Foranex ample,seeHowto:CustomizeDataFormattingintheWindowsForms DataGridViewControl.Whendeterminingacell''sstyle,usetheDa taGridViewCell.InheritedStylepropertyratherthantheDataGridVi ewCell.Styleproperty.AccessingtheStylepropertycreatesanew instanceoftheDataGridViewCellStyleclassifthepropertyhas notalreadybeenused.Additionally,thisobjectmightnotcontai nthecompletestyleinformationforthecellifsomestylesare inheritedfromtherow,column,orcontrol.Formoreinformation aboutcellstyleinheritance,seeCellStylesintheWindowsForm sDataGridViewControl.6.2UsingShortcutMenusEfficientlyEachc ell,row,andcolumncanhaveitsownshortcutmenu.Shortcutmen usintheDataGridViewcontrolarerepresentedbyContextMenuStri pcontrols.Justaswithcellstyleobjects,creatingshortcutme nusformanyindividualDataGridViewelementswillnegativelyimp actperformance.Toavoidthispenalty,usethefollowingguideli nes:Avoidcreatingshortcutmenusforindividualcellsandrows. Thisincludestherowtemplate,whichisclonedalongwithitssh ortcutmenuwhennewrowsareaddedtothecontrol.Formaximums calability,useonlythecontrol''sContextMenuStrippropertytos pecifyasingleshortcutmenufortheentirecontrol.Ifyourequi remultipleshortcutmenusformultiplerowsorcells,handlethe CellContextMenuStripNeededorRowContextMenuStripNeededevents. Theseeventsletyoumanagetheshortcutmenuobjectsyourself,a llowingyoutotuneperformance.6.3UsingAutomaticResizingEffi cientlyRows,columns,andheaderscanbeautomaticallyresizedas cellcontentchangessothattheentirecontentsofcellsaredi splayedwithoutclipping.Changingsizingmodescanalsoresizer ows,columns,andheaders.Todeterminethecorrectsize,theDat aGridViewcontrolmustexaminethevalueofeachcellthatitmus taccommodate.Whenworkingwithlargedatasets,thisanalysisc annegativelyimpacttheperformanceofthecontrolwhenautomati cresizingoccurs.Toavoidperformancepenalties,usethefollow ingguidelines:AvoidusingautomaticsizingonaDataGridViewcon trolwithalargesetofrows.Ifyoudouseautomaticsizing,on lyresizebasedonthedisplayedrows.Useonlythedisplayedrow sinvirtualmodeaswell.Forrowsandcolumns,usetheDisplayed CellsorDisplayedCellsExceptHeadersfieldoftheDataGridViewAut oSizeRowsMode,DataGridViewAutoSizeColumnsMode,andDataGridViewA utoSizeColumnModeenumerations.Forrowheaders,usetheAutoSizeT oDisplayedHeadersorAutoSizeToFirstHeaderfieldoftheDataGridV iewRowHeadersWidthSizeModeenumeration.Formaximumscalability,t urnoffautomaticsizinganduseprogrammaticresizing.6.4Using theSelectedCells,Rows,andColumnsCollectionsEfficientlyThe SelectedCellscollectiondoesnotperformefficientlywithlarge selections.TheSelectedRowsandSelectedColumnscollectionscan alsobeinefficient,althoughtoalesserdegreebecausetherear emanyfewerrowsthancellsinatypicalDataGridViewcontrol,a ndmanyfewercolumnsthanrows.Toavoidperformancepenaltiesw henworkingwiththesecollections,usethefollowingguidelines: TodeterminewhetherallthecellsintheDataGridViewhavebeen selectedbeforeyouaccessthecontentsoftheSelectedCellscoll ection,checkthereturnvalueoftheAreAllCellsSelectedmethod. Note,however,thatthismethodcancauserowstobecomeunshare d.Formoreinformation,seethenextsection.AvoidusingtheCou ntpropertyoftheDataGridViewSelectedCellCollectiontodetermin ethenumberofselectedcells.Instead,usetheGetCellCount()m ethodandpassintheDataGridViewElementStates.Selectedvalue.S imilarly,usetheDataGridViewRowCollection.GetRowCount()andDat aGridViewColumnCollection.GetColumnCount()methodstodeterminet henumberofselectedelements,ratherthanaccessingtheselecte drowandcolumncollections.Avoidcell-basedselectionmodes.In stead,settheSelectionModepropertytoFullRowSelectorFullCol umnSelect.6.5UsingSharedRowsEfficientmemoryuseisachievedi ntheDataGridViewcontrolthroughsharedrows.Rowswillsharea smuchinformationabouttheirappearanceandbehavioraspossibl ebysharinginstancesoftheDataGridViewRowclass.Whilesharing rowinstancessavesmemory,rowscaneasilybecomeunshared.For example,wheneverauserinteractsdirectlywithacell,itsrow becomesunshared.Becausethiscannotbeavoided,theguidelines inthistopicareusefulonlywhenworkingwithverylargeamoun tsofdataandonlywhenuserswillinteractwitharelativelysm allpartofthedataeachtimeyourprogramisrun.Arowcannotb esharedinanunboundDataGridViewcontrolifanyofitscellsc ontainvalues.WhentheDataGridViewcontrolisboundtoanexter naldatasourceorwhenyouimplementvirtualmodeandprovideyo urowndatasource,thecellvaluesarestoredoutsidethecontro lratherthanincellobjects,allowingtherowstobeshared.Ar owobjectcanonlybesharedifthestateofallitscellscanbe determinedfromthestateoftherowandthestatesofthecolum nscontainingthecells.Ifyouchangethestateofacellsotha titcannolongerbededucedfromthestateofitsrowandcolum n,therowcannotbeshared.Forexample,arowcannotbesharedi nanyofthefollowingsituations:Therowcontainsasingleselec tedcellthatisnotinaselectedcolumn.Therowcontainsacell withitsToolTipTextorContextMenuStrippropertiesset.Therow containsaDataGridViewComboBoxCellwithitsItemspropertyset.I nboundmodeorvirtualmode,youcanprovideToolTipsandshortc utmenusforindividualcellsbyhandlingtheCellToolTipTextNeed edandCellContextMenuStripNeededevents.TheDataGridViewcontrol willautomaticallyattempttousesharedrowswheneverrowsare addedtotheDataGridViewRowCollection.Usethefollowingguideli nestoensurethatrowsareshared:AvoidcallingtheAdd(Object[] )overloadoftheAddmethodandtheInsert(Object[])overloadof theInsertmethodoftheRowscollection.Theseoverloadsautoma ticallycreateunsharedrows.Besurethattherowspecifiedinth eRowTemplatepropertycanbesharedinthefollowingcases:When callingtheAdd()orAdd(Int)overloadsoftheAddmethodorthe Insert(Int,Int)overloadoftheInsertmethodoftheRowscollec tion.WhenincreasingthevalueoftheRowCountproperty.Whensett ingtheDataSourceproperty.Besurethattherowindicatedbythe indexSourceparametercanbesharedwhencallingtheAddCopy,Ad dCopies,InsertCopy,andInsertCopiesmethodsoftheRowscollect ion.Besurethatthespecifiedroworrowscanbesharedwhencal lingtheAdd(DataGridViewRow)overloadoftheAddmethod,theAdd Rangemethod,theInsert(Int32,DataGridViewRow)overloadoftheI nsertmethod,andtheInsertRangemethodoftheRowscollection.T odeterminewhetherarowisshared,usetheDataGridViewRowColle ction.SharedRow(Int)methodtoretrievetherowobject,andthen checktheobject''sIndexproperty.SharedrowsalwayshaveanInd expropertyvalueof–1.6.6PreventingRowsfromBecomingUnshare dSharedrowscanbecomeunsharedasaresultofcodeoruseracti on.Toavoidaperformanceimpact,youshouldavoidcausingrows tobecomeunshared.Duringapplicationdevelopment,youcanhandl etheRowUnsharedeventtodeterminewhenrowsbecomeunshared.T hisisusefulwhendebuggingrow-sharingproblems.Topreventrows frombecomingunshared,usethefollowingguidelines:Avoidindex ingtheRowscollectionoriteratingthroughitwithaforeachlo op.Youwillnottypicallyneedtoaccessrowsdirectly.DataGrid Viewmethodsthatoperateonrowstakerowindexargumentsrather thanrowinstances.Additionally,handlersforrow-relatedevent sreceiveeventargumentobjectswithrowpropertiesthatyoucan usetomanipulaterowswithoutcausingthemtobecomeunshared.I fyouneedtoaccessarowobject,usetheDataGridViewRowCollect ion.SharedRow(Int)methodandpassintherow''sactualindex.Not e,however,thatmodifyingasharedrowobjectretrievedthrough thismethodwillmodifyalltherowsthatsharethisobject.The rowfornewrecordsisnotsharedwithotherrows,however,soit willnotbeaffectedwhenyoumodifyanyotherrow.Notealsoth atdifferentrowsrepresentedbyasharedrowmayhavedifferent shortcutmenus.Toretrievethecorrectshortcutmenufromashar edrowinstance,usetheGetContextMenuStripmethodandpassint herow''sactualindex.Ifyouaccessthesharedrow''sContextMenu Strippropertyinstead,itwillusethesharedrowindexof-1an dwillnotretrievethecorrectshortcutmenu.Avoidindexingthe DataGridViewRow.Cellscollection.Accessingacelldirectlywill causeitsparentrowtobecomeunshared,instantiatinganewData GridViewRow.Handlersforcell-relatedeventsreceiveeventargum entobjectswithcellpropertiesthatyoucanusetomanipulatec ellswithoutcausingrowstobecomeunshared.Youcanalsouseth eCurrentCellAddresspropertytoretrievetherowandcolumninde xesofthecurrentcellwithoutaccessingthecelldirectly.Avoid cell-basedselectionmodes.Thesemodescauserowstobecomeuns hared.Instead,settheSelectionModepropertytoDataGridViewSel ectionMode.FullRowSelectorDataGridViewSelectionMode.FullColumnS elect.DonothandletheDataGridViewRowCollection.CollectionChang edorRowStateChangedevents.Theseeventscauserowstobecomeu nshared.Also,donotcalltheDataGridViewRowCollection.OnCollec tionChanged(CollectionChangeEventArgs)orOnRowStateChanged(Int,D ataGridViewRowStateChangedEventArgs)methods,whichraisethesee vents.DonotaccesstheSelectedCellscollectionwhentheSelecti onModepropertyvalueisFullColumnSelect,ColumnHeaderSelect,Fu llRowSelect,orRowHeaderSelect.Thiscausesallselectedrowsto becomeunshared.DonotcalltheAreAllCellsSelected(boolean)met hod.Thismethodcancauserowstobecomeunshared.Donotcallth eSelectAllmethodwhentheSelectionModepropertyvalueisCellS elect.Thiscausesallrowstobecomeunshared.DonotsettheRea dOnlyorSelectedpropertyofacelltofalsewhenthecorrespond ingpropertyinitscolumnissettotrue.Thiscausesallrowst obecomeunshared.DonotaccesstheDataGridViewRowCollection.Lis tproperty.Thiscausesallrowstobecomeunshared.Donotcallt heSort(IComparer)overloadoftheSortmethod.Sortingwithacu stomcomparercausesallrowstobecomeunshared.你可以检索各种属性的DataGr idView,DataGridViewColumn的,的DataGridViewRow,和DataGridViewCell类及其派 生类DataGridViewCellStyle对象。如果其中一个属性尚未设置,检索其值将创建一个新的DataGridViewCel lStyle对象。您还可以将自己的DataGridViewCellStyle对象,并将它们分配给这些属性。您可以通过共享的Data GridViewCellStyle避免不必要的在多个DataGridView元素对象的样式信息的重复。因为在控制,列集的风格,和行 各层面渗透到细胞水平的水平了,你还可以通过设置避免只在每个级别,从不同层次上的风格样式属性重复。这是进行了更详细的样式继承节如下。 下表列出了获取或设置DataGridViewCellStyle对象的主要属性。物业类的描述的DefaultCellStyle的Da taGridView,DataGridViewColumn的,的DataGridViewRow和派生类获取或设置所有单元格中使用的 整个控制(包括标题单元格)的默认风格,在一列,或在一排。?RowsDefaultCellStyle的DataGridView获取或 设置默认单元格的控件中的所有行使用的样式。这不包括标题单元格。AlternatingRowsDefaultCellStyle的Da taGridView获取或设置默认单元格的行交替使用的样式的控制。用于创建一个总账般的效果。?RowHeadersDefaultC ellStyle的DataGridView获取或设置该控件的默认单元格的行标题使用的样式。由当前主题重写如果启用视觉样式。?Col umnHeadersDefaultCellStyle的DataGridView获取或设置该控件的默认单元格的列标题使用的样式。由当 前主题重写如果启用视觉样式。?风格的DataGridViewCell和派生类获取或设置在细胞水平上指定的样式。这些样式覆盖上级继承 的。InheritedStyle的DataGridViewCell,的DataGridViewRow,DataGridViewCo lumn和派生类获取所有的风格,包括从上级继承样式应用到当前单元格,行或列。如上所述,得到了一个样式属性的值会自动实例化一个新的D ataGridViewCellStyle对象如果属性尚未以前设置。为了避免不必要地创建这些对象,行和列类有一个HasDefault CellStyle属性,您可以检查以确定是否DefaultCellStyle属性已设置。同样,细胞类具有HasStyle属性,指示 是否Style属性已设置。每个属性的样式上有一个相应的PropertyNameChangedDataGridView控件的事件。 对于行,列和单元格属性,事件名称开头“行”,“列”,或“细胞”(例如,RowDefaultCellStyleChanged)。这些 事件发生时,每一个对应的样式属性设置为不同的DataGridViewCellStyle对象。这些事件不会发生当您检索从样式属性的D ataGridViewCellStyle对象,并修改其属性值。为了应对变化的单元格样式对象本身,处理CellStyleConten tChanged事件。?5.1.3样式继承每个DataGridViewCell的会从它的InheritedStyle属性它的外观。 DataGridViewCellStyle对象的此属性返回继承从类型DataGridViewCellStyle的属性层次的价值。 下面列出了这些属性的顺序在其中非头细胞InheritedStyle获取其值。1。DataGridViewCell.Style2。 DataGridViewRow.DefaultCellStyle3。AlternatingRowsDefaultCellSty le(只适用于奇数行单元格指数)4。RowsDefaultCellStyle5。DataGridViewColumn.Defa ultCellStyle6。的DefaultCellStyle对于行和列标题单元格,InheritedStyle属性填充的值是从给 定的顺序在下面的列表源属性。1。DataGridViewCell.Style2。ColumnHeadersDefaultCel lStyle或RowHeadersDefaultCellStyle3。的DefaultCellStyle下图演示了这个过程。您还可 以通过特定的行和列继承的样式。列InheritedStyle财产继承了以下属性的值。1。DataGridViewColumn.D efaultCellStyle2。的DefaultCellStyle该行InheritedStyle财产继承了以下属性的值。1。 DataGridViewRow.DefaultCellStyle2。AlternatingRowsDefaultCellStyl e(只适用于奇数行单元格指数)3。RowsDefaultCellStyle4。的DefaultCellStyle对于每一个由In heritedStyle属性返回一个DataGridViewCellStyle对象属性,属性值是从第一个单元格样式列表,在适当的相 应的属性设置为除DataGridViewCellStyle类的默认值等。下表说明了一个例子细胞ForeColor属性的值是从包含列 继承。类型DataGridViewCellStyle的范例前景色为检索对象的价值属性DataGridViewCell.Style Color.EmptyDataGridViewRow.DefaultCellStyleColor.RedAlternatingR owsDefaultCellStyleColor.EmptyRowsDefaultCellStyleColor.EmptyDa taGridViewColumn.DefaultCellStyleColor.DarkBlue的DefaultCellStyle Color.Black在这种情况下,从单元格的行System.Drawing.Color.Red值是第一个在名单上的实际价值。这 成为该单元格的InheritedStyleForeColor属性值。下图说明了不同的DataGridViewCellStyle属 性可以继承他们的价值观不同的地方。通过利用样式继承的优势,可以提供,而无需指定相同的信息在多个地方为整个控制适当的样式。虽然标题单 元格样式继承中所描述的身份参加,由DataGridView控件的ColumnHeadersDefaultCellStyle和Row HeadersDefaultCellStyle属性返回的对象具有初始属性值覆盖由DefaultCellStyle属性返回的对象的属 性值。如果你想由DefaultCellStyle属性返回的对象设置为适用于行和列标题的属性,你必须设置由ColumnHeaders DefaultCellStyle和RowHeadersDefaultCellStyle属性返回的DataGridViewCellS tyle类为默认显示对象的相应属性。注:如果启用视觉样式,行和列标题(除TopLeftHeaderCell)会自动由当前的主题风格 ,覆盖了这些属性所指定的任何样式。设置EnableHeadersVisualStyle属性为false,如果你想标题不使用XP的视 觉样式。该DataGridViewButtonColumn,DataGridViewImageColumn和DataGridVie wCheckBoxColumn类型还初始化由列DefaultCellStyle属性返回的对象的一些值。有关详细信息,请参见这些类型 的参考文件。?5.1.4设置样式动态要自定义,特别值的单元格的样式,实施一项CellFormatting事件的处理程序。此事件的处 理程序收到的DataGridViewCellFormattingEventArgs类型的参数。此对象包含的属性,让您确定单元格的值 被格式化,其在DataGridView控制地沿。此对象还包含一个CellStyle属性,初始化为单元格的InheritedStyl e属性值被格式化。您可以修改单元格样式属性来指定样式的信息适合单元格的值和位置。注:RowPrePaint和RowPostPain t事件还接收事件数据的DataGridViewCellStyle对象,但他们的案件,这是该行InheritedStyle属性为只读 目的副本,以及它的变更不会影响控制。您还可以动态改变以因应如CellMouseEnter和CellMouseLeave活动活动单个 细胞的风格。例如,在为CellMouseEnter事件处理程序中,你可以存储单元格的背景颜色(通过细胞的Style属性检索)的当前 值,然后将其设置为一个新的色彩,将突出显示单元格时在它的鼠标悬停。在为CellMouseLeave事件处理程序,然后就可以恢复到原 来的背景颜色值。注:缓存在细胞的Style属性中存储的值是重要的,无论是否设置特定的样式值。如果您暂时替换样式设置,恢复到原来的“ 未设置”国家保障,细胞会返回从更高的层次继承的样式设置。如果您需要确定在一个单元的实际效果风格的风格无论是继承,使用单元格的Inh eritedStyle属性。?5.2风俗画DataGridView控件提供了多个属性,您可以用它来调整外观和基本行为(外观和感觉) 的单元格,行和列。如果您有要求,超越的DataGridViewCellStyle类的功能的时候,你可以执行单元格或行的内容自定义绘 制。单元格和行画自己,你可以处理各种如RowPrePaint的DataGridView,CellPainting和RowPostP aint绘画活动。?5.2.1油漆件自定义绘制的一个重要部分是油漆部件的概念。该DataGridViewPainParts枚举用于 指定哪些部分细胞油漆。枚举值可结合在一起,有一个单元不油漆涂料或特定部分。这里是不同的部分:?PaintPart为例前景色为检索对 象的价值所有的所有部件都画背景单元格的背景是画使用单元格的背景颜色(1)边境的边界是画ContentBackground单元格的内 容是画背景的一部分。(2)ContentForeground单元格的内容的前景部分是画(2)ErrorIcon错误图标画重点加强 对单元格焦点矩形画没有任何部分是画(1)SelectionBackground画的背景是,如果选中该单元格被选中。注释1)如果一个 单元格不绘制其背景则没有什么是画。一个行或列执行任何作画,确保至少细胞的背景画,或者您执行您自己的自定义背景画,否则仍然是无效的矩 形(着色)。2)每个单元确定什么前景为内容的背景和内容,如下面的列表描述的那样涂料:细胞类型的内容前景内容背景文本框单元格的文字是 画没有画扣式电池文字画,画按钮组合框单元格的文字是画,画组合框选中复选框是画没有画链接单元格文本链接是没有画成画图像细胞图像是画没 有画标题栏标题栏文字排序雕画行头行头文字Current行三角形,编辑铅笔和新行的指标是画5.2.2行预油漆涂料和邮政业您可以通过处 理一个或DataGridView.RowPrePaint和DataGridView.RowPostPaint两个事件的DataGr idView行的外观。这些活动的设计,让你可以画只有你想在DataGridView控制,而让其余的油漆。例如,如果你想画一个自定义 的背景,你可以处理DataGridView.RowPrePaint事件,并让自己的单个细胞涂料前景的内容。在RowPrePaint 事件你可以设置PaintParts事件参数属性来轻松定制的细胞如何油漆。例如,如果您想保留的任何选择,或从绘画的焦点细胞,你Row PrePaint事件将设置像这样PaintParts属性:?e.PaintParts=DataGridViewPaintPar ts.All&?(DataGridViewPaintParts.Focus|DataGridViewPaintParts.Sel ectionBackground);这也可以写成:e.PaintParts=(DataGridViewPaintParts.Ba ckground|DataGridViewPaintParts.Border|DataGridViewPaintParts.C ontentBackground|DataGridViewPaintParts.ContentForeground|DataG ridViewPaintParts.ErrorIcon);或者,也可以让自己和油漆的细胞中添加一个自定义事件处理程序的DataGr idView.RowPostPaint前景的内容。您还可以禁用油漆和涂料的一切细胞在DataGridView.RowPrePain t自己的事件处理程序?5.3AutosizingDataGridView控件提供了自定义的列和行的调整大小行为的许多选项。通常情 况下,DataGridView单元格不调整的基础上的内容。相反,她们还会给任何显示值比电池大。如果内容可以作为一个字符串显示,该单 元格显示在工具提示。默认情况下,用户可以用鼠标拖动来显示更多信息行,列和标题分隔。用户还可以双击一个分频器来自动调整相关的行,列或 标题带其内容为基础。列共享默认情况下,控制可用宽度??,所以,如果用户可以调整控制,例如,如果它是一个可调整大小的对接形式,他们也 可以更改列的所有可用的展示空间。DataGridView控件提供的属性,方法和事件,使您可以自定义或禁用这些用户导向的所有行为。此 外,您可以通过编程方式调整行,列和标题,以适合他们的内容,也可以将其配置为自动调整自己只要其内容的变化。?常见问题:1)如何调整最 后一列的宽度使其占据网格的剩余客户区?5.3.1在Windows窗体DataGridView控件调整大小选项DataGridVie w行,列和标题可以改变许多不同的事件结果的大小。下表显示了这些事件。发生说明用户调整大小用户可以通过拖动或双击行,列或标题分隔大小 的调整。控制调整在列填充模式,列宽度变化时,控制宽度的改变,例如,当控件停靠到其父形式和用户调整的表格。细胞在基于内容的自动调整大 小模式值的变化,大小变化,以适应新的显示值。方法调用的方案内容为基础的大小可以让用户调整大小的基础上伺机在方法调用时单元格值。属性 设置也可以设置特定的高度和宽度值。默认情况下,启用用户调整大小,自动调整大小被禁用,是更广泛的单元格值比列剪裁。下表显示的情况,你 可以用它来调整预设的行为,或使用特定的调整大小选项来达到特定的效果。方案实施使用列填充显示同样,在一列,占据了整个宽度的控制数量相 对较少,而不显示水平滚动条大小的数据模式。AutoSizeColumnsMode属性设置为Fill。使用列填充不同大小显示值模式 。AutoSizeColumnsMode属性设置为Fill。初始化设置列的FillWeight属性或调用控件AutoResize Columns灌装后用数据控制方法相对列宽度。?使用列填充不同的重要性与价值模式。AutoSizeColumnsMode属性设置 为Fill。设置大量列的MinimumWidth值,必须始终显示的数据部分或使用一个尺寸的选择以外填补特定列模式。?使用列填充模式 ,以避免显示控件的背景。设置最后一列AutoSizeMode属性为Fill和使用其他尺寸的其他列选项。显示一个固定宽度的列,如图标 或ID列。AutoSizeMode设置为None,可调整大小为False的列。初始化设置width属性,或者调用控件AutoRe sizeColumn后用数据填??充它的宽度控制方法。?大小时自动调整单元格内容的变化,以避免裁减和优化使用空间。设置一个自动调整 大小属性的值,表示一个基于内容的大小调整模式。为了避免性能下降时,大量的数据工作,使用一个尺寸模式,只计算显示的行。?调整大小以适 应显示的行值,以避免性能下降时,许多行工作。使用自动或编程调整大小适当的调整大小模式枚举值。要调整大小,以适应在新显示的行滚动时, 请在一个滚动的事件处理程序大小的方法价值。定制用户双击调整大小,以便显示的行的值只有在确定新的尺寸,要求在一个RowDivider DoubleClick或ColumnDividerDoubleClick事件处理程序大小的方法。?只有在特定时间调整大小以适应单元 格内容,以避免性能罚款或启用用户调整大小。调用事件处理程序中的基于内容的大小的方法。例如,使用DataBindingComplet e事件绑定后初始化大小和处理CellValidated或CellValueChanged事件调整大小,以弥补用户编辑或绑定的数据源 的变化。?调整多行单元格内容的行高。确保该列的宽度是用于显示相应的文本段落并使用自动或编程的基于内容的行大小来调整高度。另外,还要 确保与细胞显示多内容使用的WrapMode细胞式的真实价值。?通常,你会使用自动调整大小模式,以维持列列宽或将其设置为特定宽度前行 高进行调整。5.3.2用鼠标调整大小默认情况下,用户可以调整行,列和标题不使用自动大小调整模式对细胞价值观为基础。为了防止其他模式 ,例如列填充模式,缩放用户设置一个或以下的DataGridView属性:?AllowUserToResizeColumns?All owUserToResizeRows?ColumnHeadersHeightSizeMode?RowHeadersWidthSiz eMode您还可以防止大小设置其Resizable属性由单个行或列的用户。默认情况下,Resizable属性值是基于对列Allow UserToResizeColumns属性值和属性值的行AllowUserToResizeRows。如果你明确地设置大小可调整为T rue或False,但是,指定的值控制值覆盖该行或列中。设置调整大小toNotSet恢复继承。由于NotSet还原值继承,Res izable属性永远不会返回NotSet值,除非该行或列并没有被添加到一个DataGridView控制。如果您需要确定是否行或列R esizable属性值继承,审查其国家的财产。如果该国值包括ResizableSet标志,Resizable属性值不继承。?5.3 .3自动调整大小有两种自动调整大小在DataGridView控制类型:列填充模式和基于内容的自动调整大小。列填充模式导致在控件中可 见列,以填补该控件的显示区域的宽度。如需这个模式的详细信息,请参阅列填充模式一节。您还可以配置行,列和标题的大小自动调整以适应其单 元格内容。在这种情况下,大小调整单元格内容时发生变化。注意:如果你保持在自定义数据缓存单元格的值使用虚拟模式,自动调整大小时发生用 户编辑单元格值,但不会发生改变时,外面的一CellValuePushed事件处理缓存值。在这种情况下,调用UpdateCellVa lue方法强制控制更新单元格的显示和应用当前的自动调整大小模式。如果基于内容的自动调整大小仅用于也就是说,对于行,但不列,或列,但 不是行和的WrapMode还启用一维启用,大小调整时,也会发生在其他方面的变化。例如,如果行,但不列自动调整大小和配置的WrapM ode已启用,用户可以拖动列分隔来改变一个列和行高将自动调整使细胞内容仍然充分显示宽度。如果配置基于内容的自动调整大小行和列和的W rapMode启用,DataGridView控件将调整单元格内容改变大小时,将使用一个理想的细胞高度对宽度的比例,当计算新的大小。 要配置标题和行和列不会覆盖控制值,浆纱模式设置一个或多个以下的DataGridView属性:?ColumnHeadersHeigh tSizeMode?RowHeadersWidthSizeMode?AutoSizeColumnsMode?AutoSizeRow sMo??de若要重写控件的列大小的单个列模式,将其AutoSizeMode属性的值比NotSet等。一列大小调整模式实际上是取决 于它的InheritedAutoSizeMode财产。这个属性的值是基于列的AutoSizeMode属性值,除非该值是NotSet ,在这种情况下控制的AutoSizeColumnsMode值继承。请谨慎使用基于内容的自动调整大小时,大量数据的工作。为了避免性能 下降,使用自动调整大小模式,而不是分析计算中的每一行控制的基础上所显示的行唯一的大小。为获得最佳性能,使用编程调整大小,而不是让你 在特定的时间可以调整,如新的数据后立即加载。基于内容的自动调整大小模式不会影响行,列或标题,你已经通过设置行或列的Visible属 性或控制RowHeadersVisible或ColumnHeadersVisible属性为false隐藏。例如,如果列是隐藏后,它 会自动调整以适应一个大单元格的值,隐藏的列将不会改变它的大小,如果大所在的行单元格的值将被删除。自动调整大小时,不会出现能见度的变 化,因此更改列的Visible属性返回true,将不会强迫它重新计算其大小的当前内容为基础。方案内容为基础的大小影响的行,列和标题 不论其知名度。5.3.4编程调整大小禁用自动调整大小时,您可以通过编程设置精确的宽度通过下列属性或行,列或标题的高度:?RowHe adersWidth?ColumnHeadersHeight?DataGridViewRow.Height?DataGridVie wColumn.Width您还可以通过编程调整行,列和标题,以适合他们的内容使用下列方法:?AutoResizeColumn?Au toResizeColumns?AutoResizeColumnHeadersHeight?AutoResizeRow?AutoR esizeRows?AutoResizeRowHeadersWidth这些方法将调整行,列或标题一次,而不是连续的大小配置它们。新 的大小自动计算显示没有剪辑的所有单元格内容。当您以编程方式调整列有填充InheritedAutoSizeMode属性值,但是,计算 出的基于内容的宽度按比例用于调整列FillWeight属性值,实际列宽,然后根据这些新的计算比例,让所有列填充该控件的可用显示区域 。编程调整大小可以有效避免连续调整大小的性能损失。它也为用户提供有用的调整大小的行,列和标题的初始大小,列填充模式。你通常会在特定 时间调用的方案调整方法。例如,您可能编程加载数据后,立即调整所有列,或者你可能一个特定的编程方式调整后的行某单元格值已被修改。5. 3.5自定义基于内容的调整大小行为您可以自定义大小的行为时,派生的DataGridView单元格,行和列类型的工作通过覆盖Data GridViewCell.GetPreferredSize(),DataGridViewRow.GetPreferredHeigh t(),或DataGridViewColumn.GetPreferredWidth()方法或通过调用DataGridView的保护 ,在派生大小的方法重载控制。受保护的大小的方法重载的目的是在对工作,以实现理想的单元格高度与宽度的比例,避免过于宽或高的细胞。例如 ,如果调用AutoResizeRows(DataGridViewAutoSizeRowsMo??de,布尔)的AutoResize Rows方法重载并传入一个虚假的布尔参数的值,过载将计算在该行细胞的理想的高度和宽度,但它会调整行高而已。然后,您必须调用Auto ResizeColumns方法来调整列宽度以计算的理想选择。?5.3.6基于内容的调整大小选项由大小属性和方法使用的枚举有基于内容 的大小相似的价值观。有了这些值,你可以限制哪些细胞是用来计算首选大小。对于所有大小枚举,其名称是指显示的单元格的值限制在他们的计算 显示的行的单元格。不包括行是有用的,以避免性能损失,当您使用的是大量的行工作。您还可以限制的计算,以在页眉或nonheader细胞 的细胞值。?5.4选择模式DataGridView控件提供了一系列用于配置用户如何选择单元格,行和列的多种选择你。例如,您可以启用 单一或多重选择,全行或列的选择,当用户单击单元格,行或整列选择或仅当用户点击他们的标题,也使小区选择。如果您要提供您的选择自己的用 户界面,您可以禁用普通的选择和处理所有的编程选择。此外,还可以让用户选定的值复制到剪贴板。有时候你希望你的应用程序来执行的Data GridView控制范围内用户的选择为基础的行动。根据不同的操作,您可能希望限制的种类的选择都是可能的。例如,假设你的应用程序可以 打印出当前选中的记录报告。在这种情况下,您可能需要配置的DataGridView控件,以便在连续点击任何地方总是选择整行,所以这只 能有一个时间行可以被选中。您可以通过设置SelectionMode属性为下列DataGridViewSelectionMode枚举 值之一允许的选择。DataGridViewSelectionMode值描述CellSelect单击单元格以选中它,行列标题不能用于 选择。ColumnHeaderSelect单击单元格以选中它,单击列标题选中整列。此时列标题不能用于排序。FullColumnSe lect单击单元格或列标题会选中它们所在的列,此时列标题不能用于排序。FullRowSelect单击单元格或行标题会选中它们所在的 行。RowHeaderSelectDGV的默认选择模式,单击单元格选中该单元格,单击行标题则选中整行。注意:在运行时改变选择模式 会自动清除当前选择的内容。默认情况下,用户可以选择用鼠标拖动,按Ctrl或Shift的同时选择延长或修改的选择,或者点击左上角的标 题单元格来选择控件中的所有细胞的多个行,列或单元格。为了防止这种行为,设置为falseMultiSelect属性。该FullRo wSelect和RowHeaderSelect模式允许用户通过选择删除,再按DELETE键的行。用户可以删除行,只有在当前单元格不 处于编辑模式,AllowUserToDeleteRows属性设置为true,并且基础数据源支持用户驱动的行删除。请注意,这些设置不 会防止纲领性行删除。?5.4.1编程选择目前的选择模式限制了方案选择,以及用户的选择行为。你可以改变当前选择编程方式设置的任何单元 格,行或列在DataGridView控制选录的财产。您还可以选择通过SelectAll方法控制所有单元格,选择模式而定。要清除的选 择,使用ClearSelection方法。如果MultiSelect属性设置为true,则可以添加或删除DataGridView元 素从选择通过改变这些元素的Selected属性。否则,设置一个元素的Selected属性为true自动删除从选择的其他因素。注意: 改变CurrentCell属性的值不会改变当前选择的内容。通过SelectedCells,SelectedRows和的Select edColumns属性你可以访问当前选中的单元格,行和列。不过当所有单元格都被选中的时候,使用这些属性效率会比较低,为此可首先使用 AreAllCellsSelected方法查看是否已选中全部单元格。此外,访问这些属性来查看选中单元格,行和列的数目效率也比较低, 此时应该使用GetCellCount,GetRowCount和GetColumnCount方法,传给它们的参数为DataGridV iewElementStates.Selected。?5.5滚动(滚动)DataGridView中毫无疑问地会提供对水平和垂直滚动 条的支持,它同时也支持使用鼠标滚轮进行垂直滚动。水平方向的滚动基于像素值,而垂直方向的滚动则基于行的索引,不支持垂直的DataGr idView方向的基于像素值的滚动。?5.5.1Scroll事件当你滚动DataGridView的引发Scroll事件,让您被通 知滚动发生。对滚动事件参数定位属性可以让你知道滚动的方向。5.5.2滚动条DataGridView的滚动条可以访问,它通过保护Ho rizo??ntalScrollBar和VerticalScrollBar属性显示。ScrollBar控件直接访问这些让你拥有滚 动更好的控制。?5.5.3滚动属性有许多的属性,提供更大的详细程度如何设??置DataGridView的滚动。该图突出这些属性和在 这种状态下它们的值。这些属性的读/写除了FirstDisplayedScrollingColumnHiddenWidth和Vert icalScrollingOffset属性。5.6排序默认情况下,用户可以按一下文字方块的栏标题在DataGridView控件中的 数据。您可以修改特定列SortMode属性,允许用户通过其他列类型进行排序时,这样做是有道理的。您还可以通过编程对数据进行排序任何 列或多个列。DataGridView列有三种排序模式。每个列的排序模式是通过指定的列,它可以设置为以下DataGridViewCo lumnSortMode枚举值之一SortMode属性。?DataGridViewColumnSortMode值描述自动默认为文本 框列。除非列标头用于选择,单击列标题此列自动排序,并显示一个指示排序顺序字形的DataGridView。NotSortable默认 非文本框列。您可以按该列编程,但是,它不适合排序,所以没有空间为排序标志符号保留。编程您可以按该列编程和空间是为排序标志符号保留。 您可能要更改的列,默认为NotSortable如果它包含可以有意义有序值的排序方式。例如,如果你有一个数据库列包含表示项状态的数字 ,你可以显示一个图像列绑定到数据库列的这些数字对应的图标。然后,您可以改变一个CellFormatting事件处理程序将图像显示值 的数值单元格值。在这种情况下,设置SortMode属性,使您的用户自动排序列。自动分拣将使您的用户组项目,具有相同的状态,即使各国 所对应的数字没有一个自然顺序。复选框列是另一个例子,自动排序分组,在同一国家的项目有用。你可以在任何编程方式进行排序列中的值或多个 列的DataGridView,无论SortMode设置。编程排序是有用的当您想为排序或当你想实现自己的自定义排序用户界面(UI)。 提供自己的排序用户界面是有用的,例如,当您设置了DataGridView选择模式,使列标题选择。在这种情况下,虽然列标头不能用于排 序,你仍然想的标题来显示相应的排序标志符号,所以你会设置SortMode属性编程。列设置为编程排序模式不会自动显示排序标志符号。对 于这些列,你必须显示的字形通过设置DataGridViewColumnHeaderCell.SortGlyphDirection自 己的财产。这是必要的,如果你想在自定义排序的灵活性。例如,如果按多列DataGridView的,你可能要显示多个排序标志符号或无排 序标志符号。虽然您可以通过编程任意列进行排序的DataGridView,一些栏目,如按钮列,可能不包含可以有意义的有序值。对于这些 列,一个NotSortableSortMode属性设置表示,它将永远不会被用于排序的,所以没有必要储备为排序标志符号头空间。当D ataGridView的排序,你可以同时确定排序列和通过检查SortedColumn和SortOrder的属性的值进行排序。这些值 不是一个自定义排序操作??后,有意义的。有关自定义排序信息,请参见本主题中的自定义排序节后面。当DataGridView控件同时包 含绑定和未绑定列进行排序,在未绑定列的值不能自动维护。为了保持这些值,你必须执行VirtualMode属性设置为true,并处理C ellValueNeeded和CellValuePushed事件虚拟模式。?5.6.1编程排序您可以排序的DataGridView 编程方式调用它的排序方法。本的Sort(DataGridViewColumn,ListSortDirection)Sort方法重载 采用DataGridViewColumn和一个枚举值作为参数ListSortDirection。此重载时非常有用,可以通过与有意义 的命令,但你不想配置值的列自动分拣排序。当调用此重载并同一个DataGridViewColumnSortMode.Automati c的SortedColumn和SortOrder的性能SortMode属性值列通过自动设置和相应的排序标志符号出现在列标题。注意: 当DataGridView控件绑定通过设置DataSource属性到外部数据源,的Sort(DataGridViewColumn, ListSortDirection)方法重载不能用于未绑定列。此外,当VirtualMode属性为true,则可以只绑定列调用此重 载。要确定是否列是数据绑定,检查IsDataBound属性值。在绑定模式下未绑定列排序不受支持。?5.6.2自定义排序您可以通过使 用自定义的Sort(IComparer)Sort方法重载或通过处理DataGridView的SortCompare事件。的Sort (IComparer)方法重载采用一个实现类作为参数的IComparer接口的实例。此重载很有用,当您要提供自定义排序,例如,当在 一列中的值没有自然排序顺序或者当自然排序顺序是不适当的。在这种情况下,您不能使用自动排序,但您可能仍然希望用户通过点击排序列标题。 你还可以打电话为ColumnHeaderMouseClick此重载事件处理程序,如果你不使用选择栏标题。注意:的Sort(ICom parer)方法重载仅当DataGridView控件未绑定到外部数据源和VirtualMode属性值为false。要自定义绑定到外 部数据源的列排序,你必须使用排序的数据源提供的操作。在虚拟模式下,你必须为自己的未绑定列排序操作。要使用的Sort(ICompar er)方法重载,您必须创建自己的类实现IComparer接口。此接口要求您的类来实现IComparer.Compare(Objec t)方法,对此,作为输入传递时的DataGridView的Sort(IComparer)方法重载被称为DataGridViewRo w对象。有了这个,你可以计算出正确的行排序的基础上在任一列的值。的Sort(IComparer)方法重载不设置SortedColu mn和SortOrder的属性,所以你必须总是设置DataGridViewColumnHeaderCell.SortGlyphDi rection属性以显示排序标志符号。作为对的Sort(IComparer)方法重载替代方法,可以通过实施提供了SortCompa re事件处理程序自定义排序。此事件发生在用户单击列或配置自动分拣头当调用Sort方法的Sort(DataGridViewColum n,ListSortDirection)重载。事件发生时,每行一对在控制,使您能够计算它们的正确顺序。注:SortCompare事 件不会发生当DataSource属性设置或当VirtualMode属性值为true。5.6.3常见问题及案例1)如何避免用户对列排 序?2)如何针对多个列排序?5.7边框样式使用DataGridView控件,您可以自定义该控件的边框和网格线,以改善用户体验的外观 。您可以修改除了为细胞内控制边境网格线的颜色和样式的控件的边框样式。网格线颜色控制,通过GridColor财产。您还可以申请普通细 胞,行标题单元格和列标题单元格不同的单元格边框样式。对于先进的边框样式的DataGridView提供先进的边框样式的属性。注:网格 线颜色仅用于与DataGridViewCellBorderStyle枚举和枚举的DataGridViewHeaderBorderS tyle单值单,SingleHorizo??ntal和SingleVertical值。这些枚举的其他值使用由操作系统指定的颜色。此 外,当视觉样式的WindowsXP及以上的启用,GridColor属性值不被使用。?5.7.1标准边框样式边框样式控制标准通过C ellBorderStyle,RowHeadersBorderStyle和ColumnHeadersBorderStyle属性。下 表列出了标??准通过所提供的边框样式:边框值描述Fixed3D一个三维边框。FixedSingle单行边框。无无边框。5.7.2高 级边境风格DataGridView控件允许你完全自定义其外观,包括细胞和头的边界。DataGridView的有CellBorde rStyle,ColumnHeadersBorderStyle和RowHeadersBorderStyle属性,让您设置单元格边框 的外观。但是,如果您需要进一步定制边界,DataGridViewAdvancedBorderStyle类允许您设置单元格的个人双方 的边框样式。对DataGridViewAdvancedBorderStyle左,右,顶部和底部属性代表左,右,上,一个细胞和底部边 框,分别为。您可以设置在AdvancedCellBorderStyle,AdvancedColumnHeadersBorderSt yle,AdvancedRowHeadersBorderStyleDataGridView的属性这些属性产生的细胞之间的边界,展 现多种风采。下表列出了可用的先进的边框样式,可以设置为左,右,顶部和底部部分。请注意,某些组合是无效的。边框值描述嵌入一??个三维 边框。InsetDouble单行边框。无无边框。NotSet边界是没有设置一开始就是单行凸起边框OutsetDouble一个双线凸 起边框OutsetPartial单行边界包含凸起部分单单行边界5.8输入,编辑模式默认情况下,用户可以通过在编辑,或按F2键当前D ataGridView的文本框格的内容。这使得在编辑模式下,如果下列条件全部得到满足手机:?基础数据源支持编辑。?DataGrid View控件已启用。?将EditMode属性值不是EditProgrammatically。?单元格,行,列的ReadOnly属性 和控制,都设置为false。在编辑模式下,用户可以更改单元格的值,然后按Enter键提交更改或ESC细胞恢复到其原始值。您可以配置 一个DataGridView控件,以使单元格进入编辑模式,一旦它成为当前单元格。该ENTER键和ESC键的行为在这种情况下保持不变 ,但细胞仍然处于编辑模式后,该值被提交或还原。您还可以配置控制,使细胞进入编辑模式仅当用户键入单元格或只有当用户按下F2键。最后, 您可以阻止其进入编辑,除非你调用BeginEdit方法模式细胞。下表描述了不同的编辑模式可供选择:编辑模式值描述EditOnEnt er编辑开始时,细胞接收焦点。这种模式是有用的当按下TAB键,进入跨越行值,或当按下回车键,进入下一个列值。EditOnF2编辑开 始时按下F2键时,单元格具有焦点。此模式放置在单元格内容的末尾的选择点。开始编辑EditOnKeystroke当任何字母数字键被按 下,而细胞具有焦点。EditOnKeystrokeOrF2编辑开始时,任何字母数字键或F2键被按下,而细胞具有焦点。EditPro grammatically编辑时,才开始BeginEdit方法被调用。5.9剪贴板拷贝模式当你使细胞复制,你才能在DataGrid View控件的数据很容易接触到其他应用程序通过剪贴板。DataGridView控件复制到选定的单元格的每个剪贴板的文本表示。此值 是单元格的值转换为图像细胞,Description属性的值的字符串或。其内容后加入为制表符分隔的文本值的剪贴簿在诸如记事本和Exc el应用程序粘贴,并作为应用程序,如Word粘贴到HTML格式的表格。您可以配置单元格值复制到复制只,包括在剪贴板上的数据行和列标 题文本,或包含标题文本仅当用户选择整个行或列。下表列出了不同的剪贴板复制模式:剪贴板拷贝模式说明禁用复制到剪贴板被禁用。Enabl eAlwaysIncludeHeaderText所选单元格的文本值可以被复制到剪贴板。标题文字是否列入行和包含选定单元格的列。En ableWithAutoHeaderText所选单元格的文本值可以被复制到剪贴板。行或列标题的文本包含或包含的行只选择当Selec tionMode属性设置为RowHeaderSelect或ColumnHeaderSelect和至少一个头被选中单元格的列。?En ableWithoutHeaderText所选单元格的文本值可以被复制到剪贴板。标题文字是否不包括在内。在选择模式的不同,用户可以 选择多个不连续的细胞群。当用户复制到剪贴板细胞,行和列,没有选定的单元格不会被复制。所有其他行或列成为复制到剪贴板上的数据表的行和 列。在这些行或列未选定的单元格被复制到剪贴板作为空白占位符。当用户复制内容时,DataGridView控件添加到剪贴板DataOb ject中。此数据对象是取自GetClipboardContent()方法。你可以调用这个方法时,您希望以编程方式将数据添加对象到 剪贴板。该GetClipboardContent()方法通过调用DataGridViewCell.GetClipboardCont ent检索()方法为个别单元格的值。你可以重写派生类中任一这些方法或两个自定义复制的单元格的布局,或支持格式的其他数据。?5.10 冻结的列/行当用户查看数据有时他们需要参考一列或列集频繁。例如,当显示的客户信息表,其中包含许多列,显示是非常有用的在任何时候,客 户名称,同时使其他列可见区域之外的滚动。为了实现这一行为,您可以冻结在控制列。这是通过设置在列或行冻结的财产。当你冻结一列,所有列 在它的左边(或在从右到左的语言脚本右),冻结。冻结列留在原地,而所有其他列可以滚动。行以类似的方式行事:前行中的所有行被冻结的冻结 ,以及维持不变,而在非冰冻行可以滚动。?5.11实现自定义和编辑控制细胞/细胞您可以实现在你的派生类来创建一个细胞的细胞类型具有编 辑功能,但不承载的编辑模式控制IDataGridViewEditingCell接口。要创建一个控件,你可以在一个宿主细胞中的编辑模 式,可以实现从Control派生的类IDataGridViewEditingControl接口。?5.11.1IDataGrid ViewEditingControl支持先进的单元格编辑功能通常使用一个托管控件是从Windows窗体控件派生的。此接口由编辑控件 ,如DataGridViewComboBoxEditingControl和DataGridViewTextBoxEditingCo ntrol,这是由相应的DataGridView单元格,如的DataGridViewComboBoxCell和DataGridVi ewTextBoxCell,当他们处于编辑模式主持。单元格可以承载编辑控件设置其EditType属性类型,表示一个类型的编辑控件的 类型。5.11.2IDataGridViewEditingCell此接口的类没有提供存取指定的编辑控制值的用户界面(UI)。在这 种情况下用户界面显示无论是在细胞处于编辑模式。该DataGridViewCheckBoxCell的是一个细胞,它实现了IDataG ridViewEditingCell接口的例子。其他细胞类型,如的DataGridViewButtonCell,提供一个用户界面, 但不存储用户指定的值。在这种情况下,细胞类型不落实IDataGridViewEditingCell或主机一个编辑控制。?5.12虚 拟模式使用虚拟模式,您可以管理之间的DataGridView控件和自定义数据缓存交互。为了实现虚拟模式,设置VirtualMode 属性为true,并处理一个或本主题描述的事件更多。您通常处理至少CellValueNeeded事件,它使控件的外观在数据缓存值。? 5.12.1绑定模式和虚拟模式虚拟模式只有当你需要补充或替换绑定模式。在绑定模式下,可以设置DataSource属性和控制自动加载 从指定的源数据和提交给它的用户更改回来。您可以控制??哪些绑定列的显示方式,和一般的数据源本身处理,如排序操作。?5.12.2补充 绑定模式您可以通过显示补充随着绑定列绑定列绑定模式。这有时也被称为“混合模式”,是用来显示像计算值或用户界面(UI)控制的东西有用 。由于未绑定列之外的数据源,他们是忽视了数据源的排序操作。因此,当您在混合模式下启用排序,你必须管理一个本地缓存中绑定数据,并实现 虚拟模式,让DataGridView控件交互。?5.12.3常见问题及案例1)如何显示绑定的数据绑定以及数据?2)我怎样的数据显示 ,从两个表来?5.12.4更换绑定模式如果绑定模式无法满足您的性能需求,您可以通过虚拟管理模式的自定义事件处理程序缓存中的所有数据 。例如,你可以使用虚拟模式来实现一个公正的实时数据加载的机制,只是从一个网络数据库,获得最佳性能所必需的数据检索。这种情况是非常有 用的大量时,通过速度较慢的网络连接或与客户机的数据有一个内存或存储空间有限的工作。?5.12.5虚拟模式事件如果您的数据是只读的, CellValueNeeded事件可能是唯一的事件,你将需要处理。额外的虚拟模式事件让你启用特定的功能,如用户编辑,添加和删除行和 行级的交易。一些标准的DataGridView事件(如发生的事件当用户添加或删除行,或在编辑单元格值时,解析,验证,或者格式化)在 虚拟模式中非常有用,以及。你也可以处理事件,让你保持在一个通常不绑定的数据源中存储的值,如细胞提示文本,单元格和行的错误文本,单元 格和行的快捷菜单数据,和行高的数据。下列事件发生时,才VirtualMode属性设置为true。事件描述CellValueNeed ed由控制用于检索从显示数据高速缓存单元格的值。此事件只发生在未绑定列细胞。CellValuePushed由控制用于提交,可以向用 户输入的数据高速缓存单元。此事件只发生在未绑定列细胞。调用方法时UpdateCellValue更改之外的CellValuePush ed事件处理缓存值,以确保当前值显示在控件中的作用,并适用于目前所有自动调整大小模式。?NewRowNeeded由控件用来指示一个 数据高速缓存中的新行的需要。RowDirtyStateNeeded的控制,用来确定行是否有任何未提交的更改。CancelRowEd it使用的控制,表明该行应恢复其缓存的值。以下事件在虚拟模式中非常有用,但也可以使用了VirtualMode属性设置无关。事件的说 明UserDeletingRowUserDeletedRowRowsRemovedRowsAdded由控件用来指示行被删除或添加, 让您更新相应的数据高速缓存。CellFormattingCellParsingCellValidatingCellValidate dRowValidatingRowValidated使用的显示格式为单元格值和解析和验证用户输入控制。CellToolTipTex tNeeded由控制单元用于检索工具提示文本当DataSource属性设置或VirtualMode属性为true。工具提示显示细胞 只有在ShowCellToolTips属性值为true。CellErrorTextNeededRowErrorTextNeeded 的控制,用来检索单元格或行的错误文本当DataSource属性设置或VirtualMode属性为true。调用方法或UpdateR owErrorTextUpdateCellErrorText方法,当你更改单元格或行的错误文本,以确保当前值在控件中显示。细胞与 行的错误标志符号时显示ShowCellErrors和ShowRowErrors属性值是正确的。CellContextMenuStr ipNeededRowContextMenuStripNeeded由控制用于检索单元格或行的ContextMenuStrip当控件 的DataSource属性设置或VirtualMode属性为true。?RowHeightInfoNeededRowHeightI nfoPushed由控制用于检索或存储数据的高速缓存行中高度信息。调用方法时改变UpdateRowHeightInfo缓存行之外的 RowHeightInfoPushed事件处理的高度信息,以确保当前值在控制显示器使用。?5.12.6在虚拟模式下的最佳实践如果要 实现虚拟模式,以工作效率的大量数据,你也想确保您正在使用DataGridView控件本身的效率。请参阅下面的最佳做法的信息5.13 容量(容量)一般来说,在DataGridView没有硬编码容量限制。网格的设计,使越来越多的内容可以添加的机器变得更快,并有更多的 内存。尽管如此,格并不是用来处理大量列。如果您添加超过300行,您会开始注意到在随着我们对电网的表现却不是这样的优化性能的退化。如 果你需要一个大量的列格,然后在DataGridView可能不符合您的需求。关于支持的行数时,DataGridView是受内存限制。 当使用虚拟模式,您可以轻松支持超过200万行。看看你可以做的事情(不要做),以提高内存的使用情况和性能的最佳做法的信息,下面一节。 6个最佳实践(最佳做法)DataGridView控件的设计提供最大的可扩展性。如果你需要显示大量数据,你应该按照本主题中所述,以避 免内存或有辱人格的用户界面(UI)的响应消耗大量的指导方针。?6.1使用高效单元格样式每个单元格,行和列可以有自己的样式信息。样式 信息存储在DataGridViewCellStyle对象。创造许多个人DataGridView元素单元格样式的对象可以是低效的,特 别是当大量数据的工作。为了避免性能的影响,请遵循下列准则:?避免为单个DataGridViewCell或DataGridViewR ow对象的单元格样式属性。这包括由RowTemplate行对象属性中指定。每个新行是从行模板克隆将接收其模板的单元格样式对象的副本 。为了获得最大的可扩展性,设置在DataGridView的单元格样式属性的水平。例如,设置DefaultCellStyle属性,而 不是DataGridViewCell.Style财产。?如果某些细胞需要的格式以外的默认格式,在使用相同的单元格,行或列组的Dat aGridViewCellStyle实例。避免直接设置个别类型的单元格,行和列DataGridViewCellStyle属性。对于 一个单元格样式共享的例子,请参见如何:设置单元格样式的默认为Windows窗体DataGridView控件。您也可避免性能下降时, 通过处理CellFormatting设置事件处理个别单元格样式。有关示例,请参见如何:自定义的数据格式在Windows窗体Data GridView控件。?当确定一个单元格样式,使用DataGridViewCell.InheritedStyle财产,而不是Dat aGridViewCell.Style财产。访问Style属性创建一个DataGridViewCellStyle类的新实例如果该属 性还没有被使用。此外,这个对象可能不包含完整的样式为单元格的信息,如果有些样式从行,列或控件继承。欲了解更多有关单元格样式继承的详 细信息,请参阅细胞在Windows窗体DataGridView控件样式。?6.2使用高效快捷菜单每个单元格,行和列可以有它自己的快 捷菜单。在DataGridView控制快捷菜单ContextMenuStrip控件代表。这正好与单元格样式对象作为,创造许多个人D ataGridView元素的快捷菜单将产生负面影响性能。为了避免这种损失,请使用下列准则:?避免为单个单元格和行的快捷菜单。这包括 行模板,这是克隆了它的快捷方式菜单时,新行被添加到控件一起。为了获得最大的可扩展性,仅使用控件的ContextMenuStrip属 性来指定整个控制单一的快捷菜单。?如果您需要多个行或多种细胞的快捷菜单,处理CellContextMenuStripNeeded或 RowContextMenuStripNeeded事件。这些事件让您管理自己的快捷菜单对象,让您调整性能。6.3使用自动调整大小高 效行,列和标题可以自动调整大小的单元格内容的变化,使细胞中的全部内容都没有剪辑显示。更改调整大小模式也可以调整行,列和标题。要确定 正确的大小,DataGridView控件必须检查每一个细胞,它必须适应值。当处理大量数据时,这种分析可以产生负面影响控制性能的自动 调整大小时发生。为了避免性能下降,请遵循下列准则:?避免使用带有大量行集的DataGridView控制自动调整大小。如果你使用自动 大小调整,只调整的基础上所显示的行。在虚拟模式下只使用所显示的行以及。对行和列?,使用DataGridViewAutoSizeRo wsMo??de,DataGridViewAutoSizeColumnsMode和DataGridViewAutoSizeColu mnMode枚举的DisplayedCells或DisplayedCellsExceptHeaders领域。?对于行头,使用该Da taGridViewRowHeadersWidthSizeMode枚举AutoSizeToDisplayedHeaders或Aut oSizeToFirstHeader领域。为了获得最大的可扩展性?,关闭自动调整大小尺寸和使用方案。6.4使用选定的单元格,行和列 的集合高效SelectedCells集合不执行效率大选择。收藏的SelectedRows和SelectedColumns也可以是低 效的,但在较小的程度,因为有许多比细胞中的行数少一个典型的DataGridView控件,比列行少得多。为了避免性能下降与这些藏品时 ,请遵循下列准则:?要确定是否所有在DataGridView单元格已被选中,然后再访问该SelectedCells集合的内容,检查 AreAllCellsSelected方法的返回值。请注意,但是,这种方法可能会导致行成为非共享。有关详细信息,请参阅下一节。?避 免使用的DataGridViewSelectedCellCollectionCount属性来确定所选细胞的数量。相反,使用Get CellCount()方法并传入DataGridViewElementStates.Selected价值。同样,使用DataGri dViewRowCollection.GetRowCount()和DataGridViewColumnCollection.Get ColumnCount()方法来确定所选元素,而不是访问选定的行和列集合,数量。?避免细胞为基础的选择模式。相反,Selectio nMode属性设置为FullRowSelect或FullColumnSelect。6.5使用共享行实现有效的内存使用在通过共享行的 DataGridView控制。作为行会分享他们的外观和行为,尽可能通过DataGridViewRow类的共享实例的信息。虽然共享行 实例节省内存,很容易成为非共享行。例如,每当一个直接与用户交互的一个单元,它的行成为非共享。因为这是无法避免,在这个主题中的准则是 有用的,只有当工作与数据量非常大,只有当用户将与每一个数据你的程序运行时间的一小部分。阿行不能共享在未绑定的DataGridVie w控制,如果它的任何单元格包含值。当DataGridView控件绑定到外部数据源,或当您实现虚拟模式,并提供您自己的数据源,该单元 格值存储以外的控制,而不是在单元格对象,允许行被共享。行对象只能共享,如果它的所有细胞的状态可以从该行的状态和细胞列载的状态决定。 如果您更改单元格的状态,这样它可以不再从它的行和列的状态推断,该行不能被共享。例如,行不能共享在下列情形之一:?该行包含一个选定的 单元格是不是在选定的列。?该行包含一个与它的ToolTipText或ContextMenuStrip属性设置单元。?该行包含其项目 属性的DataGridViewComboBoxCell集。在绑定模式或虚拟模式,您可以通过处理CellToolTipTextNee ded提供CellContextMenuStripNeeded事件和个别细胞工具提示和快捷菜单。DataGridView控件将自动 尝试使用共享每当行添加到DataGridViewRowCollection行。使用下面的指引,以确保行共享:?避免调用Add(Ob ject[]的)的添加方法和插入(对象[])的插入的行的集合方法重载超载。这些重载自动创建非共享行。?确保在RowTemplat e属性指定的行可以在下列情况下,共享:当调用add()或Add方法添加或插入(智力,智力)的行的集合插入方法重载(智力)重载。当增 加RowCount属性的值。当设置DataSource属性。?确保该行的indexSource参数指定当呼叫可以共享的行集合Add Copy,AddCopies,InsertCopy和InsertCopies方法。?请确定指定的行或列时,可以共享调用Add(的D ataGridViewRow)Add方法的重载,AddRange方法,插入(Int32的,的DataGridViewRow)方法重 载的插入,和Rows集合InsertRange方法。要确定行是否是共享的,使用DataGridViewRowCollection. SharedRow(int)方法来检索行对象,然后检查对象的Index属性。共享行总是为-1Index属性值。?6.6防止行成为 非共享共享成为非共享行可以作为一个代码或用户操作的结果。为了避免影响性能,你应该避免造成行成为非共享。在应用开发,你可以处理Row Unshared事件来确定行成为非共享。这是非常有用的调试行共享问题。为了防止行成为非共享,请使用下列准则:?避免索引中的行集或通 过它迭代与foreach循环。你不会通常需要直接访问行。DataGridView的操作方法,对行,而不是采取行实例行索引参数。此 外,对于行相关的事件处理程序接收行属性,您可以用它来操作,而不会造成他们成为非共享行的事件参数对象。?如果您需要访问的行对象,请使 用DataGridViewRowCollection.SharedRow(int)方法并传入行的实际索引。请注意,但是,修改一个共 享行对象通过此方法检索将修改所有行共享此对象。在新记录行不共享,所以这是不会受到影响,当您修改任何其他行中的其他行。还要注意的是一 个共享行代表不同的行可能有不同的快捷菜单。以检索共享行实例的正确快捷菜单中,使用GetContextMenuStrip方法并传入行 的实际索引。如果您访问共享行的ContextMenuStrip属性,而是将使用-1共享行的索引,将不检索正确的快捷菜单。?避免索引 DataGridViewRow.Cells集合。访问一个细胞将直接导致其父行成为非共享,实例化一个新的DataGridViewRo w。为细胞相关的事件处理程序接收单元属性,你可以用它来操作不会导致行成为非共享细胞事件参数对象。您也可以使用CurrentCell Address属性来检索,而不用访问细胞直接当前单元格的行和列索引。?避免细胞为基础的选择模式。这些模式导致行成为非共享。相反,将 SelectionMode属性设置DataGridViewSelectionMode.FullRowSelect或DataGrid ViewSelectionMode.FullColumnSelect。?不处理DataGridViewRowCollection. CollectionChanged或RowStateChanged事件。这些事件会导致行成为非共享。另外,不要叫DataGridV iewRowCollection.OnCollectionChanged(CollectionChangeEventArgs)或O nRowStateChanged(智力,DataGridViewRowStateChangedEventArgs)方法,提高了这些 事件。?不访问SelectedCells集合时SelectionMode属性值是FullColumnSelect,ColumnHe aderSelect,FullRowSelect或RowHeaderSelect。这会导致所有行成为非共享选择。?不要调用AreA llCellsSelected(布尔)方法。这种方法可能会导致行成为非共享。?不要调用SelectAll方法当SelectionM ode属性值是CellSelect。这会导致所有行成为非共享。?不要设置只读或选定的一对假时,在其列对应的属性设置为true单元属 性。这会导致所有行成为非共享。?不访问DataGridViewRowCollection.List财产。这会导致所有行成为非共享。 ?不要调用Sort方法的Sort(IComparer接口)超载。一个自定义比较排序会导致所有行成为非共享。附录A–FAQ该附 录包含的代码示例和片段集中解答了前面散落的常见问题:1.如何使指定的单元格不可编辑?ReadOnly属性决定了单元格中的数据是否 可以编辑,可以设置单元格的ReadOnly属性,也可以设置DataGridViewRow.ReadOnly或DataGridV iewColumn.ReadOnly使得一行或一列所包含的单元格都是只读的。默认情况下,如果一行或一列是只读的,那么其包含的单元 格也会使只读的。不过你仍可以操作一个只读的单元格,比如选中它,将其设置为当前单元格,但用户不能修改单元格的内容。注意,即使单元格通 过ReadOnly属性设置为只读,仍然可以通过编程的方式修改它,另外ReadOnly也不会影响用户是否可以删除行。2.如何让一个 单元格不可用(disable)?单元格可以设置为只读而不可编辑,但DataGridView却没提供使单元格不可用的支持。一般意义上 ,不可用意味着用户不能进行操作,通常会带有外观的暗示,如灰色。没有一种简单的方法来创建那种不可操作的单元格,但提供一个暗示性的外观 告诉用户某单元格不可用还是可行的。内置的单元格类型没有进行不可用设置的属性,下面的例子扩展了DataGridViewButtonC ell,参照常见控件的Enabled属性,为其添加了Enabled属性,如果该属性设置为false,那么其外观状态将类似于普通按 钮的不可用状态。publicclassDataGridViewDisableButtonColumn:DataGridVi ewButtonColumn{publicDataGridViewDisableButtonColumn(){this.C ellTemplate=newDataGridViewDisableButtonCell();}}publicclass DataGridViewDisableButtonCell:DataGridViewButtonCell{private boolenabledValue;publicboolEnabled{get{returnenabledValu e;}set{enabledValue=value;}}//OverridetheClonemethod sothattheEnabledpropertyiscopied.publicoverrideobjectC lone(){DataGridViewDisableButtonCellcell=(DataGridViewDisableB uttonCell)base.Clone();cell.Enabled=this.Enabled;returncell; }//Bydefault,enablethebuttoncell.publicDataGridViewDisa bleButtonCell(){?this.enabledValue=true;}protectedoverride voidPaint(Graphicsgraphics,RectangleclipBounds,Rectanglecel lBounds,introwIndex,DataGridViewElementStateselementState,ob jectvalue,objectformattedValue,stringerrorText,DataGridView CellStylecellStyle,DataGridViewAdvancedBorderStyleadvancedBord erStyle,DataGridViewPaintPartspaintParts){//Thebuttoncell isdisabled,sopainttheborder,?//background,anddisabledbu ttonforthecell.if(!this.enabledValue){//Drawthecellbac kground,ifspecified.if((paintParts&DataGridViewPaintParts.B ackground)==DataGridViewPaintParts.Background){SolidBrushcell Background=newSolidBrush(cellStyle.BackColor);graphics.FillRe ctangle(cellBackground,cellBounds);cellBackground.Dispose();} //Drawthecellborders,ifspecified.if((paintParts&DataGri dViewPaintParts.Border)==DataGridViewPaintParts.Border){Paint Border(graphics,clipBounds,cellBounds,cellStyle,advancedBorde rStyle);}//Calculatetheareainwhichtodrawthebutton.Rec tanglebuttonArea=cellBounds;RectanglebuttonAdjustment=this .BorderWidths(advancedBorderStyle);buttonArea.X+=buttonAdjustm ent.X;buttonArea.Y+=buttonAdjustment.Y;buttonArea.Height-=b uttonAdjustment.Height;buttonArea.Width-=buttonAdjustment.Widt h;//Drawthedisabledbutton.ButtonRenderer.DrawButton(graphic s,buttonArea,PushButtonState.Disabled);//Drawthedisabledbu ttontext.if(this.FormattedValueisString){TextRenderer.Draw Text(graphics,(string)this.FormattedValue,this.DataGridView.Fon t,buttonArea,SystemColors.GrayText);}}else{//Thebuttonc ellisenabled,soletthebaseclass//handlethepainting.bas e.Paint(graphics,clipBounds,cellBounds,rowIndex,elementState, value,formattedValue,errorText,cellStyle,advancedBorderStyle ,paintParts);}}}3.如何避免用户将焦点设置到指定的单元格?默认情况下DataGridView的操作(nav igation)模型在限制用户将焦点置于指定的单元格方面没有提供任何支持。你可以实现自己的操作逻辑,这需要重写合适的键盘、导航、鼠 标方法,如DataGridView.OnKeyDown,DataGridView.ProcessDataGridViewKey, DataGridView.SetCurrentCellAddressCore,?DataGridView.SetSelected CellCore,DataGridView.OnMouseDown。4.如何使所有单元格总是显示控件(不论它是否处于编辑状态) ?DataGridView控件只支持在单元格处于编辑状态时显示真实的控件(如TextBox)。DataGridView没有被设 计为显示多控件或为每行重复显示控件。DataGridView在单元格不被编辑时为其绘制对应控件的外观,该外观可能是你想要的。例如 ,DataGridViewButtonCell类型的单元格,不管它是否处于编辑状态,总是表现为一个按钮。5.Whydoes thecelltextshowupwith“square”characterswheretheyshould benewlines(TODO,未能实现该效果)?Bydefault,textinaDataGridViewText BoxCelldoesnotwrap.ThiscanbecontrolledviatheWrapModepr opertyonthecellstyle(e.g.DataGridView.DefaultCellStyle.Wrap Mode).Becausetextdoesn’twrap,newlinecharactersinthetext donotapplyandsotheyaredisplayedasa“non-printable”char acter.ThisissimilartosettingaTextBox’sTextpropertytoth esametextwhentheTextBox’sMultiLinepropertyisfalse.6.如何在 单元格内同时显示图标和文本?DataGridView控件没有对在同一单元格内同时显示图标和文本提供支持。但通过实现自定义的绘制事件 ,如CellPaint事件,你可以轻松实现这个效果。下面这段代码扩展了DataGridViewTextBoxColumn和Da taGridViewTextBoxCell类,将一个图片显示在文本旁边。这个示例使用了DataGridViewCellStyle. Padding属性来调整文本的位置,重写了Paint方法来绘制图片。该示例可以得到简化,方法是处理CellPainting事 件,在这里实现类似的功能。publicclass?TextAndImageColumn:DataGridViewTextBox Column{private?Image?imageValue;private?Size?imageSize;public TextAndImageColumn(){this.CellTemplate=new?TextAndImageCell( );}publicoverrideobjectClone(){??TextAndImageColumn?c=bas e.Clone()as?TextAndImageColumn;c.imageValue=this.imageValue; c.imageSize=this.imageSize;returnc;}public?Image?Image{?ge t{returnthis.imageValue;}set{if(this.Image!=value){th is.imageValue=value;this.imageSize=value.Size;if(this.Inhe ritedStyle!=null){??Padding?inheritedPadding=this.InheritedS tyle.Padding;this.DefaultCellStyle.Padding=new?Padding(imageSi ze.Width,?inheritedPadding.Top,inheritedPadding.Right,??inherite dPadding.Bottom);?}}}}private?TextAndImageCell?TextAndImageCe llTemplate{get{returnthis.CellTemplateas?TextAndImageCell; }}internal?Size?ImageSize{?get{returnimageSize;}}}publi cclass?TextAndImageCell?:?DataGridViewTextBoxCell{private?Imag e?imageValue;private?Size?imageSize;?publicoverrideobjectClo ne(){??TextAndImageCell?c=base.Clone()as?TextAndImageCell;c. imageValue=this.imageValue;c.imageSize=this.imageSize;return c;}public?Image?Image{get{if(this.OwningColumn==null|| ?this.OwningTextAndImageColumn==null){returnimageValue;}e lseif(this.imageValue!=null){returnthis.imageValue;}else {?returnthis.OwningTextAndImageColumn.Image;}}set{if(this .imageValue!=value){this.imageValue=value;this.imageSize= value.Size;??Padding?inheritedPadding=this.InheritedStyle.Padd ing;this.Style.Padding=new?Padding(imageSize.Width,?inherited Padding.Top,inheritedPadding.Right,?inheritedPadding.Bottom);} ?}}protectedoverridevoidPaint(Graphics?graphics,?Rectangle?c lipBounds,??Rectangle?cellBounds,introwIndex,?DataGridViewEleme ntStates?cellState,objectvalue,objectformattedValue,stringe rrorText,???DataGridViewCellStyle?cellStyle,???DataGridViewAdvanc edBorderStyle?advancedBorderStyle,??DataGridViewPaintParts?paintP arts){//Paintthebasecontentbase.Paint(graphics,clipBounds ,cellBounds,rowIndex,cellState,?value,formattedValue,errorT ext,cellStyle,advancedBorderStyle,paintParts);if(this.Image !=null){//Drawtheimageclippedtothecell.System.Drawing. Drawing2D.GraphicsContainer?container=?graphics.BeginContainer( );?graphics.SetClip(cellBounds);graphics.DrawImageUnscaled(this .Image,cellBounds.Location);graphics.EndContainer(container);} }private?TextAndImageColumn?OwningTextAndImageColumn{get{re turnthis.OwningColumnas?TextAndImageColumn;}}}7.如何隐藏一列?有时希望 仅显示DataGridView的部分列,将其它列隐藏。比如DataGridView含有一列包含员工薪水信息,你可能希望仅将这些信息 显示给具有一定信用级别的人,其他人则隐藏。通过编程方式隐藏DataGridViewColumn类的Visible属性决定了是否显 示该列。?通过设计器隐藏1)右击DataGridView控件,选择EditColumns;2)在列列表中选择一列;3)在列属性网 格中,将Visible属性设置为false。8.如何避免用户对列排序?对于DataGridView控件,默认情况下,TextB ox类型的列会自动排序,而其它类型的列则不会自动排序。这种自动排序有时会把数据变得比较乱,这时你会想更改这些默认设置。DataGr idViewColumn的属性SortMode决定了列的排序方式,将其设置为DataGridViewColumnSortMode. NotSortable就可以避免默认的排序行为。9.如何针对多个列排序?默认情况下DataGridView不支持针对多列排序。下 面针对是否将数据绑定到DataGridView来分别演示如何为其添加多列排序功能。9.1?将数据绑定到DataGridView时D ataGridView进行数据绑定的时候,数据源(如DataView)可对多个列排序。DataGridView会保留这种排序,但只 有第一个排序列会显示排序符号(向上或向下的箭头),此外SortedColumn属性也只会返回第一个排序列。一些数据源内置了对多列排 序的支持。如果你的数据源实现了IBindingListView接口,提供了对Sort属性的支持,那么该数据源就支持多列排序。为了明 确指出DataGridView对多列排序,手动为已排序列设置正确的SortGlyphDirection属性,指示该列已经排序。下面 这个示例使用DataTable作为数据源,使用其DefaultView的Sort属性对第二列和第三列排序;该示例同时演示了如何 设置列的SortGlyphDirection属性。该示例假定在你的窗体上有一个DataGridView控件和一个BindingSo urce组件:?DataTable?dt=new?DataTable();dt.Columns.Add("C1",typeo f(int));dt.Columns.Add("C2",typeof(string));dt.Columns.Add("C3", typeof(string));dt.Rows.Add(1,"1","Test1");dt.Rows.Add(2,"2", "Test2");dt.Rows.Add(2,"2","Test1");dt.Rows.Add(3,"3","Test3 ");dt.Rows.Add(4,"4","Test4");dt.Rows.Add(4,"4","Test3");Data View?view=dt.DefaultView;view.Sort="C2ASC,C3ASC";bindingSo urce.DataSource=view;DataGridViewTextBoxColumn?col0=new?DataG ridViewTextBoxColumn();col0.DataPropertyName="C1";dataGridView1 .Columns.Add(col0);col0.SortMode=?DataGridViewColumnSortMode.Pro grammatic;col0.HeaderCell.SortGlyphDirection=?SortOrder.None;Dat aGridViewTextBoxColumn?col1=new?DataGridViewTextBoxColumn();col 1.DataPropertyName="C2";dataGridView1.Columns.Add(col1);col1.So rtMode=?DataGridViewColumnSortMode.Programmatic;col1.HeaderCell. SortGlyphDirection=?SortOrder.Ascending;DataGridViewTextBoxColum n?col2=new?DataGridViewTextBoxColumn();col2.DataPropertyName= "C3";dataGridView1.Columns.Add(col2);col2.SortMode=?DataGridView ColumnSortMode.Programmatic;col2.HeaderCell.SortGlyphDirection=? SortOrder.Ascending;9.2UnboundDataGridViewToprovidesupportfo rsortingonmultiplecolumnsyoucanhandletheSortCompareeven torcalltheSort(IComparer)overloadoftheSortmethodforgre atersortingflexibility.9.2.1CustomSortingUsingtheSortCompa reEventThefollowingcodeexampledemonstratescustomsortingus ingaSortCompareeventhandler.TheselectedDataGridViewColumn issortedand,ifthereareduplicatevaluesinthecolumn,theI Dcolumnisusedtodeterminethefinalorder.usingSystem;using System.Collections.Generic;usingSystem.ComponentModel;usingSyst em.Data;usingSystem.Drawing;usingSystem.Windows.Forms;classFor m1:Form{privateDataGridViewdataGridView1=newDataGridView( );//Establishthemainentrypointfortheapplication.[STAThr eadAttribute()]staticvoid?Main(){Application.EnableVisualStyl es();Application.Run(newForm1());}publicForm1(){//Initial izetheform.//Thiscodecanbereplacedwithdesignergenerate dcode.dataGridView1.AllowUserToAddRows=false;dataGridView1.D ock=DockStyle.Fill;dataGridView1.SortCompare+=newDataGridVi ewSortCompareEventHandler(this.dataGridView1_SortCompare);Contr ols.Add(this.dataGridView1);this.Text="DataGridView.SortCompar edemo";PopulateDataGridView();}//Replacethiswithyourown populationcode.publicvoidPopulateDataGridView(){//Addcolu mnstotheDataGridView.dataGridView1.ColumnCount=3;//Setth epropertiesoftheDataGridViewcolumns.dataGridView1.Columns[0 ].Name="ID";dataGridView1.Columns[1].Name="Name";dataGridVi ew1.Columns[2].Name="City";dataGridView1.Columns["ID"].HeaderT ext="ID";dataGridView1.Columns["Name"].HeaderText="Name";da taGridView1.Columns["City"].HeaderText="City";//Addrowsofd atatotheDataGridView.dataGridView1.Rows.Add(newstring[]{"1 ","Parker","Seattle"});dataGridView1.Rows.Add(newstring[]{ "2","Parker","NewYork"});dataGridView1.Rows.Add(newstring[] {"3","Watson","Seattle"});dataGridView1.Rows.Add(newstring []{"4","Jameson","NewJersey"});dataGridView1.Rows.Add(new string[]{"5","Brock","NewYork"});dataGridView1.Rows.Add(ne wstring[]{"6","Conner","Portland"});//Autosizethecolumn s.dataGridView1.AutoResizeColumns();}privatevoiddataGridView 1_SortCompare(objectsender,DataGridViewSortCompareEventArgse) {?//Trytosortbasedonthecellsinthecurrentcolumn.e.Sort Result=System.String.Compare(e.CellValue1.ToString(),e.CellVa lue2.ToString());//Ifthecellsareequal,sortbasedontheID column.if(e.SortResult==0&&e.Column.Name!="ID"){e.Sort Result=System.String.Compare(dataGridView1.Rows[e.RowIndex1].C ells["ID"].Value.ToString(),dataGridView1.Rows[e.RowIndex2].Cell s["ID"].Value.ToString());?}e.Handled=true;}}?9.2.2?CustomSo rtingUsingtheIComparerInterfaceThefollowingcodeexampledem onstratescustomsortingusingtheSort(IComparer)overloadofth eSortmethod,whichtakesanimplementationoftheIComparerint erfacetoperformamultiple-columnsort.usingSystem;usingSyste m.Drawing;usingSystem.Windows.Forms;classForm1:Form{private DataGridViewDataGridView1=newDataGridView();privateFlowLayo utPanelFlowLayoutPanel1=newFlowLayoutPanel();privateButton Button1=newButton();privateRadioButtonRadioButton1=newRa dioButton();privateRadioButtonRadioButton2=newRadioButton() ;//Establishthemainentrypointfortheapplication.[STAThre adAttribute()]publicstaticvoid?Main(){Application.Run(newFo rm1());}publicForm1(){//Initializetheform.//Thiscodec anbereplacedwithdesignergeneratedcode.AutoSize=true;Tex t="DataGridViewIComparersortdemo";FlowLayoutPanel1.FlowDire ction=FlowDirection.TopDown;FlowLayoutPanel1.Location=newSy stem.Drawing.Point(304,0);FlowLayoutPanel1.AutoSize=true;Flo wLayoutPanel1.Controls.Add(RadioButton1);FlowLayoutPanel1.Contro ls.Add(RadioButton2);FlowLayoutPanel1.Controls.Add(Button1);But ton1.Text="Sort";RadioButton1.Text="Ascending";RadioButton2 .Text="Descending";RadioButton1.Checked=true;Controls.Add(F lowLayoutPanel1);Controls.Add(DataGridView1);}protectedoverri devoidOnLoad(EventArgse){PopulateDataGridView();Button1.Cli ck+=newEventHandler(Button1_Click);base.OnLoad(e);}//Repla cethiswithyourowncodetopopulatetheDataGridView.private voidPopulateDataGridView(){DataGridView1.Size=newSize(300,3 00);//AddcolumnstotheDataGridView.DataGridView1.ColumnCoun t=2;//SetthepropertiesoftheDataGridViewcolumns.DataGri dView1.Columns[0].Name="First";DataGridView1.Columns[1].Name= "Last";DataGridView1.Columns["First"].HeaderText="FirstName" ;DataGridView1.Columns["Last"].HeaderText="LastName";DataGri dView1.Columns["First"].SortMode=DataGridViewColumnSortMode.Pro grammatic;DataGridView1.Columns["Last"].SortMode=DataGridViewC olumnSortMode.Programmatic;//AddrowsofdatatotheDataGridVi ew.DataGridView1.Rows.Add(newstring[]{"Peter","Parker"});D ataGridView1.Rows.Add(newstring[]{"James","Jameson"});DataG ridView1.Rows.Add(newstring[]{"May","Parker"});DataGridView 1.Rows.Add(newstring[]{"Mary","Watson"});DataGridView1.Rows .Add(newstring[]{"Eddie","Brock"});}privatevoidButton1_C lick(objectsender,EventArgse){if(RadioButton1.Checked==tr ue){DataGridView1.Sort(newRowComparer(SortOrder.Ascending));} elseif(RadioButton2.Checked==true){DataGridView1.Sort(new RowComparer(SortOrder.Descending));}}privateclassRowComparer :System.Collections.IComparer{privatestaticintsortOrderMod ifier=1;publicRowComparer(SortOrdersortOrder){if(sortOrde r==SortOrder.Descending){sortOrderModifier=-1;}elseif(s ortOrder==SortOrder.Ascending){sortOrderModifier=1;}}pub licintCompare(objectx,objecty){DataGridViewRowDataGridVie wRow1=(DataGridViewRow)x;DataGridViewRowDataGridViewRow2=(D ataGridViewRow)y;//TrytosortbasedontheLastNamecolumn.i ntCompareResult=System.String.Compare(DataGridViewRow1.Cells[ 1].Value.ToString(),DataGridViewRow2.Cells[1].Value.ToString()); //IftheLastNamesareequal,sortbasedontheFirstName.if (CompareResult==0){CompareResult=System.String.Compare(Dat aGridViewRow1.Cells[0].Value.ToString(),?DataGridViewRow2.Cells[0 ].Value.ToString());}returnCompareResultsortOrderModifier; }}}10.如何为编辑控件添加事件处理函数?有时候你需要处理单元格包含的编辑控件的特定事件。你需要处理DataGridView .EditingControlShowing事件,它的第二个参数的Control属性能让你访问该单元格包含的编辑控件。如果你要处 理的事件不属于它的基类Control,还需要将该控件转换为特定的控件(一般为ComboBox控件或TextBox控件)。?注意:如 果类型相同,DataGridView会重用该编辑控件,因此,你应该确保不会添加已存在的事件处理函数,否则会调用相同的函数多次(可以 在添加前先将其移除,请参考我的示例代码)。11.应在何时移除编辑控件的事件处理函数?如果你只是想临时为编辑控件添加事件处理函数( 可能是针对特定列的特定单元格),你可以在CellEndEdit事件中移除该处理函数。你也可以在添加之前移除任何已存在的事件处理函数 。12.如何处理ComboBox列中控件的SelectIndexChanged事件?有时知道用户何时选择了ComboBox编辑控 件的项(item)会比较有用。对于窗体上的ComboBox控件,你通常会处理它的SelectedIndexChanged事件,对 于DataGridViewComboBox,通过处理DataGridView.EditingControlShowing事件你可以 完成相同的事情。下面这段示例代码演示了这一点。注意:它同时也演示了如何避免添加多个相同的事件处理函数(即在添加前先移除已存在的事件 处理函数,可以参考问题11)。privatevoiddataGridView1_EditingControlShowing(o bjectsender,??DataGridViewEditingControlShowingEventArgs?e){??Co mboBox?cb=e.Controlas?ComboBox;if(cb!=null){//firstrem oveeventhandlertokeepfromattachingmultiple:cb.SelectedInd exChanged-=new??EventHandler(cb_SelectedIndexChanged);?//now attachtheeventhandlercb.SelectedIndexChanged+=new???EventHa ndler(cb_SelectedIndexChanged);}}?voidcb_SelectedIndexChanged(o bjectsender,?EventArgs?e){??MessageBox.Show("Selectedindexchan ged");}13.如何通过拖放调整行的顺序?通过拖放调整行的顺序不是DataGridView的内置功能,但使用标准的拖放处理代 码,你可以很容易的实现这个功能。下面这个代码片断演示了这个过程,假定你的窗体上有一个name为dataGridView1的Data GridView,它的AllowDrop属性为true,还要为它添加必要的事件处理方法。(我试运行了这段代码,如果通过数据绑定为D ataGridView添加数据,那么下面的代码将不会生效,因为它只能为非绑定方式添加的行排序,如果要以绑定方式添加数据,请参看我的 示例程序)?private?Rectangle?dragBoxFromMouseDown;privateintrowIndex FromMouseDown;privateintrowIndexOfItemUnderMouseToDrop;private voiddataGridView1_MouseMove(objectsender,?MouseEventArgs?e){if ((e.Button&?MouseButtons.Left)==?MouseButtons.Left){//Ifth emousemovesoutsidetherectangle,startthedrag.if(dragBoxF romMouseDown!=?Rectangle.Empty&&!dragBoxFromMouseDown.Contains (e.X,e.Y)){?//Proceedwiththedraganddrop,passinginthe listitem.??DragDropEffects?dropEffect=dataGridView1.DoDragDrop (dataGridView1.Rows[rowIndexFromMouseDown],??DragDropEffects.Mov e);}}}?privatevoiddataGridView1_MouseDown(objectsender,?Mous eEventArgs?e){//Gettheindexoftheitemthemouseisbelow.r owIndexFromMouseDown=dataGridView1.HitTest(e.X,e.Y).RowIndex;? if(rowIndexFromMouseDown!=-1){//Rememberthepointwheret hemousedownoccurred.??//TheDragSizeindicatesthesizethat themousecanmove??//beforeadrageventshouldbestarted.??Si ze?dragSize=?SystemInformation.DragSize;??//Createarectangle usingtheDragSize,withthemousepositionbeing//atthecente roftherectangle.dragBoxFromMouseDown=new?Rectangle(new?Poin t(e.X-(dragSize.Width/2),?e.Y-(dragSize.Height/2)),dragS ize);}else//Resettherectangleifthemouseisnotoverani temintheListBox.dragBoxFromMouseDown=?Rectangle.Empty;}?priv atevoiddataGridView1_DragOver(objectsender,?DragEventArgs?e){ e.Effect=?DragDropEffects.Move;}?privatevoiddataGridView1_Drag Drop(objectsender,?DragEventArgs?e){//Themouselocationsare relativetothescreen,sotheymustbe//convertedtoclientco ordinates.??Point?clientPoint=dataGridView1.PointToClient(new?P oint(e.X,e.Y));?//Gettherowindexoftheitemthemouseisb elow.rowIndexOfItemUnderMouseToDrop=dataGridView1.HitTest(clie ntPoint.X,clientPoint.Y).RowIndex;?//Ifthedragoperationwas amovethenremoveandinserttherow.if(e.Effect==?DragDropEf fects.Move){??DataGridViewRow?rowToMove=e.Data.GetData(typeof (DataGridViewRow))as?DataGridViewRow;dataGridView1.Rows.RemoveA t(rowIndexFromMouseDown);dataGridView1.Rows.Insert(rowIndexOfIte mUnderMouseToDrop,rowToMove);?}}14.如何调整最后一列的宽度使其占据网格的剩余客户区?以默认 方式填充DataGridView时,可能会发生因列的宽度不够,而暴露出控件的灰色背景的情况,很不美观。将最后一列的AutoSize Mode属性设置为Fill会使该列调整大小来填充网格的剩余客户区(clientarea)。作为一个可选的方式,你可以设置最后一列 MinimumWidth属性,以保持该列的宽度不至于太小。15.如何让TextBox类型的单元格支持换行?默认情况下,DataG ridViewTextBoxCell不支持换行,这个可以由DataGridViewCellStyle的WrapMode属性来控制。 (如DataGridView.DefaultCellStyle.WrapMode)。将WrapMode属性DataGridVi ewTriState枚举的三个取值之一。下面的代码示例使用DataGridView.DefaultCellStyle属性设置整个控 件所包含的单元格的WrapMode属性(即设置所有单元格的换行模式)。?this.dataGridView1.DefaultCel lStyle.WrapMode=?DataGridViewTriState.True;16.如何使Image列不显示任何图像( 字段值为null时)?默认情况下Image类型的列和单元格将null值转换为标准的“X”图像(),将Image列的NullVal ue属性设置为null可使该列不显示任何图像。下面这行代码演示了如何设置Image列的NullValue属性。this.dataG ridViewImageColumn1.DefaultCellStyle.NullValue=null;17.如何能够在Co mboBox类型的单元格中输入数据?默认情况下,DataGridViewComboBoxCell不接受用户的输入值。但有时确实有向 ComboxBox输入数据的需要。实现这个功能,你需要做两件事。一是将ComboBox编辑控件的DropDownStyle属性设置 为DropDown,使用户可以进行输入(否则只能进行选择);二是确保用户输入的值能够添加到ComboBox的Items集合。这是因 为ComboBoxCell的值必须在Items集合中,否则会触发DataError事件(参看3.5.1节),而适合添加新值到Ite ms集合的地方是CellValidating事件处理函数:privatevoiddataGridView1_CellValid ating(objectsender,?DataGridViewCellValidatingEventArgs?e){if( e.ColumnIndex==comboBoxColumn.DisplayIndex){if(!this.comboBo xColumn.Items.Contains(e.FormattedValue)){this.comboBoxColumn.I tems.Add(e.FormattedValue);}}}privatevoiddataGridView1_Editin gControlShowing(objectsender,??DataGridViewEditingControlShowing EventArgs?e){if(this.dataGridView1.CurrentCellAddress.X==comb oBoxColumn.DisplayIndex){??ComboBox?cb=e.Controlas?ComboBox; if(cb!=null){cb.DropDownStyle=?ComboBoxStyle.DropDown;}}} 18.HowdoIhaveacomboboxcolumndisplayasubsetofdataba seduponthevalueofadifferentcomboboxcolumn(TODO)?Sometime sdatathatyouwanttodisplayintheDataGridViewhasarelatio nshipbetweentwotablessuchasacategoryandsubcategory.You wanttolettheuserselectthecategoryandthenchoosebetween asubcategorybaseduponthecategory.Thisispossiblewiththe DataGridViewbyusingtwocomboboxcolumns.Toenablethis,two versionsofthefilteredlist(subcategory)needstobecreated. Onelisthasnofilterappliedwhiletheotheronewillbefilter edonlywhentheuseriseditingasubcategorycell.Twolistsar erequiredduetotherequirementdescribedin?http://www.cnblogs .cc2/3.5.1section?thatacomboboxcellsvaluemustbeintheit emscollectionorelseaDataErroreventisraised.Inthiscase, sinceallcomboboxcellsinthecolumnusethesamedatasource ifyoufilterthedatasourceforonerowthenacomboboxcellin anotherrowmightnothaveitsvaluevisibleinthedatasource, thuscausingaDataErrorevent.ThebelowexampleusestheNorthwi nddatabasetodisplayrelateddatafromtheTerritoryandRegion tables(aterritoryisinaspecificregion.)Usingthecategory andsubcategoryconcept,theRegionisthecategoryandtheTerr itoryisthesubcategory.privatevoidForm1_Load(objectsender,?E ventArgs?e){this.territoriesTableAdapter.Fill(this.northwindData Set.Territories);this.regionTableAdapter.Fill(this.northwindData Set.Region);//SetupBindingSourceforfilteredview.filteredTe rritoriesBS=new?BindingSource();??DataView?dv=new?DataView(no rthwindDataSet.Tables["Territories"]);filteredTerritoriesBS.Data Source=dv;}privatevoiddataGridView1_CellBeginEdit(objectsend er,?DataGridViewCellCancelEventArgs?e){if(e.ColumnIndex==terr itoryComboBoxColumn.Index){//Setthecomboboxcelldatasource tothefilteredBindingSource??DataGridViewComboBoxCell?dgcb=(D ataGridViewComboBoxCell)dataGridView1[e.ColumnIndex,e.RowIndex] ;dgcb.DataSource=filteredTerritoriesBS;//FiltertheBindingS ourcebasedupontheregionselectedthis.filteredTerritoriesBS.F ilter="RegionID="+this.dataGridView1[e.ColumnIndex-1,e.R owIndex].Value.ToString();}}privatevoiddataGridView1_CellEndEd it(objectsender,?DataGridViewCellEventArgs?e){if(e.ColumnIndex ==this.territoryComboBoxColumn.Index){//Resetcomboboxcell totheunfilteredBindingSource??DataGridViewComboBoxCell?dgcb= (DataGridViewComboBoxCell)dataGridView1[e.ColumnIndex,e.RowInde x];dgcb.DataSource=territoriesBindingSource;//unfilteredthis .filteredTerritoriesBS.RemoveFilter();}}19.如何在用户编辑控件的时候(而不是在验证时 )就显示错误图标?在使用错误文本和图标时,有时你希望为用户提供一个即时反馈,以提示当前的输入不正确。默认情况下,即使设置了Erro rText属性,如果单元格仍处于编辑模式下,那么错误图标也不会显示,比如TextBox和ComboBox。下面的示例演示了如何在C ellValidating事件中填充(padding)一个单元格为错误图标提供空间。因为默认情况下填充行为会影响错误图标的位置,该 示例(TODO)。Thebelowsampledemonstrateshowyoucansetacell’sp addingintheCellValidatingeventtoprovidespacingfortheerr oricon.Sincepaddingbydefaultaffectsthelocationoftheerr oriconthesampleusestheCellPaintingtomovethepositionoftheiconforpainting.Lastly,thesampleusesthetooltipcontroltodisplayacustomtooltipwhenthemouseisoverthecelltoindicatewhattheproblemis.ThissamplecouldalsobewrittenasacustomcellthatoverridesGetErrorIconBoundsmethodtoprovidealocationfortheerroriconthatwasindependentofthepadding.private?ToolTip?errorTooltip;private?Point?cellInError=new?Point(-2,-2);publicForm1(){InitializeComponent();dataGridView1.ColumnCount=3;dataGridView1.RowCount=10;}privatevoiddataGridView1_CellValidating(objectsender,?DataGridViewCellValidatingEventArgs?e){if(dataGridView1.IsCurrentCellDirty){if(e.FormattedValue.ToString()=="BAD"){??DataGridViewCell?cell=dataGridView1[e.ColumnIndex,e.RowIndex];cell.ErrorText="Invaliddataenteredincell";//increasepaddingforicon.Thismovestheeditingcontrolif(cell.Tag==null){cell.Tag=cell.Style.Padding;?cell.Style.Padding=new?Padding(0,0,18,0);cellInError=new?Point(e.ColumnIndex,e.RowIndex);}if(errorTooltip==null){errorTooltip=new?ToolTip();errorTooltip.InitialDelay=0;errorTooltip.ReshowDelay=0;errorTooltip.Active=false;}e.Cancel=true;}}}privatevoiddataGridView1_CellPainting(objectsender,?DataGridViewCellPaintingEventArgs?e){if(dataGridView1.IsCurrentCellDirty&&!String.IsNullOrEmpty(e.ErrorText)){//painteverythingexcepterroricone.Paint(e.ClipBounds,?DataGridViewPaintParts.All&?~(DataGridViewPaintParts.ErrorIcon));?//nowmoveerroriconovertofillinthepaddingspace??GraphicsContainer?container=e.Graphics.BeginContainer();e.Graphics.TranslateTransform(18,0);e.Paint(this.ClientRectangle,?DataGridViewPaintParts.ErrorIcon);e.Graphics.EndContainer(container);e.Handled=true;}}privatevoiddataGridView1_CellEndEdit(objectsender,?DataGridViewCellEventArgs?e){if(dataGridView1[e.ColumnIndex,e.RowIndex].ErrorText!=?String.Empty){??DataGridViewCell?cell=dataGridView1[e.ColumnIndex,e.RowIndex];cell.ErrorText=?String.Empty;cellInError=new?Point(-2,-2);//restorepaddingforcell.Thismovestheeditingcontrolcell.Style.Padding=(Padding)cell.Tag;?//hideanddisposetooltipif(errorTooltip!=null){errorTooltip.Hide(dataGridView1);errorTooltip.Dispose();errorTooltip=null;}}}//showandhidethetooltipforerrorprivatevoiddataGridView1_CellMouseMove(objectsender,???DataGridViewCellMouseEventArgs?e){if(cellInError.X==e.ColumnIndex&&cellInError.Y==e.RowIndex){DataGridViewCell?cell=dataGridView1[e.ColumnIndex,e.RowIndex];if(cell.ErrorText!=?String.Empty){if(!errorTooltip.Active){errorTooltip.Show(cell.ErrorText,dataGridView1,1000);}errorTooltip.Active=true;}}}privatevoiddataGridView1_CellMouseLeave(objectsender,?DataGridViewCellEventArgs?e){if(cellInError.X==e.ColumnIndex&&cellInError.Y==e.RowIndex){if(errorTooltip.Active){errorTooltip.Hide(dataGridView1);errorTooltip.Active=false;}}}20.如何同时显示绑定数据和非绑定数据?ThedatayoudisplayintheDataGridViewcontrolwillnormallycomefromadatasourceofsomekind,butyoumightwanttodisplayacolumnofdatathatdoesnotcomefromthedatasource.Thiskindofcolumniscalledanunboundcolumn.Unboundcolumnscantakemanyforms.???Asdiscussedinthedatasectionabove,youcanusevirtualmodetodisplayadditionaldataalongwithbounddata.Thefollowingcodeexampledemonstrateshowtocreateanunboundcolumnofcheckboxcellstoenabletheusertoselectdatabaserecordstoprocess.Thegridisputintovirtualmodeandrespondstothenecessaryevents.TheselectedrecordsarekeptbyIDinadictionarytoallowtheusertosortthecontentbutnotlosethecheckedrows.privateSystem.Collections.Generic.DictionarycheckState;privatevoidForm1_Load(objectsender,?EventArgs?e){dataGridView1.AutoGenerateColumns=false;dataGridView1.DataSource=customerOrdersBindingSource;//Thecheckboxcolumnwillbevirtual.dataGridView1.VirtualMode=true;dataGridView1.Columns.Insert(0,new?DataGridViewCheckBoxColumn());//Initializethedictionarythatcontainsthebooleancheckstate.checkState=new?Dictionary();}privatevoiddataGridView1_CellValueChanged(objectsender,?DataGridViewCellEventArgs?e){//Updatethestatusbarwhenthecellvaluechanges.if(e.ColumnIndex==0&&e.RowIndex!=-1){//GettheorderIDfromtheOrderIDcolumn.intorderID=(int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;checkState[orderID]=(bool)dataGridView1.Rows[e.RowIndex].Cells[0].Value;}privatevoiddataGridView1_CellValueNeeded(objectsender,?DataGridViewCellValueEventArgs?e){//Handlethenotificationthatthevalueforacellinthevirtualcolumn//isneeded.Getthevaluefromthedictionaryifthekeyexists.if(e.ColumnIndex==0){intorderID=(int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;if(checkState.ContainsKey(orderID)){e.Value=checkState[orderID];}elsee.Value=false;}}privatevoiddataGridView1_CellValuePushed(objectsender,?DataGridViewCellValueEventArgs?e){//Handlethenotificationthatthevalueforacellinthevirtualcolumn//needstobepushedbacktothedictionary.if(e.ColumnIndex==0){//GettheorderIDfromtheOrderIDcolumn.intorderID=(int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;//Addorupdatethecheckedvaluetothedictionarydependingonifthe//key(orderID)alreadyexists.if(!checkState.ContainsKey(orderID))?{checkState.Add(orderID,(bool)e.Value);}elsecheckState[orderID]=(bool)e.Value;}}21.HowdoIshowdatathatcomesfromtwotables(TODO)?TheDataGridViewdoesnotprovideanynewfeaturesapartfromvirtualmodetoenablethis.WhatyoucandoisusetheJoinViewclassdescribedinthefollowingarticle?http://support.microsoft.com/default.aspx?scid=kb;en-us;325682http://support.microsoft.com/default.aspx?scid=kb;en-us;325682.UsingthisclassyoucanjointwoormoreDataTablestogether.ThisJoinViewcanthenbedataboundtotheDataGridView.22.如何显示主从表?使用DataGridView时最常见的情况之一就是主从表单,这时要显示具有主从关系的两个数据表。在主表中选择一行记录,从表中也会随之变化,显示相应的记录。通过DataGridView控件和BindingSource组件的交互作用来实现主从表单是非常简单的。下面的示例演示的是SQLServer的范例数据库Northwind中的两个表:Customers和Orders。在主DataGridView中选择一个顾客,那么该顾客的所有订单会显示在从DataGridView中。usingSystem;usingSystem.Data;usingSystem.Data.SqlClient;usingSystem.Windows.Forms;publicclass?Form1?:System.Windows.Forms.Form{private?DataGridView?masterDataGridView=new?DataGridView();private?BindingSource?masterBindingSource=new?BindingSource();private?DataGridView?detailsDataGridView=new?DataGridView();private?BindingSource?detailsBindingSource=new?BindingSource();[STAThreadAttribute()]publicstaticvoid?Main(){??Application.Run(new?Form1());}//Initializestheform.publicForm1(){masterDataGridView.Dock=?DockStyle.Fill;detailsDataGridView.Dock=?DockStyle.Fill;??SplitContainer?splitContainer1=new?SplitContainer();splitContainer1.Dock=?DockStyle.Fill;splitContainer1.Orientation=?Orientation.Horizontal;splitContainer1.Panel1.Controls.Add(masterDataGridView);?splitContainer1.Panel2.Controls.Add(detailsDataGridView);this.Controls.Add(splitContainer1);this.Load+=newSystem.EventHandler(Form1_Load);this.Text="DataGridViewmaster/detaildemo";}privatevoidForm1_Load(objectsender,System.EventArgs?e){//BindtheDataGridViewcontrolstotheBindingSource//componentsandloadthedatafromthedatabase.masterDataGridView.DataSource=masterBindingSource;detailsDataGridView.DataSource=detailsBindingSource;GetData();//ResizethemasterDataGridViewcolumnstofitthenewlyloadeddata.masterDataGridView.AutoResizeColumns();//ConfigurethedetailsDataGridViewsothatitscolumnsautomatically//adjusttheirwidthswhenthedatachanges.detailsDataGridView.AutoSizeColumnsMode=??DataGridViewAutoSizeColumnsMode.AllCells;}privatevoidGetData(){try{//Specifyaconnectionstring.Replacethegivenvaluewitha//validconnectionstringforaNorthwindSQLServersample//databaseaccessibletoyoursystem.??String?connectionString="IntegratedSecurity=SSPI;PersistSecurityInfo=False;"+"InitialCatalog=Northwind;DataSource=localhost";??SqlConnection?connection=new?SqlConnection(connectionString);//CreateaDataSet.??DataSet?data=new?DataSet();data.Locale=System.Globalization.CultureInfo.InvariantCulture;//AdddatafromtheCustomerstabletotheDataSet.??SqlDataAdapter?masterDataAdapter=new??SqlDataAdapter("selectfromCustomers",connection);?masterDataAdapter.Fill(data,"Customers");//AdddatafromtheOrderstabletotheDataSet.??SqlDataAdapter?detailsDataAdapter=new??SqlDataAdapter("selectfromOrders",connection);detailsDataAdapter.Fill(data,"Orders");//Establisharelationshipbetweenthetwotables.??DataRelation?relation=new?DataRelation("CustomersOrders",data.Tables["Customers"].Columns["CustomerID"],data.Tables["Orders"].Columns["CustomerID"]);data.Relations.Add(relation);//BindthemasterdataconnectortotheCustomerstable.masterBindingSource.DataSource=data;masterBindingSource.DataMember="Customers";//Bindthedetailsdataconnectortothemasterdataconnector,//usingtheDataRelationnametofiltertheinformationinthe//detailstablebasedonthecurrentrowinthemastertable.detailsBindingSource.DataSource=masterBindingSource;detailsBindingSource.DataMember="CustomersOrders";}catch(SqlException){MessageBox.Show("Torunthisexample,replacethevalueofthe"+"connectionStringvariablewithaconnectionstringthatis"+"validforyoursystem.");}}}23.如何在同一DataGridView中显示主从表?DataGridView不支持在同一DataGridView中显示主从表。WindowsForms的先前版本中的DataGrid控件或许是你需要的一个解决方案。24.如何避免用户对列排序?对于DataGridView控件,默认情况下,TextBox类型的列会自动排序,而其它类型的列则不会自动排序。这种自动排序有时会把数据变得比较乱,这时你会想更改这些默认设置。DataGridViewColumn的属性SortMode决定了列的排序方式,将其设置为DataGridViewColumnSortMode.NotSortable就可以避免默认的排序行为。25.如何在点击工具栏按钮的时候将数据提交到数据库?默认情况下,操作工具栏或菜单不会导致对控件的验证。但对于绑定控件来说,提交数据前进行验证是必要的。而一旦窗体和其中的所有控件得到验证,当前编辑过的数据就需要提交。最后,数据适配器(如SqlDataAdapter)需要将数据的修改写入数据库。要达到这个效果,将下面三行代码加到相应的事件处理函数(指工具栏按钮或菜单项的事件)内:this.Validate();this.customersBindingSource.EndEdit();???????????this.customersTableAdapter.Update(this.northwindDataSet.Customers);26.如何在用户删除记录时显示确认对话框?当用户选择DataGridView的一行,按下Delete键时就会触发UserDeletingRow事件。你可以提示用户是否确定要删除该行记录,建议仅在用户要删除已存在的记录(而不是用户添加的新行)时才进行这种提示。将下面这些代码添加到UserDeletingRow事件的处理方法中就可以实现这种功能:if(!e.Row.IsNewRow){??DialogResult?response=?MessageBox.Show("Areyousure?","Deleterow?",?MessageBoxButtons.YesNo,??MessageBoxIcon.Question,??MessageBoxDefaultButton.Button2);if(response==?DialogResult.No)e.Cancel=true;} |
|