13.1 GridView控件
GridView控件是早期ASP.NET的版本中的DataGrid控件的后继控件,和DataGrid相比,GridView控件除了添加利用数据源控件功能的新功能外,还进行了一些改进,例如,增加了定义多个主键字段的功能,使用绑定字段和模板的改进用户界面自定义及用于处理或取消事件的新模型。
利用GridView控件,可以完成以下操作。
(1)通过数据源控件自动绑定和显示数据。
(2)通过数据源控件对数据进行选择、排序、分页、编辑和删除操作。
另外,还可以通过指定自定义列和样式自定义GridView件的外观和行为。
GridView控件提供了两个用于绑定到数据的选项。
(1)使用DataSourceID属性进行数据绑定,此选项能够将GridView控件绑定到数据源控件,它允许GridView控件利用数据源控件的功能并提供了内置的排序、分页和更新功能。
(2)使用DataSource属性进行数据绑定,能够绑定到ADO.NET数据集和数据读取器在内的各种对象,此时,需要为所有附加功能(比如排序、分页和更新等)编写代码。
另外,GridView控件数据绑定类型由DataControlField对象表示,GridView控件中的每一列由一个DataControlField对象表示。默认情况下,AutoGenerateColumns属性被设置为true,为数据源中的每一个字段创建一个AutoGeneratedField对象。然后,每一个字段按照在数据源中出现的顺序在GridView控件中呈现为一个列。
通过将AutoGenerateColumns属性设置为false,可以自定义列字段集合,也可以手动控制哪些列字段将显示在GridView控件中。不同的列字段类型决定控件中各列的行为,通过处理事件将自己的代码添加到GridView控件的功能中。
表13-1列出了GridView控件列字段类型。
表13-1 GridView控件列字段类型
13.1.1 使用GridView控件
GridView控件以表的形式显示数据,并可以对列进行排序、翻阅数据及编辑或删除单个记录。使用GridView控件无须编写任何代码即可在页面上显示数据,下面使用GridView控件显示在上一章使用LinqDataSource节中配置的数据源控件中的数据。
示例13-1:使用GridView控件
(1)打开12章的示例12-3,双击Default.aspx页面,在Web页面的“设计”视图中,双击工具箱中的“数据”组的“GridView”控件,在页面上添加GridView控件。
(2)在页面上插入GridView控件后,如图13-1所示。
图13-1 GridView任务
(3)在“选择数据源”下拉框中选择前面配置的数据源控件:LinqDataSource1,数据源设置完成后,控件显示出数据源包含的全部字段,如图13-2所示。
图13-2 选择数据源
(4)不用编写任何代码,即可使用GridView控件显示数据,测试一下页面,如图13-3所示。
图13-3 显示效果
(5)若要指定列的顺序,对显示的列表头自定义,需要重新设置GridView控件的属性,首先把AutoGenerateColumns属性设置为false,在“GridView任务”面板中单击“编辑列”选项,打开“字段”对话框,选中字段修改该列的属性,比如,字段的HeaderText属性,UserID的HeaderText修改为用户编号,UserName的HeaderText修改为用户姓名,UserPass的HeaderText修改为用户密码,UserEmail的HeaderText修改为用户邮箱,修改后如图13-4所示。
图13-4 修改字段属性
(6)单击“确定”按钮后,返回到页面上,GridView控件在页面显示的列字段已经全部为刚修改过的,如图13-5所示。
图13-5 修改后的页面
(7)在“GridView任务”面板中单击“自动套用格式”选项,打开“自动套用格式”对话框,这里可以为控件选择默认的外观界面,如图13-6所示。
图13-6 自动套用格式
(8)再一次运行该页面,GridView控件从LinqDataSource控件中获取其数据,如图13-7所示。
图13-7 使用GridViewListView的示例
13.1.2 GridView布局和样式
GridViewColumn的列单元格和列标题具有相同的宽度。默认情况下,每一列都根据其内容来调整宽度,并可以选择将列设置为固定宽度。
当定义要显示在GridViewColumn中的数据字段时,应使用DisplayMemberBinding、CellTemplate或CellTemplateSelector属性。DisplayMemberBinding属性优先于任何一个模板属性。
若要设置GridView的列中内容的对齐方式,必须定义CellTemplate。不要使用GridView,显示的ListView内容使用HorizontalContentAlignment和VerticalContent Alignment属性。
在多个相关类中找到定义内容、布局和GridView中的列标头样式属性,这些属性中的某些属性具有类似或相同的功能。
若要为列标题指定模板和样式属性,应使用GridView、GridViewColumn和GridViewColumnHeader类。
表13-2中的行显示执行相同功能的属性组,可以使用这些属性自定义GridView中的列标头。相关属性的优先级顺序从右向左,其中,最右边列中的属性具有最高优先级。例如,如果ContentTemplate设置在GridViewColumnHeader对象上,而HeaderTemplate Selector设置在相关GridViewColumn上,那么,ContentTemplate具有更高的优先级。此种情况下,设置了HeaderTemplateSelector属性无效。
表13-2 GridView中的列标头的相关属性
13.1.3 使用模板列
通常情况下,利用GridView控件可以自动从数据源提供的字段生成列,但有时可能会遇到需要自定义单个列显示方式的情况。这时,可以使用TemplateField对象指定自定义的列布局。
使用TemplateField对象可以指定包含标记和控件的模板,以便自定义GridView控件中列的布局和行为。使用ItemTemplate可以指定当GridView显示列中的数据时所使用的布局。若要在用户编辑列中的数据时指定自定义布局,可以创建一个EditItemTemplate。
在模板中,可以使用前面介绍的Eval和Bind方法将控件绑定到数据。当控件将仅仅显示某个值时,可以使用Eval方法。当需要在显示的同时还可以修改数据值时,也就是在数据更新方案中,可以使用Bind方法。可以在任何模板中使用Eval方法显示数据。如果模板包含值可能被用户更改的控件,如TextBox和CheckBox控件,或者模板允许删除记录,则可以使用Bind方法。
下面示例演示GridView控件的Columns集合,该集合中包含TemplateFiel对象,该对象中又包含ItemTemplate对象。若要显示邮箱,可在ItemTemplate中包括一个使用Eval方法的Label控件。若要编辑邮箱,可在其他模板中包括一个使用Bind方法的TextBox控件,代码如下所示。
13.1.4 GridView控件事件
使用GridView控件后,对GridView进行数据操作(如分页、更新)时,会引发许多事件。GridView控件事件分页事件和排序事件,此外,还有在创建当前行或将当前行绑定至数据时发生的数据绑定事件。具体主要事件如下。
PageIndexChanging:在单击页导航按钮时发生,但在GridView控件执行分页操作前,此事件通常用于取消分页操作。
PageIndexChanged:在单击页导航按钮时发生,但在GridView控件执行分页操作之后,此事件通常用于在用户定位到该控件中不同的页之后需要执行某项任务时。
SelectedIndexChanging:在单击GridView控件内某一行的Select按钮(其CommandName属性设置为“Select”的按钮)时发生,但在GridView控件执行选择。
RowCommand:在GridView控件中单击某个按钮时发生,此事件通常用于在该控件中单击某个按钮时执行某项任务。操作之前,此事件通常用于取消选择操作。
SelectedIndexChanged:在单击GridView控件内某一行的Select按钮时发生,但在GridView控件执行选择操作后,此事件用于在选择了该控件中的某行后执行某项任务。
Sorting:在单击某个用于对列进行排序的超链接时发生,但在GridView控件执行排序操作前,此事件通常用于取消排序操作或执行自定义的排序例程。
Sorted:在单击某个用于对列进行排序的超链接时发生,但在GridView控件执行排序操作后,此事件通常用于在用户单击对列进行排序的超链接后执行某项任务。
RowDataBound:在GridView控件中的某个行被绑定到一个数据记录时发生,此事件通常用于在某个行被绑定到数据时修改该行的内容。
RowCreated:在GridView控件中创建新行时发生,此事件通常用于在创建某个行时修改该行的布局或外观。
RowDeleting:在单击GridView控件内某一行的Delete按钮(其CommandName属性设置为“Delete”的按钮)时发生,但在GridView控件从数据源删除记录之前,此事件通常用于取消删除操作。
RowDeleted:在单击GridView控件内某一行的Delete按钮时发生,但在GridView控件从数据源删除记录后,此事件通常用于检查删除操作的结果。
RowEditing:在单击GridView控件内某一行的Edit按钮(其CommandName属性设置为“Edit”的按钮)时发生,但在GridView控件进入编辑模式之前,此事件通常用于取消编辑操作。
RowCancelingEdit:在单击GridView控件内某一行的Cancel按钮(其CommandName属性设置为“Cancel”的按钮)时发生,但在GridView控件退出编辑模式之前,此事件通常用于停止取消操作。
RowUpdating:在单击GridView控件内某一行的Update按钮(其CommandName属性设置为“Update”的按钮)时发生,但在GridView控件更新记录之前,此事件通常用于取消更新操作。
RowUpdated:在单击GridView控件内某一行的Update按钮时发生,但在GridView控件更新记录之后,此事件通常用来检查更新操作的结果。
DataBound:此事件继承自BaseDataBoundControl控件,在GridView控件完成到数据源的绑定后发生。
13.1.5 实现分页
当GridView中数据很多时,可以通过GridView的分页功能分页显示这些记录。GridView控件提供了简单的分页功能,通过使用GridView控件的PagerTemplate属性,可以自定义GridView控件的分页功能。要启用GridView控件的分页功能,只需将AllowPaging属性设置为true就可以启用分页。如果使用LinqDataSource控件访问数据库,在GridView控件的“GridView任务”面板中选中“启用分页”选项就可以启用GridView控件对数据的分页功能,如图13-8所示。
图13-8启用分页
注意
如果使用SqlDataSource控件,并将其DataSourceMode属性设置为DataReader,则GridView控件无法实现分页。
当GridView控件移动到新的数据页时,会引发两个事件:PageIndexChanging事件和PageIndexChanged事件,PageIndexChanging事件在GridView控件执行分页操作之前发生;PageIndexChanged事件在新的数据页返回到GridView控件之后发生。
根据需要,可以使用PageIndexChanging事件取消分页操作,或在GridView控件请求新的数据页之前执行某项任务。可以使用PageIndexChanged事件在用户移动到另一个数据页后执行某项任务。另外,还可以通过多种方式自定义GridView控件的分页用户界面,比如,使用PageSize属性来设置页的大小(即每次显示的项数),设置PageIndex属性来设置GridView控件的当前页。下列通过示例演示通过编程来设置GridView控件的分页。
示例13-2:通过代码来控制GridView分页
(1)新建网站,添加窗体:Default.aspx,在窗体上放置一个GridView控件。
(2)配置Web.config文件,设置数据连接信息。
(3)编写GridView的前台代码,代码如下。
(4)在后台编写如下分页处理代码。
(5)运行网站,显示效果如图13-9所示。
图13-9 分页效果
在本示例中,首先使用BindData方法为GridView控件绑定数据,设置GridView控件中的PagerSettings属性来定义分页的样式;接着分别对GridView的分页事件PageIndexChanged()和PageIndexChanging()进行处理;因为要添加分页码显示,即显示当前在第几页,示例中还添加了DataBound()事件,最终实现了分页效果。
13.1.6 实现排序效果
GridView控件可以在不需要编写任何代码的情况下,实现单个列的内容排序。可以通过处理排序事件、提供排序表达式或通过将CSS样式应用到要排序数据的列,自定义GridView控件的排序功能。使用SortedAscendingHeaderStyle、SortedDescendingCellStyle、SortedAscendingHeaderStyle和SortedDescendingHeaderStyle属性对排序的列应用CSS样式。
GridView控件本身并不执行列排序,而是依赖数据源控件来代表它执行排序,该控件提供用于排序的用户界面(UI),如显示在网格每一列最上方的LinkButton控件。
如果绑定的数据源控件支持数据排序,则选择数据后,GridView控件可以通过将SortExpression传递给数据源与该数据源控件进行交互并请求排序后的数据。但并不是所有的数据源控件都支持排序,例如,XmlDataSource控件就不支持排序,但如果数据源控件支持排序,GridView就可以利用它。利用GridVeiw控件进行排序,需要数据源控件作如下配置。
如果数据源控件是SqlDataSource和AccessDataSource控件,则将它们的DataSourceMode属性设置为DataSet,或SortParameterName属性设置为DataSet或DataReader,则这两个控件可以排序。
如果数据源控件是ObjectDataSource控件,则将ObjectDataSource控件的SortParameterName属性设置为基础对象所支持的值,则该控件可以排序。
通过将GridView控件的AllowSorting属性设置为true,即可启用该控件中的默认排序行为。将此属性设置为true会使GridView控件将LinkButton控件呈现在列标题中。此外,该控件还将每一列的SortExpression属性隐式设置为其所绑定到的数据字段的名称。
GridView在运行时,用户可以单击列标题中的LinkButton控件,使该列排序。单击该链接会使页面执行回发并引发GridView控件的Sorting事件。排序表达式(默认情况下是数据列的名称)作为事件参数的一部分传递。Sorting事件的默认行为是GridView控件将排序表达式传递给数据源控件。数据源控件执行其选择查询或方法,其中,包括由网格传递的排序参数。
使用LinqDataSource控件访问数据库时,只需在“GridView任务”面板中选中“启用排序”选项就可以启用GridView控件的排序功能,如图13-10所示。
图13-10 启用排序
GridView控件不检查数据源控件是否支持排序;在任何情况下它都会将排序表达式传递给数据源。如果数据源控件不支持排序并且由GridView控件执行排序操作,则GridView控件会引发NotSupportedException异常。
如果默认排序行为无法满足需要,可以自定义网格的排序行为。自定义排序的基本原理是处理Sorting事件,比如,下面的示例显示如何使用SortExpression属性确定正在对GridView控件中的哪一列进行排序。在上节显示数据的基础上作如下改进。
(1)打开示例Ch13-2中的页,在窗体上添加一个Label控件,用来显示排序信息。
(2)在GridView控件中,设置GridView控件的属性AllowSorting为True,如图13-11所示。
图13-11 设置排序事件
(3)设置作为排序关键字的列的SortExpression属性,因为GridView中可以包含按钮列,按钮列一般并不映射到某个数据字段,而排序必须以某个字段作为排序关键字才能完成。
在GridView控件的便捷任务面板中选择“编辑列”,选择可以作为排序关键字的列,设置其SortExpression属性为排序字段名,如图13-12所示。
图13-12 设置排序的字段
设置完成后,作为排序关键字的列的列名变为超链接样式,如图13-13所示。
图13-13 排序字段变为超链接样式
(4)为GridView控件设置排序事件处理方法,如图13-14所示。
图13-14 设置排序方法
(5)为事件编写以下处理代码。
(6)运行网站,当单击“用户编号”排序时,提示“这是按ID排序”,如图13-15所示。
图13-15 排序效果