在ASP.NET 2.0中操作数据之十四:使用FormView 的模板
导言
在上两节教程中,我们看到了如何使用templatefield来自定义gridview和detailsview的输入。templatefield使我们可以高度自主的定义某个特定的列,但不管是gridview还是detailsview,都会有点太规则了,简单的说就是它们都有着四四方方的格子一样的外观。很多情况下这样的格子一样的外观是很不错的,不过有的时候我们却需要使用一个不规则的显示外观。当需要显示一个单独的记录时,使用formview控件就可以实现这种比较随意的外观呈现。
跟detailsview不同,formview并不是由那些杂七杂八的列所组成的。你不能给一个formview添加boundfield或是templatefield,不过formview是使用模板来呈现的。我们可以这样来理解formview,把它当作只含有一个templatefield的detailsview控件。formview支持以下这些模板:
· itemtemplate – 用于在formview种呈现一个特殊的记录
· headertemplate – 用于指定一个可选的页眉行
· footertemplate –用于指定一个可选的页脚行
· emptydatatemplate – 当formview的datasource缺少记录的时候,emptydatatemplate将会代替
itemtemplate来生成控件的标记语言
· pagertemplate – 如果formview启用了分页的话,这个模板可以用于自定义分页的界面
· edititemtemplate / insertitemtemplate – 如果formview支持编辑或插入功能,那么这两种模板可以用于自定义相关的界面
在本节教程中,我们将解释如何使用formview控件来为产品呈现一个不规则的外观。formview的itemtemplate将会使用一个页眉元素和<table>的结合体来显示名称、分类、供应商等等的值,而不是使用各种各样的列(如图一所示)。
图一:formview打破了detailsview的那种格子一样外观
第一步:将数据绑定到formview
打开formview.aspx页面,并从工具箱中拖一个formview到设计器中。formview刚刚添加到页面上时,它就是一个灰色的方块,这就告诉我们它需要一个itemtemplate。
图二:formview在添加一个itemtemplate之前是不会在设计器中呈现出来的
可以手工编写代码(在源视图中)来添加itemtemplate,也可以通过在设计器中将formview绑定到一个数据源控件上来实现自动添加。这个自动生成的itemtemplate包含了用于显示各字段的名称的html代码,还有用于显示各字段的值的label控件,当然了,这些label控件的text属性都已经绑定到了各相应的字段上。这个操作也同时生成了insertitemtemplate和edititemtemplate,它们为数据源控件的每一个字段都呈现了一个输入控件。
如果你想要自动生成模板,首先应该使用productsbll类的getproducts()方法来给formview添加一个objectdatasource控件,通过formview的智能标签你就可以做到上面的这个操作。这样就可以创建一个带有itemtemplate、insertitemtemplate和edititemtemplate的formview了。在源视图中,删除insertitemtemplate和edititemtemplate,因为我们现在对创建一个可编辑和可插入的formview并不感兴趣。然后,清空itemtemplate中的标记语言代码,这样我才可以工作于一个干净的环境上。
如果你喜欢手工建立itemtemplate,你可以从工具箱中拖一个objectdatasource到设计器中并配置它,这里可不要在设计器中为formview添加数据源。我们应该到源视图中手工的将forview的datasourceid属性设置为objectdatasource的id,然后再手工添加itemtemplate。不管你决定使用哪种方式,反正最后你的formview的声明标记代码应该像下面这个样子:
<asp:formview id="formview1" runat="server" datasourceid="objectdatasource1"> <itemtemplate> </itemtemplate> </asp:formview>
花点儿时间到formview的智能标签中勾上“启用分页(enable paging)”复选框,这样可以在formview的声明标记代码中加上allowpaging="true"这么一个属性(attribute)。另外,把enableviewstate属性设置为false。
第二步:定义itemtemplate的标记代码(markup)
在将formview绑定到objectdatasource控件并且将其配置为支持分页之后,我们就准备指定itemtemplate的内容了。在本教程中,让我们将产品名称显示在一个<h3>中。跟着让我们使用<table>将余下的产品属性显示在一个四列的表中,其中第一列和第三列用于显示产品属性的名称,第二列和第四列用于显示产品属性的值。
在设计器中通过formview的模板编辑界面或是在源视图中手工输入代码都可以添加上面所说的这些标记代码。使用模板的时候,我发现直接在源视图中编代码会来得比较快,不过你可以使用任何一种让你觉得够爽的方式。下面的声明标记代码展示了formview在完成了itemtemplate的结构之后所应该有的样子:
<asp:formview id="formview1" runat="server" datasourceid="objectdatasource1" allowpaging="true" enableviewstate="false"> <itemtemplate> <hr /> <h3><%# eval("productname") %></h3> <table border="0"> <tr> <td class="productpropertylabel">category:</td> <td class="productpropertyvalue"> <%# eval("categoryname") %></td> <td class="productpropertylabel">supplier:</td> <td class="productpropertyvalue"> <%# eval("suppliername")%></td> </tr> <tr> <td class="productpropertylabel">price:</td> <td class="productpropertyvalue"><%# eval("unitprice", "{0:c}") %></td> <td class="productpropertylabel">units in stock:</td> <td class="productpropertyvalue"> <%# eval("unitsinstock")%></td> </tr> <tr> <td class="productpropertylabel">units on order:</td> <td class="productpropertyvalue"> <%# eval("unitsonorder") %></td> <td class="productpropertylabel">reorder level:</td> <td class="productpropertyvalue"> <%# eval("reorderlevel")%></td> </tr> <tr> <td class="productpropertylabel">qty/unit</td> <td class="productpropertyvalue"> <%# eval("quantityperunit") %></td> <td class="productpropertylabel">discontinued:</td> <td class="productpropertyvalue"> <asp:checkbox runat="server" enabled="false" checked='<%# eval("discontinued") %>' /> </td> </tr> </table> <hr /> </itemtemplate> </asp:formview>
注意这个数据绑定语法——以<%# eval("productname") %>为例——可以直接插入到模板的输出中。那是因为它没有必要绑定到一个label控件的text属性上。举个例子,比如我们要将productname的值使用<h3><%# eval("productname") %></h3>来显示在一个<h3>元素中,那么产品“chai”将被输出为<h3>chai</h3>。
css类productpropertylabel和productpropertyvalue用于指定<table>中的产品属性的名称和值的样式。这些css类定义在styles.css中,它们使产品属性的名称粗体显示并且右对齐,它们还给产品属性的值加上一个右填充。
由于formview没有checkboxfield,要将discontinued的值显示为一个checkbox的话,我们就必须自己添加一个checkbox控件。将这个checkbox控件的enabled属性设置为false以使其只读,并将其checked属性绑定到discontinued字段上去。
完成了itemtemplate之后,产品信息就以一种更加不规则的方式来显示了。来比较一下上一节中的detailsview的输出(图三)和本节所讨论的formview的输出(图四)。
图三:生硬的detailsview输出
图四:柔和的formview输出
总结
虽然gridview和detailsview控件可以使用templatefield来自定义它们的输出,不过它们都呈现为一种格子一样的四四方方的样子。在那些需要使用一种不规则的外观来显示一个单独的记录的时候,formview就是一个理想的选择。跟detailsview一样,formview从它的datasource中显示一个单独的记录。不过它也有跟detailsview不同的地方,它仅由模板组成,而且它根本不支持字段(fields。译者注:比如说checkboxfield)。
就像我们在本节中看到的那样,在显示一个单独的记录的时候,formview提供了一种更加复杂的的呈现方式。在今后的教程中我们将解释一下datalist和repeater控件,它们可以提供跟formview一样复杂的呈现,不过它们可以显示多列(就像gridview那样)。
编程愉快!
关于作者
scott mitchell,著有六本asp/asp.net方面的书,是4guysfromrolla.com的创始人,自1998年以来一直应用微软web技术。scott是个独立的技术咨询顾问,培训师,作家,最近完成了将由sams出版社出版的新作,24小时内精通asp.net 2.0。他的联系电邮为,也可以通过他的博客http://scottonwriting.net与他联系。