六、对验证控件进行分组
页面上有两套逻辑上独立的验证控件集合: GridView的编辑界面和DetailsView新增界面上相应的两组。默认情况下,当postback发生时页面上所有的验证都会生效。显然,当编辑记录时我们不希望DetailsView新增功能的验证起作用,图13说明了这种尴尬局面-当用户在编辑product时输入了有些有效数据,在点击更新时却由于新增功能中的name和price空白而产生验证错误。 
图13:更新Product引发新增功能的验证控件 (点击放大)
ASP.NET 2.0中的验证控件可以进行分组,这一功能是通过ValidationGroup属性。为了将这些验证控件关联到一个组,只需把ValidationGroup属性指定成同一个值。本教程中,将GridView模板中的ValidationGroup属性统一设置为EditValidationControls,而DetailsView模板中的 ValidationGroup属性则为InsertValidationControls。上述操作可以直接在代码编辑窗口完成或者通过设计器模板编辑界面的属性窗口修改。
ASP.NET 2.0中除了验证控件,按钮和按钮相关控件也增加了ValidationGroup属性。验证组中的验证控件只在有相同ValidationGroup属性的按钮产生 postback时才会进行有效性检测,例如,为使DetailsView的新增按钮可以触发InsertValidationControls验证组,我们给CommandField的 ValidationGroup属性指定为InsertValidationControls(图14),而GridView中CommandField的ValidationGroup属性则指定为 EditValidationControls。
图14:设置DetailsView中CommandField的 ValidationGroup属性为InsertValidationControls
上述操作后,DetailsView和GridView的模板TemplateFields 和 CommandFields大致如下:
DetailsView中的TemplateField模板和CommandField模板:
<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName"> <InsertItemTemplate> <asp:TextBox ID="InsertProductName" runat="server" Text='<%# Bind("ProductName") %>'>
</asp:TextBox> <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
ControlToValidate="InsertProductName" ErrorMessage="You must provide the product's name" ValidationGroup="InsertValidationControls">*</asp:RequiredFieldValidator> </InsertItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="UnitPrice" SortExpression="UnitPrice"> <InsertItemTemplate> <asp:TextBox ID="InsertUnitPrice" runat="server" Text='<%# Bind("UnitPrice") %>' Columns="6"></asp:TextBox> <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server"
ControlToValidate="InsertUnitPrice" ErrorMessage="You must provide the product's price" ValidationGroup="InsertValidationControls">*</asp:RequiredFieldValidator> <asp:CompareValidator ID="CompareValidator2" runat="server"
ControlToValidate="InsertUnitPrice" ErrorMessage="The price must be greater than or equal to zero and cannot include
the currency symbol" Operator="GreaterThanEqual" Type="Currency" ValueToCompare="0" ValidationGroup="InsertValidationControls">*
</asp:CompareValidator> </InsertItemTemplate> </asp:TemplateField> <asp:CommandField ShowInsertButton="True" ValidationGroup="InsertValidationControls" />
GridView中的CommandField模板和TemplateFields模板:
<asp:CommandField ShowEditButton="True" ValidationGroup="EditValidationControls" /> <asp:TemplateField HeaderText="ProductName" SortExpression="ProductName"> <EditItemTemplate> <asp:TextBox ID="EditProductName" runat="server" Text='<%# Bind("ProductName") %>'>
</asp:TextBox> <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
ControlToValidate="EditProductName" ErrorMessage="You must provide the product's name" ValidationGroup="EditValidationControls">*</asp:RequiredFieldValidator> </EditItemTemplate> <ItemTemplate> <asp:Label ID="Label1" runat="server" Text='<%# Bind("ProductName") %>'>
</asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="UnitPrice" SortExpression="UnitPrice"> <EditItemTemplate> <asp:TextBox ID="EditUnitPrice" runat="server" Text='<%# Bind("UnitPrice", "{0:n2}")
%>' Columns="6"></asp:TextBox> <asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="EditUnitPrice" ErrorMessage="The price must be greater than or equal to zero and cannot
include the currency symbol" Operator="GreaterThanEqual" Type="Currency" ValueToCompare="0" ValidationGroup="EditValidationControls">*</asp:CompareValidator> </EditItemTemplate> <ItemTemplate> <asp:Label ID="Label2" runat="server" Text='<%# Bind("UnitPrice", "{0:c}") %>'>
</asp:Label> </ItemTemplate> </asp:TemplateField>
当GridView的更新按钮点击时,编辑中特定的验证控件将会开始检测,而当DetailsView中的新增按钮被点击时,新增功能的
相关验证生效,图13的高亮部分显示了此举解决的问题。但是这些改动之后,输入无效数据时ValidationSummary验证总结却不再显示了。这是由于 ValidationSummary控件也拥有ValidationGroup属性并且只显示来自于同一验证组中验证控件的信息。因此,我们需要使用两个验证控件,分别作为InsertValidationControls验证组和EditValidationControls验证组:
<asp:ValidationSummary ID="ValidationSummary1" runat="server" ShowMessageBox="True" ShowSummary="False" ValidationGroup="EditValidationControls" /> <asp:ValidationSummary ID="ValidationSummary2" runat="server" ShowMessageBox="True" ShowSummary="False" ValidationGroup="InsertValidationControls" />
写到这里,本节教程就可以画上句号了。
小结
虽然绑定列BoundField可以提供了新增/编辑界面,却不能对其进行定制。很多情况,我们要给新增/编辑增加验证功能以确保用户输入合法有效的数据。为此,我们将BoundFields转换成了TemplateField,并在相应模板中增加了验证控件。本节教程扩展了《Examining the Events Associated with Inserting, Updating, and Deleting》中的代码,为DetailsView的新增和GridView的编辑界面增加了验证功能。此外,还演示了如何使用ValidationSummary控件显示验证总结以及如何对验证控件进行分组。
正如本文所见,模板列允许为新增/编辑界面增加验证控件,当然也可以扩展其他的Web控件。在下节教程中,将会演示如何用可数据绑定的DropDownList控件替换原有的TextBox,仅仅通过一个外键(如Products表中的CategoryID或SupplierID)。
祝编程快乐!
作者简介
Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用微软Web技术。Scott是个独立的技术咨询顾问,培训师,作家,最近完成了将由Sams出版社出版的新作, 《24小时内精通ASP.NET 2.0》(英文) 。 他的联系电邮为mitchell@4guysfromrolla.com,也可以通过他的博客http://ScottOnWriting.NET与他联系。
特别感谢
本系列教程采纳了很多宝贵意见,本文的主要意见来自Liz Shulok 和 Zack Jones。对我即将在MSDN发布的最新文章有兴趣的话,可以来信mitchell@4GuysFromRolla.com。