<asp:DetailsView runat="server" AutoGenerateRows="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True" EnableViewState="False"> <Fields> <asp:BoundField DataField="ProductName" HeaderText="Product" SortExpression="ProductName" /> <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True" SortExpression="CategoryName" /> <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True" SortExpression="SupplierName" /> <asp:BoundField DataField="QuantityPerUnit" HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" /> <asp:TemplateField HeaderText="Price and Inventory"> <ItemTemplate> <asp:Label runat="server" Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:Label> <br /> <strong> (In Stock / On Order: </strong> <asp:Label runat="server" Text='<%# Eval("UnitsInStock") %>'></asp:Label> <strong>/</strong> <asp:Label runat="server" Text='<%# Eval("UnitsOnOrder") %>'> </asp:Label><strong>)</strong> </ItemTemplate> </asp:TemplateField> <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" /> </Fields> </asp:DetailsView>
做了这些修改之后,我们已经把单价和总量信息统一的显示在一个单独的DetailsView行中了。
图八:单价和总量信息显示在一个单独的行上了
第三步:自定义折扣字段的信息
Products表的Discontinued字段是一个BIT值,它指明一个产品是否打折。当把一个DetailsView(或者GridView)绑定到一个数据源控件时,布尔型的字段(比如说Discontinued)会被实现为CheckBoxField,而非布尔型的字段(比如说ProductID、ProductName等等)将被实现为BoundField。CheckBoxField被呈现为一个禁用的CheckBox,如果数据的值为true则CheckBox为选中状态,否则就是未选中状态。
比起显示一个CheckBoxField,可能我们更希望将其显示为一个文本以说明这个产品是不是有折打。要做到这一点,我们可以从DetailsView中删掉这个CheckBoxField,再添加一个BoundField,并将其DataField属性设置到Discontinued上。嗯,花点时间完成它!做完这个改变后,DetailsView对那些打折的产品就显示一个“True”,而对其他的就显示一个“False”。
图九:字符串“True”和“False”用来显示打折状态
想想一下,我们不想用“True”或者“False”,而是想要“YES”和“NO”。这样的自定义可以由一个TemplateField和一个格式化方法来实现。格式化方法可以接受若干个输入参数,但是智能返回一个用于插入到模板中的HTML(字符串类型的)
在DetailsViewTemplateField.aspx页面的后置代码类中添加一个名为DisplayDiscontinuedAsYESorNO的格式化方法,它接受一个布尔型的值作为参数并返回一个字符串。就像前一节中讨论的那样,这个方法必须标记为protected或是public,不然就不能从模板中访问到它了。
protected string DisplayDiscontinuedAsYESorNO(bool discontinued) { if (discontinued) return "YES"; else return "NO"; }
这个方法检查输入的参数(是否折扣),如果为true则返回“YES”,否则就返回“NO”。
注意:回忆一下我们在上一节中的相关内容,传递给格式化方法的参数可能是空值,所以我们需要在访问雇员的HiredDate之前对它进行空值检查。这样的检查在这里却是不需要的,因为Discontinued字段永远不会是空值。此外,这也是为什么这个方法接受的是一个布尔值而不是ProductsRow实例或object类型的参数的原因。
完成了这个格式化方法之后,剩下的就只是在TemplateField的ItemTemplate中调用它了。要创建这个TemplateField,我们可以删除Discontinued绑定列再添加一个新的TemplateField,也可以直接将Discontinued BoundField转换成TemplateField。然后,在源视图(译者注:就是HTML视图)编辑TemplateField以使其包含一个调用DisplayDiscontinuedAsYESorNO方法的ItemTemplate,传过去的参数就是当前ProductRow实例的Discontinued属性。这个可以通过Eval方法来访问。现在,这个TemplateField的标记代码就像这样了: