1. GridView控件的属性
GridView支持大量属性,这些属性属于如下几大类:行为、可视化设置、样式、状态和模板。
行为属性 |
描述 |
AllowPaging |
指示该控件是否支持分页。 |
AllowSorting |
指示该控件是否支持排序。 |
AutoGenerateColumns |
指示是否自动地为数据源中的每个字段创建列。默认为true。 |
AutoGenerateDeleteButton |
指示该控件是否包含一个按钮列以允许用户删除映射到被单击行的记录。 |
AutoGenerateEditButton |
指示该控件是否包含一个按钮列以允许用户编辑映射到被单击行的记录。 |
AutoGenerateSelectButton |
指示该控件是否包含一个按钮列以允许用户选择映射到被单击行的记录。 |
DataMember |
指示一个多成员数据源中的特定表绑定到该网格。该属性与DataSource结合使用。如果DataSource是有一个DataSet对象,则该属性包含要绑定的特定表的名称。 |
DataSource |
获得或设置包含用来填充该控件的值的数据源对象。 |
DataSourceID |
指示所绑定的数据源控件。 |
EnableSortingAndPagingCallbacks |
指示是否使用脚本回调函数完成排序和分页。默认情况下禁用。 |
RowHeaderColumn |
用作列标题的列名。该属性旨在改善可访问性。 |
SortDirection |
获得列的当前排序方向。 |
SortExpression |
获得当前排序表达式。 |
UseAccessibleHeader |
规定是否为列标题生成<th>标签(而不是<td>标签)。 |
SortDirection和SortExpression属性规定当前决定行的排列顺序的列上的排序方向和排序表达式。这两个属性都是在用户单击列的标题时由该控件的内置排序机制设置的。整个排序引擎通过AllowSorting属性启用和禁用。EnableSortingAndPagingCallbacks属性打开和关闭该控件的使用脚本回调进行分页和排序,而不用往返于服务器并改变整个页面的功能。
GridView控件内显示的每一行对应于一种特殊的网格项。预定义的项目类型几乎等于DataGrid的项目类型,包括标题、行和交替行、页脚和分页器等项目。这些项目是静态的,因为它们在控件的生命期内在应用程序中保持不变。其他类型的项目在短暂的时间(即,完成某种操作所需的时间)内是活动的。动态项目是编辑行、所选的行和EmptyData项。当网格绑定到一个空的数据源时,EmptyData标识该网格的主体。
样式属性 |
描述 |
|
AlternatingRowStyle |
定义表中每隔一行的样式属性。 |
|
EditRowStyle |
定义正在编辑的行的样式属性。 |
|
FooterStyle |
定义网格的页脚的样式属性。 |
|
HeaderStyle |
定义网格的标题的样式属性。 |
|
EmptyDataRowStyle |
定义空行的样式属性,这是在GridView绑定到空数据源时生成。 |
|
PagerStyle |
定义网格的分页器的样式属性。 |
|
RowStyle |
定义表中的行的样式属性。 |
|
SelectedRowStyle |
定义当前所选行的样式属性。 |
|
外观属性 |
描述 |
|
BackImageUrl |
指示要在控件背景中显示的图像的URL。 |
|
Caption |
在该控件的标题中显示的文本。 |
|
CaptionAlign |
标题文本的对齐方式。 |
|
CellPadding |
指示一个单元的内容与边界之间的间隔(以像素为单位)。 |
|
CellSpacing |
指示单元之间的间隔(以像素为单位)。 |
|
GridLines |
指示该控件的网格线样式。 |
|
HorizontalAlign |
指示该页面上的控件水平对齐。 |
|
EmptyDataText |
指示当该控件绑定到一个空的数据源时生成的文本。 |
|
PagerSettings |
引用一个允许我们设置分页器按钮的属性的对象。 |
|
ShowFooter |
指示是否显示页脚行。 |
|
ShowHeader |
指示是否显示标题行。 |
PagerSettings对象把所有可以对分页器设置的可视化属性组织在一起。其中有很多属性在DataGrid程序员看来应该是熟悉的。PagerSettings类还添加了一些新属性以满足新的预定义的按钮(第1页和最后一页),并在链接中使用图像代替文本。
模板属性 |
描述 |
|
EmptyDataTemplate |
指示该控件绑定到一个空的数据源时要生成的模板内容。如果该属性和EmptyDataText属性都设置了,则该属性优先采用。如果两个属性都没有设置,则把该网格控件绑定到一个空的数据源时不生成该网格。 |
|
PagerTemplate |
指示要为分页器生成的模板内容。该属性覆盖我们可能通过PagerSettings属性作出的任何设置。 |
|
状态属性 |
描述 |
|
BottomPagerRow |
返回表格该网格控件的底部分页器的GridViewRow对象。 |
|
Columns |
获得一个表示该网格中的列的对象的集合。如果这些列是自动生成的,则该集合总是空的。 |
|
DataKeyNames |
获得一个包含当前显示项的主键字段的名称的数组。 |
|
DataKeys |
获得一个表示在DataKeyNames中为当前显示的记录设置的主键字段的值。 |
|
EditIndex |
获得和设置基于0的索引,标识当前以编辑模式生成的行。 |
|
FooterRow |
返回一个表示页脚的GridViewRow对象。 |
|
HeaderRow |
返回一个表示标题的GridViewRow对象。 |
|
PageCount |
获得显示数据源的记录所需的页面数。 |
|
PageIndex |
获得或设置基于0的索引,标识当前显示的数据页。 |
|
PageSize |
指示在一个页面上要显示的记录数。 |
|
Rows |
获得一个表示该控件中当前显示的数据行的GridViewRow对象集合。 |
|
SelectedDataKey |
返回当前选中的记录的DataKey对象。 |
|
SelectedIndex |
获得和设置标识当前选中行的基于0的索引。 |
|
SelectedRow |
返回一个表示当前选中行的GridViewRow对象。 |
|
SelectedValue |
返回DataKey对象中存储的键的显式值。类似于SelectedDataKey。 |
|
TopPagerRow |
返回一个表示网格的顶部分页器的GridViewRow对象。 |
GridView旨在利用新的数据源对象模型,并在通过DataSourceID属性绑定到一个数据源控件时效果最佳。GridView还支持经典的DataSource属性,但是如果那样绑定数据,则其中一些特征(诸如内置的更新或分页)变得不可用。
2. GridView控件的事件
GridView控件没有不同于DataBind的方法。然而,如前所述,在很多情况下我们不需要调用GridView控件上的方法。当我们把GridView绑定到一个数据源控件时,数据绑定过程隐式地启动。
在ASP.NET 2.0中,很多控件,以及Page类本身,有很多对doing/done类型的事件。控件生命期内的关键操作通过一对事件进行封装:一个事件在该操作发生之前激发,一个事件在该操作完成后立即激发。GridView类也不例外。表10.11列出了GridView控件激发的事件。
事件 |
描述 |
PageIndexChanging, PageIndexChanged |
这两个事件都是在其中一个分页器按钮被单击时发生。它们分别在网格控件处理分页操作之前和之后激发。 |
RowCancelingEdit |
在一个处于编辑模式的行的Cancel按钮被单击,但是在该行退出编辑模式之前发生。 |
RowCommand |
单击一个按钮时发生。 |
RowCreated |
创建一行时发生。 |
RowDataBound |
一个数据行绑定到数据时发生。 |
RowDeleting, RowDeleted |
这两个事件都是在一行的Delete按钮被单击时发生。它们分别在该网格控件删除该行之前和之后激发。 |
RowEditing |
当一行的Edit按钮被单击时,但是在该控件进入编辑模式之前发生。 |
RowUpdating, RowUpdated |
这两个事件都是在一行的Update按钮被单击时发生。它们分别在该网格控件更新该行之前和之后激发。 |
SelectedIndexChanging, SelectedIndexChanged |
这两个事件都是在一行的Select按钮被单击时发生。它们分别在该网格控件处理选择操作之前和之后激发。 |
Sorting, Sorted |
这两个事件都是在对一个列进行排序的超链接被单击时发生。它们分别在网格控件处理排序操作之前和之后激发。 |
RowCreated和RowDataBound事件与DataGrid的ItemCreated和ItemDataBound事件相同,只是换了个新名称。它们的行为完全与它们在ASP.NET 1.x中的一样。对于RowCommand事件也一样,它与DataGrid的ItemCommand事件一样。
可以使用宣布某种操作的事件,极大地增强了我们的编程能力。通过连接RowUpdating事件,可以交叉检查正在更新什么并对新值进行验证。同样,我们可能需要处理RowUpdating事件,用HTML对客户端提供的值进行编码,然后把它们持久地保存在底层数据存储中。这一简单技巧有助于防御脚本侵入。
3.GridView控件支持的列类型
类型 |
描述 |
BoundField |
默认的列类型。作为纯文本显示一个字段的值。 |
ButtonField |
作为命令按钮显示一个字段的值。我们可以选择链接按钮或按钮开关样式。 |
CheckBoxField |
作为一个复选框显示一个字段的值。它通常用来生成布尔值。 |
CommandField |
ButtonField的增强版本,表示一个特殊的命令,诸如Select、Delete、Insert或Update。该属性对GridView控件几乎每什么用;该字段是为DetailsView控件定制的。(GridView和DetailsView共享从DataControlField派生的类集。) |
HyperLinkField |
作为超链接显示一个字段的值。单击该超链接时,浏览器到航道指定的URL。 |
ImageField |
作为一个<img> HTML标签的Src属性显示一个字段的值。绑定字段的内容应该是物理图象的URL。 |
TemplateField |
为列中的每一项显示用户定义的内容。当我们需要创建一个定制的列字段时,则使用该列类型。模板可以包含任意多个数据字段,还可以结合文字、图像和其他控件。 |
表10.13列出了所有的列类型共享的主要属性。
4.GridView列的公共属性
属性 |
描述 |
AccessibleHeaderText |
表示Assistive Technology设备的屏幕阅读器读取的缩写文本的文本。 |
FooterStyle |
获得该列的页脚的样式对象。 |
FooterText |
获得和设置该列的页脚的文本。 |
HeaderImageUrl |
获得和设置放在该列的标题中的图像的URL。 |
HeaderStyle |
获得该列的标题的样式对象。 |
HeaderText |
获得和设置该列的标题的文本。 |
InsertVisible |
指示当它的父数据绑定控件处于插入模式时,该字段是否可见。该属性不适用于GridView控件。 |
ItemStyle |
获得各列的单元的样式对象。 |
ShowHeader |
指示是否生成该列的标题。 |
SortExpression |
获得和设置该列的标题被单击时用来排序网格内容的表达式。通常,该字符串属性被设置为所绑定的数据字段的名称。 |
2. 绑定字段
BoundField类表示在一个数据绑定控件(诸如GridView或DetailsView)中作为纯文本显示的一个字段。为了规定要显示的字段,把DataField属性设置为该字段的名称。通过设置DataFormatString属性,可以应用一个定制的格式化字符串于所显示的值。如果NullDisplayText属性的值为null,则允许我们规定要显示的交替文本。最后,通过把ConvertEmptyStringToNull属性设置为true,强制该类把空字符串看作null值。
BoundField可以通过Visible属性以编程的方式隐藏起来,而ReadOnly属性防止所显示的值在编辑模式被修改。要在头部或页脚部分显示一个标题,请分别设置HeaderText和FooterText属性。我们还可以选择在头部显示一个图像,而不是文本,这时要设置HeaderImageUrl属性。
3. 按钮字段
按钮字段适合于把一个可单击的元素放入一个网格的列中。通常使用一个按钮字段触发针对当前行的一个操作。按钮字段表示我们希望通过一个服务器端事件处理的任何操作。当该按钮被单击时,页面回发并激发一个RowCommand事件。图10.3展示了一个示例。
4. 超链接字段
超链接列把用户指向一个不同的URL,该URL可以有选择地在一个内部框架中显示出来。该链接的文本和URL可以从所绑定的数据源中获得。特别是,URL可以按以下两种方法之一进行设置:通过直接绑定到一个数据源字段,或通过使用一个硬编码的带有定制查询字符串的URL。如果URL存储在数据源的一个字段字段中,则选择直接绑定。在这种情况下,把DataNavigateUrlFields属性设置为该列的名称。然而,在某些情况下,要访问的URL与特定的应用程序有关,并不是存储在数据源中。在这种情况下,可以用一个硬编码的URL和查询字符串中的一个参数数组设置DataNavigateUrlFormatString属性:
<asp:HyperLinkField DataTextField="productname"
HeaderText="Product"
DataNavigateUrlFields="productid"
DataNavigateUrlFormatString="productinfo.aspx?id={0}"
Target="ProductView" />
当用户单击该按钮时,浏览器用productinfo.aspx?id=xxx URL的内容填充规定的框架窗口,其中xxx取自productid字段。该URL可以包含多个参数。要包含多个数据绑定值,只要把DataNavigateUrlFields属性设置为一个逗号隔开的字段名列表。该行为扩展了DataGrid的超链接列的行为,因为它支持多个参数。
超链接的文本也可以进行格式化。DataTextFormatString属性可以包含任何有效的标记,并使用{0}占位符保留数据绑定值的位置。
5. CheckBox字段
我们迄今所考虑的列类型对于经验丰富的ASP.NET 1.x开发人员来讲并不觉得新奇。虽然被重命名了,但是它们的总体行为仍然非常类似于DataGrids的类似列类型的行为。另一方面,CheckBoxField类型是在ASP.NET 2.0中是一个新类型,并且只适用于GridView和其他视图控件。在ASP.NET 1.x中获得一个复选框的最简单的方法是通过模板(一般是针对DataGrids)。
CheckBoxField列是显示一个复选框的一个较简单的绑定列。我们可以只把它绑定到一个包含布尔值的数据字段。有效的布尔值取自一个SQL Server表中的一个Bit类型(和其他数据库中的类似类型)的列,如果该控件绑定到一个定制集合,则取自一个bool类型的属性。特别是,如果把一个CheckBoxField列绑定到一个整数属性,则会得到一个异常,从而隐式地假设0为false,非0为true。
6. 图像字段
ImageField列类型表示一个在数据绑定控件中作为图像显示的字段。该单元包含一个<img>元素,因此底层的字段必须引用一个有效的URL。然而,我们可以任意组合URL。例如,我们可以使用DataImageUrlField执行直接绑定,其中该字段的内容填充<img>标签的Src属性。另外,我们可以使该列的单元指向一个外部页面(或者HTTP处理程序),从任何来源获取该图像的字节,并把它们下传给浏览器。
7. 模板字段
TemplateField列为该网格中的每一行提供一个个性化用户界面,这完全是由页面开发人员定义的。我们可以为各生成阶段定义模板,包括默认视图、原地编辑、标题和页脚。
模板 |
描述 |
AlternatingItemTemplate |
定义交替行的内容和外观。如果没有规定该模板,则使用ItemTemplate。 |
EditItemTemplate |
定义当前正在编辑的行的内容和外观。该模板应当包含输入字段,而且还可能包含验证程序。 |
FooterTemplate |
定义该行的页脚的内容和外观。 |
HeaderTemplate |
定义该行的标题的内容和外观。 |
ItemTemplate |
定义该行的默认内容和外观。 |
一个模板化视图可以包含对我们正在创建的应用程序有意义的东西:服务器控件、文字和数据绑定表达式。数据绑定表达式允许我们插入当前数据行中包含的值。我们可以使用一个模板中所需的尽可能多的字段。然而请注意,并非所有的模板都支持数据绑定表达式。标题和页脚模板不是数据绑定的,并且对它使用表达式的任何企图都将导致一个异常。
GridView旨在利用底层数据源控件的具体功能。这样网格控件就能够应对诸如排序、分页、更新和删除等数据操作。一般而言,并非所有的数据源组件都支持所有可能的和可行的数据操作。数据源组件提供布尔属性(诸如CanSort属性),以表明它们是否能够执行一个给定的操作。
重要提示: 如果GridView控件通过DataSource属性绑定到数据源——即,不利用数据源控件——则就分页和其他操作(例如,排序和编辑)而言,它的总体行为几乎与DataGrid控件的行为一样。在这种情况下,GridView激发事件,并期望页面中的绑定代码提供指令和新数据。在本章的其余部分,除了明确说明外,我们指的是一个绑定到数据源控件的GridView。
GridView多少使页面开发人员透明地实现通常所需的特征,诸如排序和分页等。在大多数情况下,我们只需要DataGrid所需代码的一部分;在某些情况下,根本不需要代码。这就是说,不要忘了一个古老而智慧的谚语所说的,“发亮的并不一定全是金子”。换句话说,自己编写的代码越少,就越要依赖于现有基础结构来完成事情。这么做是让系统代替我们做出重大的决策。分页和排序是Web应用程序中的关键操作。我们仍然可以接受GridView默认完成的工作,但是如果确切地知道究竟发生了什么,就能更好地及时诊断和修复在应用程序的生命期内出现的任何性能问题。
8.无代码数据分页
能够滚动一个潜在的大型数据集,对于现代分布式应用来说是一个重要而具挑战性的特征。一种有效的数据分页机制允许顾客与一个数据库进行交互,而不用占据资源。要启用一个GridView控件上的数据分页功能,只需把AllowPaging属性设置为true。当AllowPaging设为true时,该网格显示一个分页器条,并准备检测用户对分页器按钮的单击。
当用户单击分页器按钮以查看一个新的页面时,该页面回发,但是GridView捕获该事件,并在内部处理它。这就标志着GridView和DataGrid与我们从ASP.NET 1.x获悉的编程模型之间的一个重大区别。对于GridView,不需要为PageIndexChanged事件编写处理程序。它仍然提供该事件(并且与PageIndexChanging配合),但是我们只有在执行额外的操作时才要处理该事件。GridView知道如何检索和显示请求的新页面。让我们分析一下如下控件声明:
<asp:GridView ID="GridView1" runat="server"
DataSourceID="SqlDataSource1" AllowPaging="true" />
SqlDataSource1绑定到该网格的任何数据立即可分页。该控件显示一个具有几个预定义链接(第一个、前一个、下一个和最后一个)的分页器,并且自动选择适合所选页面的行的正确子集。
遍历GridView控件中的页面
我们与GridView交互的默认用户界面包括页号。添加一个页号标签犹如编写一个PageIndexChanged事件的处理程序那么简单:
protected void GridView1_PageIndexChanged(object sender, EventArgs e)
{
ShowPageIndex();
}
private void ShowPageIndex()
{
CurrentPage.Text = (GridView1.PageIndex + 1).ToString();
}
再次强调,注意PageIndexChanged事件处理程序并不涉及数据绑定或页面选择,而DataGrids的对应事件处理程序则要涉及。如果不需要任何分页后的操作,就可以充满喜悦地全部删除它。
GridView控件并非真正知道如何获得一个新页面。它只是请求绑定的数据源控件返回i适合规定页面的行。分页最终由数据源控件完成。当一个网格被绑定到一个SqlDataSource控件时,则分页机制要求整个数据源绑定到该控件。当一个网格绑定到一个ObjectDataSource控件时,分页机制取决于我们连接的业务对象的能力。
让我们首先介绍SqlDataSource。我们必须把DataSourceMode设置为DataSet(默认设置)。这就意味着检索整个数据集,并且只显示适合当前页面大小的记录数。在一种极端情况下,最终可能下载1 000条记录,而每次回发只显示10条记录。如果通过把EnableCaching设置为true,启用SqlDataSource上的缓存,则情况会更好一些。在这种情况下,整个数据集只下载一次,并在指定的期限内存储在ASP.NET缓存中。只要数据保持缓存状态,显示任何页面几乎都是免费的。然而,可能有大量数据存储在内存中。因此,只推荐对所有用户共享的较小数据集采用这种方案。
9.分页器配置
当AllowPaging属性设置为true时,网格显示一个分页器条。通过<PagerSettings>和<PagerStyle>标签或者它们的相当属性,可以在很大程度上控制分页器的特征。GridView控件的分页器还支持第一页和最后一页按钮,并允许我们把一个图像赋给每个按钮。(这对于DataGrids也是可能的,但是它需要大量代码。)分页器能够以如下两种模式进行工作:显示显式的页面编号,或者提供一个相对的导航系统。在前一种情况下,分页器包含数字连接,表示一个页面索引。在后一种情况下,按钮的存在是为了导航到下一页或前一页,甚至导航到第一页或最后一页。Mode属性规定分页器的用户界面。表10.15列出了可用的模式。
模式 |
描述 |
NextPrevious |
显示下一页和前一页按钮,用于防问网格中的下一页和前一页。 |
NextPreviousFirstLast |
显示下一页和前一页按钮,以及第一页和最后一页按钮,用于直接访问网格的第一页和最后一页。 |
Numeric |
显示与网格的页面对应的数字链接按钮。 |
NumericFirstLast |
显示与网格的各页以及与直接访问网格的第一页和最后一页的第一页和最后一页按钮对应的数字链接按钮。 |
特别的属性对,xxxPageText和xxxPageImageUrl,允许我们任意设置这些按钮的标签。xxx代表如下含义:First(第一页)、Last(最后一页)、Next(下一页)或Previous(前一页)。
非常类似于DataGrid,GridView可以为网格中的每一行生成一个命令按钮列。这些特殊的命令列包含编辑或删除当前记录的按钮。如果使用DataGrid控件,则必须使用一个专门的列类型(EditCommandColumn类)显式地创建一个编辑命令列。GridView大大地简化了更新和删除操作。
10.编辑表格
1. 原地编辑和更新
原地编辑指网格能够支持对当前显示记录的变更的能力。通过打开AutoGenerateEditButton布尔属性,启用一个网格视图上的原地编辑功能:
<asp:gridview runat="server" id="GridView1" datasourceid="MySource"
autogeneratecolumns="false" autogenerateeditbutton="true">
...
</asp:gridview>
当AutoGenerateEditButton属性设置为true时,GridView显示一个附加列,就像图10.13所示的那样。通过单击Edit按钮,使所选行进入编辑模式,并且可以任意输入新数据。
2. 删除显示的记录
从GridView的角度看,删除记录与更新记录差不多。在这两种情况下,GridView利用数据源的执行数据操作的能力。通过将AutoGenerateDeleteButton属性的值设置为true,启用记录删除功能。GridView生成一个按钮列,如果单击这些按钮,则针对所绑定的数据源控件上的对应行调用删除命令;并向该数据源方法传递一个由名称/值组成的键字段对字典,用来惟一地标识要删除的行:
<asp:sqldatasource runat="server" ID="EmployeesSource"
ConnectionString="<%$ ConnectionStrings:LocalNWind %>"
SelectCommand="SELECT employeeid, firstname, lastname FROM employees"
UpdateCommand="UPDATE employees SET
firstname=@firstname, lastname=@lastname
WHERE employeeid=@original_employeeid"
DeleteCommand="DELETE employees WHERE
employeeid=@original_employeeid" />
GridView不会提供有关将要发生的操作的任何反馈信息。它在执行删除之前调用Page.IsValid,如果有一个带验证器的定制模板,这么做是有用的。此外,RowDeleting事件为我们提供了另一个以编程方式控制该操作的合法性的机会。
如果由于数据库特定的限制没有删除该记录,则删除操作失败。例如,如果子记录通过某个关系引用一个记录,则不能删除该纪录。这时会抛出一个异常。
要通过ObjectDataSource控件删除一个记录,则为业务对象提供一对方法,如下所示:
public static void Delete(Customer cust)
{
Delete(cust.ID);
}
public static void Delete(string id)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
SqlCommand cmd = new SqlCommand(cmdDelete, conn);
cmd.Parameters.AddWithValue("@id", id);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
return;
}
}
重载删除方法并非是必要条件,但这么做是有用的,这无疑会使我们的DAL更灵活、更易于使用。
3. 插入新记录
目前,GridView控件并不支持向数据源对象插入数据。缺少这个功能是由于GridView实现的结果,而不是由于底层数据源的功能和特征。实际上,所有的数据源控件都支持一个插入命令属性。正如我们在下一章将会看到的,DetailsView和FormView控件完全支持新记录的插入。
在ASP.NET 1.x中,使DataGrid控件支持记录插入的常见做法要求我们修改页脚或分页器,为空的文本框和按钮腾出空间。GridView支持相同的模型,并通过PagerTemplate属性使涉及分页器的情况更简单。通过RowCreated事件修改页脚的内容是可能的(稍后再作详细介绍)。然而请注意,如果网格绑定到一个空的数据,则页脚条被隐藏。如果希望用户能够把一个新记录添加到一个空的网格中该怎么办呢?利用EmptyDataTemplate,具体如下所示:
<emptydatatemplate>
<asp:label ID="Label1" runat="server">
There's no data to show in this view.
<asp:Button runat="server" ID="btnAddNew" CommandName="AddNew"
Text="Add New Record" />
</asp:label>
</emptydatatemplate>
要捕获该按钮上的用户单击,为RowCommand事件编写一个处理程序:
void Gridview1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "AddNew")
{ ... }
}