欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton

程序员文章站 2023-12-17 14:58:34
导言:   gridview控件提供了大量的内置功能。它包含了一系列的域(field)来显示诸如text、images、hyperlinks和buttons。另外它支持模...

导言:

  gridview控件提供了大量的内置功能。它包含了一系列的域(field)来显示诸如text、images、hyperlinks和buttons。另外它支持模板(template)用于用户自定义界面。我们可以构建这样一个gridview控件,用户仅需要点击控件里的一个按钮,每一条记录行都可以选择、编辑、删除。除了控件本身内置的功能外,在某些情况下,我们添加一些额外的、控件没有内置的功能。在本章及接下来的2篇教程里我们将探讨如何优化gridview,以支持额外的功能。

  本篇及接下来的教程将主要探讨优化行选择程序(row-selection process),就像在教程《使用 gridview和detailview实现的主/从报表》里考察的一样,我们在gridview控件里添加一个包含选择按钮的命令域(commandfield),点击该按钮后产生回传(postback),所选行的index值传给gridview控件的selectedindex属性。在那篇教程里我们看到了如何使用该功能显示所选行的详细信息。

  除了select button,我们经常在用户界面包含radio button和checkbox用于选择记录。在某些情况下我们可以对gridview扩充,在每条记录里用radio button或checkbox替换掉select button。比如,我们只希望选择gridview记录中的一条时,用radio button比用select button好;再比如,当用户要选择多条记录时——就像在邮箱里同时删除几份邮件一样,用checkbox是最好的。本教程先考察为gridview添加radio buttons,再考察添加checkboxes。

第一步:创建优化gridview的web页面

  在开始之前让我们在网站项目里创建一个本节及后面2节要用到的asp.net页面。新建一个名为enhancedgridview的文件夹,然后,添加如下所示的页面,确保使用site.master母版。

default.aspx
radiobuttonfield.aspx
checkboxfield.aspx
insertthroughfooter.aspx

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图1:添加相关页面

  像其它文件夹一样,default.aspx页面将显示本节的所有教程。记得用户控件sectionleveltutoriallisting.ascx提供该功能,从解决方案管理器里将其拖到default.aspx页面上。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图2:添加用户控件sectionleveltutoriallisting.ascx

  最后,将这4篇教程添加到web.sitemap文件里,特别的,加在“using the sqldatasource control” <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>

完成后,花几分钟在浏览器查看该系列教程,如图所示:

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图3:site map里完整地列出了本系列教程

第2步:在gridview控件里显示供应商

  让我们创建一个gridview控件,用于显示来自美国的供应商列表,同时每行记录包含一个radio button。当点击radio button后,用户将查看到供应商提供的产品。在开始具体研究如何实现以前,我们先创建一个显示供应商的gridview。

  在文件夹enhancedgridview里打开adiobuttonfield.aspx页面,进入设计模式,从工具箱拖一个gridview到页面。设其id为suppliers,在智能标签里选“创建新数据源”,特别的,我们选用objectdatasource,命名为suppliersdatasource,然后选用suppliersbll 。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图4:创建一个名为suppliersdatasource的objectdatasource

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图5:设置该objectdatasource使用suppliersbll类

因为我们只想列出来自美国的供应商,在select选项卡的下拉列表里选择 getsuppliersbycountry(country)方法。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图6:设置该objectdatasource使用suppliersbll类(原文如此)

在update选项卡选择“(none)”,点下一步

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图7:设置该objectdatasource使用suppliersbll类(原文如此)

  因为getsuppliersbycountry(country)方法需要接受一个参数,向导提示我们设置参数源,在这里我们指定一个“硬编码”值(就本例而言,我们指定usa),在数据源下拉列表里选“none”,在指定值文本框输入“usa”。点“完成”结束向导设置。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图8:为参数country使用默认值“usa”

  只保留gridview里的companyname, city和country三列(boundfields),其余的全部删除。同时将companyname列的headertext属性改为“supplier”。设置完以后, 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>

  在本篇教程,当点击某个供应商时,将在本业或另一页显示该供应商提供的产品。为达到该目的,我们在页面添加2个button web控件。id分别为listproducts和sendtoproducts,当点击listproducts按钮时,发生回传(postback),接着将在本页面显示该供应商的产品,当点击sendtoproducts按钮时,将会链接到另一个页面,显示该供应商的产品。
图9显示了gridview控件和添加的两个button web控件。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图9:显示供应商的 name, city和country信息

第3步:添加radio buttons列

  至此,gridview里包含company name, city和country三列,但还缺少radio buttons列。不幸的是gridview控件并不包含内置的radiobuttonfield,因此只有我们自己手动添加。我们可以添加一个模板(templatefield)并在其itemtemplate模板里显示一个radio button。这样的话就为gridview控件的每一行记录添加了一个radio button。

  我们首先可能会想到直接在templatefield的itemtemplate模版里添加一个radiobutton web控件。不错,这样将为每一行添加radio button,但是这些radio button不能聚合,因此不能形成互斥关系。造成的后果是,最终用户可以在gridview控件里同时选定多个radio button按钮。

  虽然这样做不能到达我们期望的要求,不过还是值得我们花时间来考察一下为什么这些radio button不能聚合。首先,为gridview添加一个templatefield,放置在最左边,然后智能标签里选“编辑模板”,进入templatefield的itemtemplate 模板,从工具箱拖一个radio button控件到模板(见图10),设置其id为rowselector , groupname属性为suppliersgroup。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图10:在itemtemplate模板添加一个radiobutton控件

完成设置后,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的groupname属性的作用在于:具有相同groupname值的radiobutton控件被认为是一个组,在一个组里面只有一个控件可以被选择(即具有互斥性)。groupname属性为radio button的名称特征(nameattribute)指定值,浏览器检查radio button的名称特征,再对其分组。

  在浏览器里查看页面,选择所有行,可以看出这些radio button并没有聚合(也就是不具有互斥性),如图11所示:

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图11:gridview的radio buttons没有聚合。

  不能聚合的原因在于:尽管将他们的groupname属性设置为相同的,但提交的名称属性是不同的。在浏览器里点查看/源代码,检查这些radio button的代码:

<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值和在属性窗口指定的准确值(exact values)相比,在开头多了一些其它id值(比如id="ctl00_maincontent_suppliers_ctl02_rowselector" 和id="rowselector"相比),这些多出来的ids值来自于这些 radio buttons的父级控件(parent controls)——gridviewrow、gridview、content control以及web form。加上这些ids的目的是使gridview控件里的每个rendered web control(具体到本例就是这些radio button)具有唯一的id值和name值。

  这样做的原因在于:在客户端,便于浏览器区分每个rendered control(比如本章的radio button);在网络服务器端,便于服务器区分当页面回传时发生了什么事件或改变。比如,无论何时,当一个 radiobutton的选中状态(checked state)发生改变时,我们希望运行某些服务器端代码。为此,我们可以将radiobutton的autopostback属性设置为true,同时为checkchanged事件创建一个事件处理器。如果每个radio buttons的name和id值相同的话,当发生页面回转时,我们不能确定到底点击了哪个radiobutton。

  这样做的缺点在于,我们不能用radiobutton web 控件在gridview里创建一个radio button列。因此,我们必须在gridview row里添加适当的代码。

  注意:和radiobutton web控件一样,当把radio button html控件添加到模板时,它也会包含唯一的名称特征。如果你不熟悉html控件,没关系,因为很少使用它,尤其在asp.net 2.0里。如果有兴趣了解更多,见 k. scott allen的博客里的文章web controls and html controls.

用literal控件注入radio button代码

  为了在gridview控件里对radio buttons进行聚合,我们要在itemtemplate模板里手动注入radio button代码。每个radio button具有相同的name特性,但id特性必须是唯一的(因为我们可能需要通过客户端脚本访问某个radio button)。因为当用户选择了一个radio button,页面回传后,浏览器将返回该按钮的一个值,所以每个radio button要具备一个唯一值特性(unique value attribute)。最后,当选择一个radio button后,我们应确保为该按钮添加checked属性。另外,用户做了选择并发生回传后,radio button将回到默认状态(可任意指定)。

  可以有2种方法在模板里注入代码。其中一种是在代码里调用定义在后台代码类(code-behind class)里的方法,并使用格式化的形式。这个方法我们在教程《在gridview控件中使用templatefield》里论述过。在本例,代码看起来像这个样子:

<input type="radio" id='<%# getuniqueradiobuttonid(...) %>' 
 name='suppliersgroup' value='<%# getradiobuttonvalue(...) %>' ... />

  其中,getuniqueradiobutton和getradiobuttonvalue是定义在后台代码类里的方法,其作用是返回特定的id和value值。用这种可以对radio button的id属性和 value属性赋值,但不能对checked属性赋值。因为只有当数据第一次绑定到该gridview控件时,数据绑定语法才能成功执行。所以只有当启用gridview的试图状态,并且是第一次登录页面(或者明确的让gridview重新绑定数据源)时这种格式化的方法才能奏效。所以,当页面发生回传时,对checked属性赋值的这个功能是失效的。这个问题有点超出了本教程的范围,所以在这里我将它搁置一边,然而我仍然鼓励你用上面的这个方法。这个练习将使你更深入的理解gridview以及数据绑定的生命周期。

  第2种,也是本教程要用的方法是在模板里添加一个literal控件。在gridview的rowcreated或rowdatabound事件处理器里,我们可以通过编程来访问literal控件,并设置其text属性。

  在templatefield的itemtemplate模板里,移除radiobutton控件,换成literal控件,设其id为radiobuttonmarkup。

 在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图12:在itemtemplate模板里添加一个literal控件

  然后,为gridview的rowcreated事件创建事件处理器。rowcreated事件是这样的,不管数据是不是重新绑定到gridview,只要在gridview里新增一行记录就将引发rowcreated事件。那意味着,当发生回传事件时,哪怕数据来自视图状态,也会引发rowcreated事件。我们使用rowcreated事件而不使用rowdatabound事件的原因在于,只有当数据明确的绑定到数据web控件时才会引发rowdatabound事件.


  在rowcreated事件处理器里,我们处理的是某一行记录。对每一行记录,我们通过编程引用literal控件radiobuttonmarkup,然后在其text属性里声明代码。比如下面的代码,我们创建一个radio button ,设置其name属性为suppliersgroup,id属性为rowselectorx,其中x代表 gridview row的index值,将value属性也设置为gridview row的index值。

protected void suppliers_rowcreated(object sender, gridviewroweventargs e)
{
 if (e.row.rowtype == datacontrolrowtype.datarow)
 {
  // grab a reference to the literal control
  literal output = (literal)e.row.findcontrol("radiobuttonmarkup");
  // 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);
 }
}

  当选择gridview控件的某条记录时,我们关心的是该供应商的supplierid值。我们首先会想到让radio button的value属性返回该supplierid值(而不是该条记录的index值)。然而这样盲目地获取并传递一个supplierid值是很危险的。以我们的gridview控件为例,它列出了所有的美国供应商,如果我们直接通过radio button来传递supplierid,我们无法阻止一个带有恶意的用户对回传过来的supplierid造假。通过将value属性设置为某条记录的index值,当发生页面回传时,从datakeys集合里获取该供应商的supplierid值。这样的话,我们就能确保用户只能使用gridview里某个供应商的对应的supplierid值。

  添加完事件处理器代码后,花几分钟在浏览器里测试该页面,首先确保每次只能选择一个radio button。然而,当选择一个radio button并点击下面的按钮,在页面发生回传后,所有的radio button都回到最初的状态(意即,发生回传后,选中的radio button又恢复未选状态)。怎样解决这个问题呢?我们在rowcreated事件处理器里添加代码,先确定发生页面回传后,选中的那个radio button的index值,然后添加checked="checked"属性。

  当发生页面回传后,浏览器返回选中的radio button的name和value值.我们可以通过编程来获取值,比如:request.form["name"]。request.form属性用一个namevaluecollection来表示form变量。在这里,form变量就是发生回转时,浏览器返回的那些names和values值。 因为gridview控件里的radio buttons的name属性是suppliersgroup,当页面发生回转时,浏览器向网络服务器传回“suppliersgroup=valueofselectedradiobutton”(连同其它form fields一起传回)。我们可以用request.form属性访问这些信息:request.form["suppliersgroup"]

  我们不仅需要在rowcreated事件处理器中确定所选radio button的index值,在click事件处理器里同样需要。让我们在后台代码类里创建suppliersselectedindex。如果没有radio button被选定则返回-1,如果有radio button被选定则返回它的index值。如下:

private int suppliersselectedindex
{
 get
 {
  if (string.isnullorempty(request.form["suppliersgroup"]))
   return -1;
  else
   return convert.toint32(request.form["suppliersgroup"]);
 }
}

  当suppliersselectedindex的值与e.row.rowindex的值相同时,我们应在rowcreated事件处理器里添加checked="checked"代码。修改如下:

protected void suppliers_rowcreated(object sender, gridviewroweventargs e)
{
 if (e.row.rowtype == datacontrolrowtype.datarow)
 {
  // grab a reference to the literal control
  literal output = (literal)e.row.findcontrol("radiobuttonmarkup");
  // 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)
   output.text += @" checked="checked"";
  // add the closing tag
  output.text += " />";
 }
}

  经过上述修改后,选中的radio button在页面回传后仍然处于选中状态。现在我们可以指定某个radio button处于选中状态。当第一次登录页面时我们可以指定选中gridview里的第一条记录的radio button按钮(默认状态是没有一个radio button被选中,就像现在一样)。为此,我们只需简单地将if (suppliersselectedindex == e.row.rowindex) 改成if (suppliersselectedindex == e.row.rowindex || (!page.ispostback && e.row.rowindex == 0)).

  到这一步,我们为gridview创建了一个聚合的radio buttons列。它只允许选中其中的任一条记录,并在页面发生回传后仍处于选中状态。接下来,我们将显示某个选中的供应商提供的产品。在第4步,我们将看如何将用户链接到另一个显示产品的页面,并传递该供应商的supplierid值;在第5步,我们将探讨如何在相同页面显示供应商的产品。

  注意:与其用templatefield模板(在第3步讨论的那样),还不如创建一个自定义的datacontrolfield class类来构建用户界面并提供相关功能。datacontrolfield class是一个基本类,gridview和detailsview控件中内置的boundfield、checkboxfield、templatefield等都源于它。如果创建自定义datacontrolfield的话,我们可以在声明代码中添加radio buttons列,复制其它页面的函数及应用程序也要容易些。

  如果你在asp.net里创建过自定义控件的话,你应该知道那需要了解更多的知识,并且需要小心处理很多问题。因此,我们目前不用自定义datacontrolfield class类,还是坚持用templatefield模板。或许我们将在以后的教程里探讨如何使用自定义datacontrolfield class类。

第4步:在另一个页面显示供应商的产品

  在gridview里选中一条记录后,我们需要显示该供应商的产品。有时候下我们想在另一个页面显示产品,而有时候我们想在同一页面显示数据。首先,我们探讨如何在另一个页面显示产品,在第5步,我们将在radiobuttonfield.aspx页面添加一个gridview显示产品。

  当前,页面上有2个button web控件——listproducts和sendtoproducts。当点击sendtoproducts时,我们希望将用户链接到位于~/filtering/productsforsupplierdetails.aspx的页面。我们在教程《》里已经创建了该页面,供应商的supplierid是由一个名为supplierid的querystring field传递的。

  为提供该功能,我们为sendtoproducts的click事件创建事件处理器。在第3步,我们添加了suppliersselectedindex属性,用于返回所选行记录的index值。在如下代码中,相应的supplierid可以从gridview控件的datakeys集合获取,并转到~/filtering/productsforsupplierdetails.aspx?supplierid=supplierid using response.redirect("url")页面。

protected void sendtoproducts_click(object sender, eventargs e)
{
 // send the user to ~/filtering/productsforsupplierdetails.aspx
 int supplierid = 
  convert.toint32(suppliers.datakeys[suppliersselectedindex].value);
 response.redirect(
  "~/filtering/productsforsupplierdetails.aspx?supplierid=" 
  + supplierid);
 }
}

  当在gridview控件里选中一个radio button时,以上代码运行正常。但是,如果最开始gridview里没有任何radio buttons被选中,而用户又点击了sendtoproducts按钮,suppliersselectedindex就会赋值为-1,这将会抛出一个异常,因为在datakeys集合里没有index为-1的情况。不过没有关系,就像在第3步中探讨的一样,修改rowcreated事件处理器,使gridview默认选中第一个radio button。

  为了应对suppliersselectedindex为-1的情况,我们在gridview上面添加一个label web控件,设其id为choosesuppliermsg,cssclass 属性为warning,enableviewstate和visible属性为false,text属性为“please choose a supplier from the grid.”。定义在styles.css文件里的css class warning将文本显示为红色、斜体、大号加粗。通过将enableviewstate和visible属性设置为false,该label控件将不可见,除非在某些页面回传时,我们有意地通过编程将其visible属性设置为true。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图13:在gridview控件上添加一个label web控件

  接着,在click事件处理器里添加代码,如果suppliersselectedindex的值小于0时label控件choosesuppliermsg将可见,并将用户直接链接到~/filtering/productsforsupplierdetails.aspx?supplierid=supplierid页面:

protected void sendtoproducts_click(object sender, eventargs e)
{
 // make sure one of the radio buttons has been selected
 if (suppliersselectedindex < 0)
  choosesuppliermsg.visible = true;
 else
 {
  // send the user to ~/filtering/productsforsupplierdetails.aspx
  int supplierid = 
   convert.toint32(suppliers.datakeys[suppliersselectedindex].value);
  response.redirect(
   "~/filtering/productsforsupplierdetails.aspx?supplierid=" 
   + supplierid);
 }
}

  在浏览器里访问该页面,在不选供应商的情况下点击sendtoproducts按钮,如图14所示,label控件choosesuppliermsg变为可见了。然后,选择一个供应商,再单击sendtoproducts按钮,这会将你链接到一个显示该供应商产品的页面。图15显示了当选择供应商bigfoot breweries时,productsforsupplierdetails.aspx
页面的情况。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图14:未选供应商时,label控件choosesuppliermsg为可见

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图15:productsforsupplierdetails.aspx页面显示了供应商的产品

第5步:在本页显示所选供应商的产品

  在第4步,我们探讨了怎样在另一页面显示供应商的产品,另外我们也可以在本页面显示产品。鉴于此,我们在radiobuttonfield.aspx页面添加另一个gridview控件展示所选供应商的产品。

  一旦选择一个供应商后,我们只想在gridview里显示该供应商的产品。在名为suppliers的gridview控件下,添加一个panel web控件,设其id为productsbysupplierpanel,将visible属性设置为false,text属性设置为“products for the selected supplier”, 紧接着添加一个名为productsbysupplier的gridview控件。在其智能标签里,将其绑定到一个名为productsbysupplierdatasource的objectdatasource控件。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图16:将gridview控件productsbysupplier绑定到一个新的objectdatasource

   然后,将设置该objectdatasource使用productsbll类。由于我们只想获取一个供应商的产品数据,指定该objectdatasource控件调用getproductsbysupplierid(supplierid)方法,同时在update, insert和delete选项卡的下拉列表里选“(none)” 。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图17:指定该objectdatasource控件调用getproductsbysupplierid(supplierid)方法

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图18:在update, insert和delete选项卡的下拉列表里选“(none)”

  完成对select, update, insert和delete选项卡的设置后,点下一步。因为getproductsbysupplierid(supplierid)方法需要一个输入参数,因此向导提示我们指定参数值的来源。

  我们有几种选择指定参数值来源。我们可以使用默认值,也可以在objectdatasource控件的selecting事件处理器里,通过编程的方式,用suppliersselectedindex属性的值对parameter的defaultvalue属性赋值。可以在前面的教程《编程设置objectdatasource的参数值》里温习相关内容。

  此外,我们可以使用一个controlparameter,它涉及到名为suppliers的gridview控件的selectedvalue属性(见图19)。gridview控件的selectedvalue属性将返回与selectedindex属性相匹配的datakey值。为此,当点击listproducts按钮时,我们将编程把gridview控件的selectedindex属性设置为选中的那行记录。另外设置了selectedindex后,选中的记录将运用定义在datawebcontrols主题中的selectedrowstyle(显示为黄色背景)。

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图19:用一个controlparameter当参数源来指定gridview的selectedvalue值

  完成向导后,visual studio将自动添加产品的数据域(data fields)。将除了productname, categoryname和unitprice外的其它列全部删除,并将headertext属性分别设为“product”, “category”和“price”。再将unitprice列格式化为货币形式。完成上述修改后,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>

  当点击listproducts按钮时,我们需要将gridview的selectedindex属性设置为selectedsuppliersindex,并将panel控件productsbysupplierpanel的visible属性设置为true。为listproducts按钮的click事件创建事件处理器,添加如下代码:

protected void listproducts_click(object sender, eventargs e)
{
 // make sure one of the radio buttons has been selected
 if (suppliersselectedindex < 0)
 {
  choosesuppliermsg.visible = true;
  productsbysupplierpanel.visible = false;
 }
 else
 {
  // set the gridview's selectedindex
  suppliers.selectedindex = suppliersselectedindex;
  // show the productsbysupplierpanel panel
  productsbysupplierpanel.visible = true;
 }
}

  如果没有从gridview里选择供应商,label控件choosesuppliermsg将显示出来,而panel控件productsbysupplierpanel则不可见。反之,如果选择了一个供应商,productsbysupplierpanel将显示出来,并且gridview的selectedindex属性将更新。

图20为选择供应商bigfoot breweries并单击“show products on page”按钮后的效果图。

 在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
图20:在本页显示供应商bigfoot breweries的产品

总结:

  就像在教程《使用 gridview和detailview实现的主/从报表》里探讨的一样,如果在gridview里使用一个commandfield,并设置其showselectbutton属性为true,我们就可以在gridview里选择记录。但是commandfield仅仅将其按钮显示为常规的button, link或image。在一个只能选择一条记录的用户界面里,要为每一个gridview row提供一个radio button或checkbox。本教程探究了如何添加一个radio button列。

  然而,添加一个radio button列并没有想像的那么容易。没有内置的radiobuttonfield供我们添加;在模板里使用radiobutton web控件也会引发其它的问题。要创建这种用户界面,我们要么创建自定义的datacontrolfield类,要么在rowcreated事件里将适当的html注入模板。

  在探讨了如何添加radio buttons列后,我们将注意力转向添加checkboxes列。使用checkboxes列的话,用户可以选择一条或多条gridview rows并执行相同的操作。(比如在邮箱里,我们同时选择多封邮件并将之删除)。在接下来的教程里我们看如何来实现。

  祝编程快乐!

作者简介

  本系列教程作者 scott mitchell,著有六本asp/asp.net方面的书,是4guysfromrolla.com的创始人,自1998年以来一直应用 微软web技术。大家可以点击查看全部教程《[翻译]scott mitchell 的asp.net 2.0数据教程》,希望对大家的学习asp.net有所帮助。

相关标签: ASP.NET RadioButton

上一篇:

下一篇: