向 DataList 的编辑界面添加验证控件 (C#)

作者 :斯科特·米切尔

下载 PDF

在本教程中,我们将了解将验证控件添加到 DataList 的 EditItemTemplate 是多么容易,以便提供一个更防空的编辑用户界面。

介绍

到目前为止,在 DataList 编辑教程中,DataLists 编辑界面不包含任何主动用户输入验证,即使用户输入无效(如缺少产品名称或负价格)也会导致异常。 在 前面的教程中 ,我们研究了如何将异常处理代码添加到 DataList 事件处理程序 UpdateCommand ,以便捕获和正常显示有关引发的任何异常的信息。 但是,理想情况下,编辑界面将包含验证控件,以防止用户首先输入此类无效数据。

在本教程中,我们将了解如何轻松地将验证控件添加到 DataList s EditItemTemplate ,以便提供一个更易懂的编辑用户界面。 具体而言,本教程采用在前面的教程中创建的示例,并扩充编辑界面以包含适当的验证。

步骤 1:从处理 BLL 和 DAL 级异常复制示例

处理 BLL 和 DAL 级异常 教程中,我们创建了一个页面,其中列出了两列可编辑 DataList 中产品的名称和价格。 本教程的目标是扩充 DataList 的编辑界面,以包含验证控件。 具体而言,验证逻辑将:

  • 要求提供产品名称
  • 确保为价格输入的值是有效的货币格式
  • 确保为价格输入的值大于或等于零,因为负 UnitPrice 值是非法的

在查看扩充前一个示例以包含验证之前,首先需要将示例从ErrorHandling.aspx文件夹中的页面EditDeleteDataList复制到本教程的页面。 UIValidation.aspx 为此,我们需要复制 ErrorHandling.aspx 页面的声明性标记及其源代码。 首先通过执行以下步骤来复制声明性标记:

  1. ErrorHandling.aspx在 Visual Studio 中打开页面
  2. 转到页面的声明性标记(单击页面底部的“源”按钮)
  3. 复制文本 <asp:Content></asp:Content> 标记(第 3 至 32 行),如图 1 所示。

复制 asp:Content> 控件中的<文本

图 1:复制控件中的 <asp:Content> 文本(单击以查看全尺寸图像

  1. UIValidation.aspx打开页面
  2. 转到页面声明性标记
  3. 将文本粘贴到控件中 <asp:Content>

若要复制源代码,请打开ErrorHandling.aspx.vb页面并仅复制类中的EditDeleteDataList_ErrorHandling文本。 复制三个事件处理程序(和)和该方法,但不复制类声明或using语句。DisplayExceptionDetails Products_UpdateCommandProducts_CancelCommandProducts_EditCommand 将复制的文本粘贴到EditDeleteDataList_UIValidation类中UIValidation.aspx.vb

在将内容和代码移 ErrorHandling.aspxUIValidation.aspx以后,花点时间在浏览器中测试页面。 在这两个页面中,应看到相同的输出并体验相同的功能(请参阅图 2)。

UIValidation.aspx页面模拟ErrorHandling.aspx中的功能

图 2:页面模拟功能(ErrorHandling.aspx单击以查看全尺寸图像UIValidation.aspx

步骤 2:将验证控件添加到 DataList s EditItemTemplate

构造数据输入表单时,用户必须输入任何必填字段,并且提供的所有输入都是合法且格式正确的值。 为了帮助确保用户的输入有效,ASP.NET 提供了五个内置验证控件,这些控件旨在验证单个输入 Web 控件的值:

有关这五个控件的详细信息,请参阅“将验证控件添加到编辑和插入接口”教程,或查看 ASP.NET 快速入门教程“验证控件”部分。

在本教程中,我们需要使用 RequiredFieldValidator 来确保已提供产品名称的值和 CompareValidator,以确保输入的价格的值大于或等于 0,并且以有效的货币格式显示。

注意

尽管 ASP.NET 1.x 具有相同的五个验证控件,ASP.NET 2.0 增加了许多改进,但除了 Internet Explorer 之外,主要两项是针对浏览器的客户端脚本支持,以及将页面上的验证控件分区为验证组的功能。 有关 2.0 中的新验证控件功能的详细信息,请参阅在 ASP.NET 2.0 中剖析验证控件。

首先,将必要的验证控件添加到 DataList s EditItemTemplate。 可以通过设计器执行此任务,方法是单击 DataList 智能标记中的“编辑模板”链接或通过声明性语法执行。 让我们使用“设计”视图中的“编辑模板”选项逐步完成该过程。 选择编辑 DataList s EditItemTemplate后,通过将 RequiredFieldValidator 从工具箱拖动到模板编辑界面中来添加 RequiredFieldValidator,并将其放在 TextBox 之后 ProductName

将 RequiredFieldValidator 添加到 ProductName TextBox 后面的 EditItemTemplate

图 3:向 TextBox 添加 RequiredFieldValidator EditItemTemplate After ProductName单击以查看全尺寸图像

所有验证控件都通过验证单个 ASP.NET Web 控件的输入来工作。 因此,我们需要指示刚添加的 RequiredFieldValidator 应针对 ProductName TextBox 进行验证;这是通过将验证控件的属性ControlToValidate设置为ID适当的 Web 控件(ProductName在此实例中)。 接下来,将属性设置为“必须提供产品名称”Text,并将属性设置为 *。ErrorMessage Text属性值(如果提供)是验证控件在验证失败时显示的文本。 ErrorMessage ValidationSummary 控件使用所需的属性值;如果Text省略属性值,则ErrorMessage属性值由验证控件在无效输入上显示。

设置 RequiredFieldValidator 这三个属性后,屏幕应类似于图 4。

设置 RequiredFieldValidator s ControlToValidate、ErrorMessage 和文本属性

图 4:设置 RequiredFieldValidator s ControlToValidateErrorMessageText属性(单击以查看全尺寸图像

将 RequiredFieldValidator 添加到其中 EditItemTemplate后,所有剩余项都是添加产品价格 TextBox 的必要验证。 UnitPrice由于编辑记录时是可选的,因此无需添加 RequiredFieldValidator。 但是,我们确实需要添加 CompareValidator,以确保 UnitPrice提供的格式正确设置为货币且大于或等于 0。

将 CompareValidator 添加到EditItemTemplate并设置其ControlToValidate属性,其ErrorMessage属性UnitPrice必须大于或等于零,并且不能包含货币符号,并且其Text属性为 *。 若要指示UnitPrice该值必须大于或等于 0,请将 CompareValidator s Operator 属性设置为 GreaterThanEqual0,并将其TypeValueToCompare属性设置为 Currency0。

添加这两个验证控件后,DataList 的 EditItemTemplate 声明性语法应如下所示:

<EditItemTemplate>
    Product name:
        <asp:TextBox ID="ProductName" runat="server"
            Text='<%# Eval("ProductName") %>'></asp:TextBox>
        <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
            ControlToValidate="ProductName"
            ErrorMessage="You must provide the product's name"
            runat="server">*</asp:RequiredFieldValidator>
    <br />
    Price:
        <asp:TextBox ID="UnitPrice" runat="server"
            Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:TextBox>
        <asp:CompareValidator ID="CompareValidator1"
            ControlToValidate="UnitPrice"
            ErrorMessage="The price must be greater than or equal to zero
                          and cannot include the currency symbol"
            Operator="GreaterThanEqual" Type="Currency" ValueToCompare="0"
            runat="server">*</asp:CompareValidator><br />
    <br />
    <asp:Button ID="UpdateProduct" runat="server" CommandName="Update"
        Text="Update" /> 
    <asp:Button ID="CancelUpdate" runat="server" CommandName="Cancel"
        Text="Cancel" />
</EditItemTemplate>

进行这些更改后,在浏览器中打开页面。 如果在编辑产品时尝试省略名称或输入无效的价格值,则文本框旁边会显示星号。 如图 5 所示,包含货币符号(如 $19.95)的价格值被视为无效。 CompareValidator 允许CurrencyType数字分隔符(如逗号或句点,具体取决于区域性设置)和前导加号或减号,但不允许货币符号。 此行为可能会使用户感到困惑,因为编辑界面当前呈现 UnitPrice 使用货币格式。

带有无效输入的文本框旁边显示星号

图 5:星号显示在输入无效的文本框旁边(单击以查看全尺寸图像

虽然验证按原样工作,但编辑记录时,用户必须手动删除货币符号,这是不能接受的。 此外,如果在编辑界面中没有无效的输入,则单击时,“更新”和“取消”按钮都不会调用回发。 理想情况下,无论用户输入的有效性如何,“取消”按钮都会将 DataList 返回到其预编辑状态。 此外,我们需要确保在更新 DataList UpdateCommand 事件处理程序中的产品信息之前页面数据有效,因为验证控制客户端逻辑可由浏览器不支持 JavaScript 或禁用其支持的用户绕过。

从 EditItemTemplate s UnitPrice TextBox 中删除货币符号

使用 CompareValidator s Currency``Type时,要验证的输入不得包含任何货币符号。 存在此类符号会导致 CompareValidator 将输入标记为无效。 但是,我们的编辑界面当前在 TextBox 中包含 UnitPrice 货币符号,这意味着用户在保存更改之前必须显式删除货币符号。 若要解决此问题,我们有三个选项:

  1. EditItemTemplate配置以便 UnitPrice TextBox 值的格式不是货币。
  2. 允许用户输入货币符号,方法是删除 CompareValidator 并将其替换为检查正确格式的货币值的 RegularExpressionValidator。 此处的挑战是,验证货币值的正则表达式不像 CompareValidator 那么简单,如果我们想要合并区域性设置,则需要编写代码。
  3. 完全删除验证控件,并依赖于 GridView RowUpdating 事件处理程序中的自定义服务器端验证逻辑。

让我们来看看本教程的选项 1。 目前,由于 UnitPrice TextBox 的数据绑定表达式在 : <%# Eval("UnitPrice", "{0:c}") %>EditItemTemplate,格式设置为货币值。 将 Eval 语句更改为,该语句 Eval("UnitPrice", "{0:n2}")将结果格式化为具有两位数精度的数字。 这可以通过声明性语法直接完成,也可以通过单击 DataList 中的 EditItemTemplateTextBox 中的“编辑 DataBindings”链接UnitPrice来完成。

通过此更改,编辑界面中的格式化价格包括逗号作为组分隔符和小数分隔符的句点,但会离开货币符号。

注意

从可编辑界面中删除货币格式时,我觉得将货币符号作为文本放在 TextBox 外部会很有帮助。 这向用户提示他们不需要提供货币符号。

修复“取消”按钮

默认情况下,验证 Web 控件发出 JavaScript 以在客户端执行验证。 单击 Button、LinkButton 或 ImageButton 时,页面上的验证控件在回发发生前在客户端进行检查。 如果有任何无效数据,则回发将被取消。 不过,对于某些按钮,数据的有效性可能并不重要;在这种情况下,由于数据无效而取消回发是一种滋扰。

“取消”按钮就是这样一个示例。 假设用户输入无效的数据,例如省略产品名称,然后决定她不想保存产品毕竟并点击“取消”按钮。 目前,“取消”按钮会触发页面上的验证控件,该控件报告缺少产品名称并阻止回发。 用户必须将某些文本 ProductName 键入到 TextBox 中,才能取消编辑过程。

幸运的是,Button、LinkButton 和 ImageButton 具有一个 CausesValidation 属性,该属性 可以指示是否单击该按钮应启动验证逻辑(默认值为 True)。 将“取消按钮”属性 CausesValidation 设置为 False

确保在 UpdateCommand 事件处理程序中输入有效

由于验证控件发出的客户端脚本,如果用户输入无效输入,验证控件将取消按钮、LinkButton 或 ImageButton 控件 CausesValidation True 启动的任何回发(默认值)。 但是,如果用户正在访问过时的浏览器或其 JavaScript 支持已被禁用的浏览器,客户端验证检查将不会执行。

所有 ASP.NET 验证控件在回发时立即重复其验证逻辑,并通过 Page.IsValid 属性报告页面输入的总体有效性。 但是,页面流不会根据值 Page.IsValid以任何方式中断或停止。 作为开发人员,我们有责任确保在继续执行假定有效输入数据的代码之前,该 Page.IsValid 属性具有值 True

如果用户禁用了 JavaScript,请访问我们的页面,编辑产品,输入价格值太贵,然后单击“更新”按钮,客户端验证将被绕过,回发将随之而来。 在回发时,ASP.NET 页的 UpdateCommand 事件处理程序将执行,在尝试分析过于昂贵时 Decimal引发异常。 由于我们有异常处理,因此此类异常将正常处理,但我们可以防止无效数据首先滑过,只需继续UpdateCommand处理事件处理程序(如果Page.IsValid值为)。True

将以下代码添加到事件处理程序的 UpdateCommand 开头,紧邻块之前 Try

if (!Page.IsValid)
    return;

添加后,仅当提交的数据有效时,产品才会尝试更新。 由于验证控制客户端脚本,大多数用户将无法回发无效数据,但浏览器不支持 JavaScript 或禁用 JavaScript 的用户可以绕过客户端检查并提交无效数据。

注意

精明的读取器会回忆一下,使用 GridView 更新数据时,我们不需要显式检查 Page.IsValid 页面代码隐藏类中的属性。 这是因为 GridView 会查阅 Page.IsValid 我们的属性,并且仅在更新返回值 True时才继续更新。

步骤 3:汇总数据输入问题

除了五个验证控件,ASP.NET 还包括 ValidationSummary 控件,该控件显示 ErrorMessage 检测到无效数据的验证控件。 此摘要数据可以显示为网页中的文本或通过模式客户端消息框显示。 让我们来增强本教程,以包含汇总任何验证问题的客户端消息框。

为此,请将 ValidationSummary 控件从工具箱拖到设计器上。 ValidationSummary 控件的位置并不重要,因为我们打算将其配置为仅将摘要显示为消息框。 添加控件后,将其ShowSummary属性False设置为及其ShowMessageBox属性。True 此外,客户端消息框中汇总了任何验证错误(请参阅图 6)。

验证错误汇总在客户端消息框中

图 6:客户端消息框中汇总了验证错误(单击以查看全尺寸图像

总结

在本教程中,我们了解了如何使用验证控件主动确保用户输入在尝试在更新工作流中使用它们之前有效,从而降低异常的可能性。 ASP.NET 提供五个验证 Web 控件,这些控件旨在检查特定 Web 控件的输入并报告输入的有效性。 在本教程中,我们使用这五个控件中的两个控制 RequiredFieldValidator 和 CompareValidator 来确保提供产品名称,并且价格的货币格式的值大于或等于零。

将验证控件添加到 DataList 的编辑界面非常简单,只需将它们拖到 EditItemTemplate 工具箱中并设置少量属性即可。 默认情况下,验证控件会自动发出客户端验证脚本;他们还在回发时提供服务器端验证,并将累积结果存储在属性中 Page.IsValid 。 若要在单击 Button、LinkButton 或 ImageButton 时绕过客户端验证,请将按钮的属性 CausesValidation 设置为 False。 此外,在对回发提交的数据执行任何任务之前,请确保 Page.IsValid 属性返回 True

到目前为止,我们检查的所有 DataList 编辑教程都有非常简单的用于产品名称的 TextBox 和价格的文本框。 但是,编辑界面可以包含不同 Web 控件的组合,例如 DropDownLists、Calendars、RadioButtons、CheckBoxes 等。 在下一教程中,我们将介绍如何生成使用各种 Web 控件的接口。

快乐编程!

关于作者

斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0。 他可以通过他的博客联系到mitchell@4GuysFromRolla.com他,可以在该博客中找到http://ScottOnWriting.NET

特别感谢

本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是丹尼斯·帕特森、肯·佩斯皮萨和莉兹·舒洛克。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请把我扔一条线。mitchell@4GuysFromRolla.com