添加 GridView 单选按钮列 (VB)
本教程介绍如何向 GridView 控件添加单选按钮列,以便为用户提供更直观的 GridView 单行选择方式。
简介
GridView 控件提供了大量内置功能。 它包含用于显示文本、图像、超链接和按钮的多个不同字段。 它支持用于进一步自定义的模板。 单击鼠标即可创建 GridView,其中每一行都可以通过按钮选择,或者启用编辑或删除功能。 尽管提供了大量功能,但经常会出现需要添加其他不受支持的功能的情况。 在本教程和接下来的两个教程中,我们将探讨如何增强 GridView 功能以包含其他功能。
本教程和下一个教程重点介绍如何增强行选择过程。 如 使用带有 DetailsView 的可选主网格视图的母版/详细信息中所述,我们可以将 CommandField 添加到包含“选择”按钮的 GridView。 单击后,将回发,GridView 的 SelectedIndex
属性将更新为单击了“选择”按钮的行的索引。 在 大纲/详细信息使用带有详细信息视图的可选主网格 视图教程中,我们了解了如何使用此功能显示所选 GridView 行的详细信息。
虽然“选择”按钮在很多情况下都有效,但它可能不适用于其他人。 其他两个用户界面元素通常用于选择,而不是使用按钮:单选按钮和复选框。 我们可以扩充 GridView,以便每行包含一个单选按钮或复选框,而不是“选择”按钮。 在用户只能选择其中一条 GridView 记录的情况下,单选按钮可能优先于“选择”按钮。 在用户可能选择多个记录(例如在基于 Web 的电子邮件应用程序中)的情况下,用户可能希望选择多封邮件以删除复选框,而“选择”按钮或单选按钮用户界面中提供的功能是不可用的。
本教程介绍如何将单选按钮列添加到 GridView。 本教程介绍如何使用复选框。
步骤 1:创建增强 GridView 网页
在开始增强 GridView 以包含一列单选按钮之前,让我们先花点时间在网站项目中创建本教程和后续两个页面所需的 ASP.NET 页面。 首先添加名为 EnhancedGridView
的新文件夹。 接下来,将以下 ASP.NET 页添加到该文件夹,确保将每个页面与 Site.master
母版页相关联:
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
图 1:为 SqlDataSource-Related 教程添加 ASP.NET 页
与其他文件夹中一样, Default.aspx
文件夹中 EnhancedGridView
会列出其部分的教程。 回想一下, SectionLevelTutorialListing.ascx
用户控件提供此功能。 因此,将此用户控件Default.aspx
从解决方案资源管理器拖到页面设计视图中,将其添加到 。
图 2:将 SectionLevelTutorialListing.ascx
用户控件添加到 Default.aspx
(单击以查看全尺寸图像)
最后,将这四个页面作为条目添加到 Web.sitemap
文件中。 具体而言,在“使用 SqlDataSource 控件 <siteMapNode>
”后面添加以下标记:
<siteMapNode
title="Enhancing the GridView"
url="~/EnhancedGridView/Default.aspx"
description="Augment the user experience of the GridView control.">
<siteMapNode
url="~/EnhancedGridView/RadioButtonField.aspx"
title="Selection via a Radio Button Column"
description="Explore how to add a column of radio buttons in the GridView." />
<siteMapNode
url="~/EnhancedGridView/CheckBoxField.aspx"
title="Selection via a Checkbox Column"
description="Select multiple records in the GridView by using a column of
checkboxes." />
<siteMapNode
url="~/EnhancedGridView/InsertThroughFooter.aspx"
title="Add New Records through the Footer"
description="Learn how to allow users to add new records through the
GridView's footer." />
</siteMapNode>
更新 Web.sitemap
后,请花点时间通过浏览器查看教程网站。 左侧菜单现在包含用于编辑、插入和删除教程的项目。
图 3:站点地图现在包含用于增强 GridView 教程的条目
步骤 2:在 GridView 中显示供应商
在本教程中,让我们生成一个 GridView,其中列出了来自美国的供应商,其中每个 GridView 行都提供一个单选按钮。 通过单选按钮选择供应商后,用户可以通过单击按钮查看供应商的产品。 虽然此任务听起来可能微不足道,但有许多微妙之处使其特别棘手。 在深入探讨这些微妙之处之前,让我们先获取一个列出供应商的 GridView。
首先打开文件夹中的页面RadioButtonField.aspx
,EnhancedGridView
方法是将 GridView 从工具箱拖到Designer。 将 GridView ID
设置为 Suppliers
,并从其智能标记中选择创建新的数据源。 具体而言,请创建一个名为 的 SuppliersDataSource
ObjectDataSource,用于从 SuppliersBLL
对象拉取其数据。
图 4:新建名为 SuppliersDataSource
的对象数据源 (单击 以查看全尺寸图像)
图 5:将 ObjectDataSource 配置为使用 SuppliersBLL
类 (单击以查看全尺寸图像)
由于我们只想列出位于美国的供应商,因此 GetSuppliersByCountry(country)
请从 SELECT 选项卡的下拉列表中选择方法。
图 6:将 ObjectDataSource 配置为使用 SuppliersBLL
类 (单击以查看全尺寸图像)
在“更新”选项卡中,选择“ (无) ”选项,然后单击“下一步”。
图 7:将 ObjectDataSource 配置为使用 SuppliersBLL
类 (单击以查看全尺寸图像)
GetSuppliersByCountry(country)
由于 方法接受参数,“配置数据源”向导会提示我们输入该参数的源。 若要 ( USA 指定硬编码值,在此示例中) ,请将“参数源”下拉列表保留设置为“无”,并在文本框中输入默认值。 单击“完成”以完成向导。
图 8:使用 USA 作为参数的默认值 country
(单击以查看全尺寸图像)
完成向导后,GridView 将包含每个供应商数据字段的 BoundField。 删除除 、 City
和 Country
BoundFields 外CompanyName
的所有属性,并将 CompanyName
BoundFields HeaderText
属性重命名为 Provider。 执行此操作后,GridView 和 ObjectDataSource 声明性语法应如下所示。
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
<SelectParameters>
<asp:Parameter DefaultValue="USA" Name="country" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
在本教程中,允许用户在供应商列表所在的页面或其他页面上查看所选供应商的产品。 若要适应这种情况,请将两个按钮 Web 控件添加到页面。 我已将这两个按钮ListProducts
的 设置为 ID
和 SendToProducts
,其理念是单击 时ListProducts
将发生回发,并且所选供应商的产品将列在同一页面上,但单击时SendToProducts
,用户将被移动到列出产品的另一个页面。
图 9 显示了 Suppliers
通过浏览器查看时的 GridView 和两个 Button Web 控件。
图 9:来自美国的供应商列出其名称、城市和国家/地区信息 (单击以查看全尺寸图像)
步骤 3:添加单选按钮列
此时, Suppliers
GridView 有三个 BoundField,显示美国每个供应商的公司名称、城市和国家/地区。 但是,它仍然缺少一列单选按钮。 遗憾的是,GridView 不包含内置的 RadioButtonField,否则我们可以将其添加到网格中并完成。 相反,我们可以添加 TemplateField 并将其配置为 ItemTemplate
呈现单选按钮,从而为每个 GridView 行生成一个单选按钮。
最初,我们可以假设可以通过将 RadioButton Web 控件添加到 TemplateField 的 来实现 ItemTemplate
所需的用户界面。 虽然这确实会将单个单选按钮添加到 GridView 的每一行,但单选按钮不能分组,因此不是互斥的。 也就是说,最终用户能够同时从 GridView 中选择多个单选按钮。
尽管使用 RadioButton Web 控件的 TemplateField 不提供所需的功能,但让我们实现此方法,因为值得检查为什么生成的单选按钮未分组。 首先,将 TemplateField 添加到 Suppliers GridView,使其成为最左侧的字段。 接下来,从 GridView 智能标记中,单击“编辑模板”链接,然后将 RadioButton Web 控件从工具箱拖到 TemplateField (ItemTemplate
请参阅图 10) 。 将 RadioButton s ID
属性设置为 RowSelector
,将 GroupName
属性设置为 SuppliersGroup
。
图 10:将 RadioButton Web 控件添加到 ItemTemplate
(单击以查看全尺寸图像)
通过Designer添加这些内容后,GridView 的标记应如下所示:
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:RadioButton ID="RowSelector" runat="server"
GroupName="SuppliersGroup" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
RadioButton s GroupName
属性 用于对一系列单选按钮进行分组。 具有相同 GroupName
值的所有 RadioButton 控件都被视为分组控件;一次只能从组中选择一个单选按钮。 属性 GroupName
指定呈现的单选按钮属性 name
的值。 浏览器检查单选按钮 name
属性以确定单选按钮分组。
将 RadioButton Web 控件添加到 后 ItemTemplate
,通过浏览器访问此页面,然后单击网格行中的单选按钮。 请注意单选按钮是如何不分组的,因此可以选择所有行,如图 11 所示。
图 11:GridView 单选按钮未分组 (单击以查看全尺寸图像)
单选按钮未分组的原因是,尽管其属性设置相同GroupName
,但呈现name
的属性不同。 若要查看这些差异,请从浏览器执行“视图/源”并检查单选按钮标记:
<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector"
name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector"
name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector"
name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector"
name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup"
type="radio" value="RowSelector" />
请注意, name
和 id
属性不是属性窗口中指定的确切值,而是在前面加上许多其他ID
值。 ID
添加到呈现id
的 前面和 name
属性的其他值是ID
单选按钮父控件GridViewRow
的 sID
、GridView 、ID
内容控件 和 ID
Web 窗体 。ID
ID
添加这些 ,以便 GridView 中呈现的每个 Web 控件都具有唯id
一的 和 name
值。
每个呈现的控件都需要不同的 name
id
,因为这是浏览器唯一标识客户端上每个控件的方式,以及它如何向 Web 服务器标识在回发时发生的操作或更改。 例如,假设每当 RadioButton 的选中状态发生更改时,我们希望运行一些服务器端代码。 为此,可以将 RadioButton s AutoPostBack
属性设置为 True
,并为 CheckChanged
事件创建事件处理程序。 但是,如果呈现 name
的 和 id
所有单选按钮的值都相同,则回发时无法确定单击的特定 RadioButton。
其简言之,我们无法使用 RadioButton Web 控件在 GridView 中创建单选按钮列。 相反,我们必须使用相当古老的技术来确保将适当的标记注入到每个 GridView 行中。
注意
与 RadioButton Web 控件一样,单选按钮 HTML 控件在添加到模板时将包含唯 name
一属性,使网格中的单选按钮取消分组。 如果不熟悉 HTML 控件,请随意忽略此注释,因为 HTML 控件很少使用,尤其是在 ASP.NET 2.0 中。 但是,如果你有兴趣了解详细信息,请参阅 K. Scott Allen 的博客文章 Web 控件和 HTML 控件。
使用文本控件注入单选按钮标记
为了正确分组 GridView 中的所有单选按钮,我们需要手动将单选按钮标记注入 到 ItemTemplate
中。 每个单选按钮都需要相同的 name
属性,但 (应具有唯 id
一属性,以防我们想要通过客户端脚本) 访问单选按钮。 用户选择单选按钮并发回页面后,浏览器将发送回所选单选按钮属性 value
的值。 因此,每个单选按钮都需要唯一 value
属性。 最后,在回发时,我们需要确保将 属性添加到 checked
所选的一个单选按钮,否则在用户进行选择并回发后,单选按钮将返回到其默认状态 (所有未选定的) 。
若要将低级别标记注入模板,可以采用两种方法。 一种是混合执行标记和对代码隐藏类中定义的格式设置方法的调用。 在 GridView 控件教程中使用 TemplateFields 中首先讨论了此方法。 在本例中,它可能如下所示:
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
此处, GetUniqueRadioButton
和 GetRadioButtonValue
将是代码隐藏类中定义的方法,这些方法返回每个单选按钮的相应 id
和 value
属性值。 此方法非常适合分配 id
和 value
属性,但在需要指定 checked
属性值时,这种方法并不有效,因为数据绑定语法仅在数据首次绑定到 GridView 时执行。 因此,如果 GridView 启用了视图状态,则仅当首次加载页面 (或 GridView 显式重新绑定到数据源) 时,才会触发格式设置方法,因此不会在回发时调用设置属性的 checked
函数。 这是一个相当微妙的问题,有点超出了本文的范围,所以我将留待它。 但是,我鼓励你尝试使用上述方法,并努力做到遇到困难。 虽然此类练习不会使你更接近工作版本,但它将有助于更深入地了解 GridView 和数据绑定生命周期。
在模板中注入自定义低级别标记的另一种方法是将 文本控件 添加到模板。 然后,在 GridView 或RowCreated
RowDataBound
事件处理程序中,可以通过编程方式访问 Literal 控件,并将其Text
属性设置为要发出的标记。
首先从 TemplateField 中删除 RadioButton, ItemTemplate
并将其替换为文本控件。 将文本控件 设置为 ID
RadioButtonMarkup
。
图 12:将文本控件添加到 ItemTemplate
(单击以查看全尺寸图像)
接下来,为 GridView 事件 RowCreated
创建事件处理程序。 无论 RowCreated
数据是否被重新绑定到 GridView,该事件都会针对添加的每一行触发一次。 这意味着,即使在从视图状态重新加载数据时回发时, RowCreated
事件仍会触发,这就是我们使用它的原因, RowDataBound
而不是 (仅当数据显式绑定到数据 Web 控件) 时才触发。
在此事件处理程序中,我们只想在处理数据行时继续。 对于每个数据行,我们希望以编程方式引用 RadioButtonMarkup
Literal 控件,并将其 Text
属性设置为要发出的标记。 如下面的代码所示,发出的标记将创建一个单选按钮,其 name
属性设置为 SuppliersGroup
RowSelectorX
id
,其中 X 是 GridView 行的索引,其 value
属性设置为 GridView 行的索引。
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex)
End If
End Sub
选择 GridView 行并发生回发时,我们对所选供应商的 感兴趣 SupplierID
。 因此,可能会认为每个单选按钮的值应是实际 SupplierID
(,而不是 GridView 行) 的索引。 虽然这在某些情况下可能起作用,但盲目接受和处理 SupplierID
会存在安全风险。 例如,我们的 GridView 仅列出了美国的供应商。 但是,如果 SupplierID
直接从单选按钮传递,那么有什么来阻止调皮的用户操作 SupplierID
回发时发送回的值? 通过将行索引用作 value
,然后从DataKeys
集合中回发时获取 SupplierID
,我们可以确保用户仅使用与其中一个 SupplierID
GridView 行关联的值。
添加此事件处理程序代码后,请花一点时间在浏览器中测试页面。 首先,请注意,一次只能选择网格中的一个单选按钮。 但是,选择单选按钮并单击其中一个按钮时,会发生回发,并且单选按钮将全部还原到其初始状态 (即,在回发时,所选单选按钮不再) 选中。 若要解决此问题,我们需要扩充 事件处理程序, RowCreated
以便它检查从回发发送的所选单选按钮索引, checked="checked"
并将 属性添加到行索引匹配项的发出标记。
发生回发时,浏览器会发送回 name
所选单选按钮的 和 value
。 可以使用 以编程方式检索 Request.Form("name")
值。 属性Request.Form
提供表示NameValueCollection
窗体变量的 。 表单变量是网页中表单字段的名称和值,每当发生回发时,Web 浏览器会发送回。 由于 GridView 中单选按钮的呈现 name
属性为 SuppliersGroup
,因此,当回发网页时,浏览器将连同) 的其他表单字段 (发 SuppliersGroup=valueOfSelectedRadioButton
回 Web 服务器。 然后,可以使用 从 属性访问 Request.Form
此信息: Request.Form("SuppliersGroup")
。
由于我们不仅需要在事件处理程序中确定选定的单选按钮索引,还需要在 RowCreated
Button Web 控件的事件处理程序中 Click
确定,因此,让我们向代码隐藏类添加属性 SuppliersSelectedIndex
,该属性在未选择任何单选按钮时返回 ;如果选择了其中一个单选按钮,则返回 -1
所选索引。
Private ReadOnly Property SuppliersSelectedIndex() As Integer
Get
If String.IsNullOrEmpty(Request.Form("SuppliersGroup")) Then
Return -1
Else
Return Convert.ToInt32(Request.Form("SuppliersGroup"))
End If
End Get
End Property
添加此属性后,我们知道在 等于 e.Row.RowIndex
时SuppliersSelectedIndex
在RowCreated
事件处理程序中添加checked="checked"
标记。 更新事件处理程序以包含此逻辑:
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}"", e.Row.RowIndex)
' See if we need to add the "checked" attribute
If SuppliersSelectedIndex = e.Row.RowIndex Then
output.Text &= " checked="checked""
End If
' Add the closing tag
output.Text &= " />"
End If
End Sub
进行此更改后,所选单选按钮在回发后保持选中状态。 现在,我们能够指定选择了哪个单选按钮,我们可以更改行为,以便在首次访问页面时,第一个 GridView 行单选按钮 (选中,而不是默认没有选择任何单选按钮,这是当前行为) 。 若要默认选择第一个单选按钮,只需将 If SuppliersSelectedIndex = e.Row.RowIndex Then
语句更改为以下内容: If SuppliersSelectedIndex = e.Row.RowIndex OrElse (Not Page.IsPostBack AndAlso e.Row.RowIndex = 0) Then
。
此时,我们已向 GridView 添加了一列分组单选按钮,允许跨回发选择和记住单个 GridView 行。 后续步骤是显示所选供应商提供的产品。 在步骤 4 中,我们将了解如何将用户重定向到另一个页面,并沿所选 SupplierID
发送 。 在步骤 5 中,我们将了解如何在同一页面上的 GridView 中显示所选供应商的产品。
注意
我们可以创建一个呈现相应用户界面和功能的自定义 DataControlField
类,而不是使用 TemplateField (此冗长步骤 3) 的重点。 类DataControlField
是派生 BoundField、CheckBoxField、TemplateField 和其他内置 GridView 和 DetailsView 字段的基类。 创建自定义 DataControlField
类意味着只需使用声明性语法即可添加单选按钮列,并且还会大大简化在其他网页和其他 Web 应用程序上复制功能。
但是,如果你曾经在 ASP.NET 中创建了自定义的编译控件,你知道这样做需要相当多的腿部工作,并且附带着大量必须仔细处理的微妙和边缘情况。 因此,我们暂时放弃将单选按钮列实现为自定义 DataControlField
类,并坚持使用 TemplateField 选项。 也许我们将有机会在未来的教程中探索如何创建、使用和部署自定义 DataControlField
类!
步骤 4:在单独的页面中显示所选供应商的产品
用户选择 GridView 行后,需要显示所选供应商的产品。 在某些情况下,我们可能需要在单独的页面中显示这些产品,而在另一些情况下,我们可能希望在同一个页面中显示这些产品。 让我们首先看看如何在单独的页面中显示产品;在步骤 5 中,我们将介绍如何将 GridView 添加到 RadioButtonField.aspx
以显示所选供应商的产品。
当前页面上有两个按钮 Web 控件 ListProducts
和 SendToProducts
。 SendToProducts
单击按钮时,我们希望将用户发送到 ~/Filtering/ProductsForSupplierDetails.aspx
。 此页面是在跨两页筛选母版/详细信息教程中创建的,它显示通过名为 SupplierID
的查询字符串字段传递的SupplierID
供应商的产品。
若要提供此功能,请为 SendToProducts
Button 事件 Click
创建事件处理程序。 在步骤 3 中,我们添加了 SuppliersSelectedIndex
属性,该属性返回选择了单选按钮的行的索引。 可以从 GridView 的 集合中检索相应的 SupplierID
,然后可以使用 将用户发送到 ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
Response.Redirect("url")
。DataKeys
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End Sub
只要从 GridView 中选择了其中一个单选按钮,此代码就非常有效。 如果最初 GridView 未选择任何单选按钮,并且用户单击该 SendToProducts
按钮, SuppliersSelectedIndex
则 将为 -1
,这将导致引发异常,因为 -1
不在集合的 DataKeys
索引范围内。 但是,如果决定按照步骤 3 中所述更新 RowCreated
事件处理程序,以便最初选择 GridView 中的第一个单选按钮,则这不是问题。
若要容纳 SuppliersSelectedIndex
值 -1
,请将标签 Web 控件添加到 GridView 上方的页面。 将其 ID
属性设置为 ChooseSupplierMsg
,其 CssClass
属性设置为 Warning
,其 EnableViewState
和 Visible
属性设置为 False
,其 Text
属性设置为 请从网格中选择供应商。 CSS 类 Warning
以红色、斜体、粗体、大字体显示文本,并在 中 Styles.css
定义。 通过将 和 Visible
属性设置为 EnableViewState
False
,除了控件 的 Visible
属性以编程方式设置为 True
的回发之外,不会呈现 Label。
图 13:在 GridView 上方添加标签 Web 控件 (单击以查看全尺寸图像)
接下来,如果 小于零,则 Click
扩充事件处理程序以显示 ChooseSupplierMsg
Label SuppliersSelectedIndex
,否则将用户重定向到 ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
。
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
Else
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End If
End Sub
在从 GridView 中选择供应商之前, SendToProducts
访问浏览器中的页面并单击该按钮。 如图 14 所示,这将显示 ChooseSupplierMsg
标签。 接下来,选择供应商并单击按钮 SendToProducts
。 这会将您带至一个页面,其中列出了所选供应商提供的产品。 图 15 显示了 ProductsForSupplierDetails.aspx
选择 Bigfoot Breweries 供应商时的页面。
图 14: ChooseSupplierMsg
如果未选择供应商,则显示标签 (单击以查看全尺寸图像)
图 15:所选供应商的产品显示在 ProductsForSupplierDetails.aspx
(单击以查看全尺寸图像)
步骤 5:在同一页上显示所选供应商的产品
在步骤 4 中,我们了解了如何将用户发送到另一个网页以显示所选供应商的产品。 或者,所选供应商的产品可以显示在同一页上。 为了说明这一点,我们将向 添加另一个 GridView RadioButtonField.aspx
以显示所选供应商的产品。
由于我们只希望在选择供应商后显示产品的 GridView,因此在 GridView 下 Suppliers
添加面板 Web 控件,将其 ID
设置为 ProductsBySupplierPanel
,将其 Visible
属性设置为 False
。 在面板中,添加文本“所选供应商的产品”,后跟名为 的 ProductsBySupplier
GridView。 在 GridView 智能标记中,选择将其绑定到名为 ProductsBySupplierDataSource
的新 ObjectDataSource。
图 16:将 ProductsBySupplier
GridView 绑定到 New ObjectDataSource (单击以查看全尺寸图像)
接下来,将 ObjectDataSource 配置为使用 ProductsBLL
类。 由于我们只想检索所选供应商提供的产品,因此指定 ObjectDataSource 应调用 GetProductsBySupplierID(supplierID)
方法来检索其数据。 从“更新”、“插入”和“删除”选项卡的下拉列表中选择“ (无) ”。
图 17:将 ObjectDataSource 配置为使用 GetProductsBySupplierID(supplierID)
方法 (单击以查看全尺寸图像)
图 18:在“更新”、“插入”和“删除”选项卡中将 Drop-Down Lists 设置为“ () 无” (单击以查看全尺寸图像)
配置 SELECT、UPDATE、INSERT 和 DELETE 选项卡后,单击“下一步”。 GetProductsBySupplierID(supplierID)
由于 该方法需要输入参数,“创建数据源”向导会提示我们指定参数值的源。
此处有几种指定参数值源的选项。 可以使用默认的 Parameter 对象,以编程方式将 属性的值 SuppliersSelectedIndex
分配给 ObjectDataSource 事件处理程序中的 Parameter DefaultValue
属性 Selecting
。 有关以 编程方式将值分配给 ObjectDataSource 参数的复习,请参阅以编程方式设置 ObjectDataSource 的参数值教程。
或者,可以使用 ControlParameter 并引用 Suppliers
GridView 属性SelectedValue
( 见图 19) 。 GridView 属性SelectedValue
返回与 DataKey
属性对应的SelectedIndex
值。 若要使此选项正常工作,我们需要在单击按钮时ListProducts
以编程方式将 GridView 属性SelectedIndex
设置为所选行。 另一个好处是,通过设置 SelectedIndex
,所选记录将采用 SelectedRowStyle
主题 (黄色背景) 中定义的 DataWebControls
。
图 19:使用 ControlParameter 将 GridView s SelectedValue 指定为参数源 (单击以查看全尺寸图像)
完成向导后,Visual Studio 将自动添加产品数据字段的字段。 删除除 、 CategoryName
和 UnitPrice
BoundFields 之外ProductName
的所有属性,并将HeaderText
属性更改为 Product、Category 和 Price。 配置 UnitPrice
BoundField,使其值的格式设置为货币。 进行这些更改后,Panel、GridView 和 ObjectDataSource 的声明性标记应如下所示:
<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
<h3>
Products for the Selected Supplier</h3>
<p>
<asp:GridView ID="ProductsBySupplier" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
<SelectParameters>
<asp:ControlParameter ControlID="Suppliers" Name="supplierID"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
</p>
</asp:Panel>
若要完成此练习,我们需要在单击按钮时将 GridView 的 SelectedIndex
属性SelectedSuppliersIndex
设置为 ,ProductsBySupplierPanel
将 Panel 属性Visible
设置为 True
。ListProducts
为此,请为 ListProducts
Button Web 控件 事件 Click
创建事件处理程序,并添加以下代码:
Protected Sub ListProducts_Click(sender As Object, e As EventArgs) _
Handles ListProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
ProductsBySupplierPanel.Visible = False
Else
' Set the GridView's SelectedIndex
Suppliers.SelectedIndex = SuppliersSelectedIndex
' Show the ProductsBySupplierPanel panel
ProductsBySupplierPanel.Visible = True
End If
End Sub
如果尚未从 GridView 中选择供应商,则会 ChooseSupplierMsg
显示标签并 ProductsBySupplierPanel
隐藏面板。 否则,如果已选择供应商, ProductsBySupplierPanel
则显示 并更新 GridView 属性 SelectedIndex
。
图 20 显示了选择 Bigfoot Breweries 供应商并单击“在页面上显示产品”按钮后的结果。
图 20:Bigfoot Breweries 提供的产品列在同一页上 (单击以查看全尺寸图像)
总结
如使用带有 DetailsView 的可选主网格视图教程中所述,可以使用属性设置为 True
的 ShowSelectButton
CommandField 从 GridView 中选择记录。 但 CommandField 将其按钮显示为常规按钮、链接或图像。 另一种行选择用户界面是在每个 GridView 行中提供单选按钮或复选框。 在本教程中,我们检查了如何添加单选按钮列。
遗憾的是,添加一列单选按钮并不像预期的那样简单或简单。 没有内置 RadioButtonField 可在单击按钮时添加,在 TemplateField 中使用 RadioButton Web 控件会引入其自身的一组问题。 最后,为了提供这样的接口,我们必须创建自定义 DataControlField
类,或者在事件期间 RowCreated
将相应的 HTML 注入到 TemplateField 中。
在探索了如何添加单选按钮列之后,让我们将注意力转向添加一列复选框。 使用一列复选框,用户可以选择一个或多个 GridView 行,然后对 (的所有选定行执行某些操作,例如从基于 Web 的电子邮件客户端选择一组电子邮件,然后选择删除所有选定的电子邮件) 。 在下一教程中,我们将了解如何添加此类列。
编程愉快!
关于作者
Scott Mitchell 是七本 ASP/ASP.NET 书籍的作者, 4GuysFromRolla.com 的创始人,自 1998 年以来一直从事 Microsoft Web 技术工作。 Scott 担任独立顾问、培训师和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0自学。 可以在 上联系 mitchell@4GuysFromRolla.com他, 也可以通过他的博客联系到他,该博客可在 http://ScottOnWriting.NET中找到。
特别感谢
本教程系列由许多有用的审阅者查看。 本教程的首席审阅者是 David Suru。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处放置一行 mitchell@4GuysFromRolla.com。