【问题标题】:asp:CustomValidator / OnServerValidateasp:CustomValidator / OnServerValidate
【发布时间】:2011-01-30 20:00:57
【问题描述】:

我有一个 CheckBoxList,我正在尝试验证是否至少选中了一个复选框。

标记:

<asp:CustomValidator ID="RequiredFieldValidator8" ValidationGroup="EditArticle"
    runat="server" ErrorMessage="At least one Category is required."
    OnServerValidate="topic_ServerValidate" />
<asp:CheckBoxList id="checkboxlistCategories" runat="server"></asp:CheckBoxList>

代码隐藏:

protected void topic_ServerValidate(object source, ServerValidateEventArgs args)
{
    int i = 0;
    foreach (ListItem item in checkboxlistCategories.Items)
    {
        if (item.Selected == true)
            i = i + 1;
    }
    if (i == 0)
        args.IsValid = false;
    else
        args.IsValid = true;
}

如果我在 CustomValidator 控件中添加 ControlToValidate="checkboxlistCategories",它就会爆炸!我得到的例外是:

System.Web.HttpException:控件“checkboxlistCategories”被“RequiredFieldValidator8”的 ControlToValidate 属性引用

我错过了什么吗?

【问题讨论】:

  • 您可能想要添加一些关于它如何“爆炸”的描述。如果显示了一些错误消息,将其添加到问题中将使其他人在遇到相同问题时更有可能找到此页面。
  • 我得到的异常是: System.Web.HttpException: ControlToValidate 'RequiredFieldValidator8' 属性引用的控件'checkboxlistCategories' 无法验证。

标签: asp.net validation checkboxlist customvalidator


【解决方案1】:

这是一个更简洁的 jQuery 实现,它允许一个 ClientValidationFunction 用于页面上任意数量的 CheckBoxList 控件:

function ValidateCheckBoxList(sender, args) {
 args.IsValid = false;

 $("#" + sender.id).parent().find("table[id$="+sender.ControlId+"]").find(":checkbox").each(function () {
     if ($(this).attr("checked")) {
  args.IsValid = true;
  return;
     }
 });
}

这是标记:

<asp:CheckBoxList runat="server"
    Id="cblOptions" 
    DataTextField="Text" 
    DataValueField="Id" />

<xx:CustomValidator Display="Dynamic" 
        runat="server" 
        ID="cblOptionsValidator"
        ControlId="cblOptions"
        ClientValidationFunction="ValidateCheckBoxList" 
        ErrorMessage="One selection required." />

最后,允许客户端函数通过 ID 检索目标控件的自定义验证器:

public class CustomValidator : System.Web.UI.WebControls.CustomValidator
{
 public string ControlId { get; set; }

 protected override void OnLoad(EventArgs e)
 {
     if (Enabled)
         Page.ClientScript.RegisterExpandoAttribute(ClientID, "ControlId", ControlId);

     base.OnLoad(e);
 }
}

【讨论】:

    【解决方案2】:

    考虑到您的服务器端验证方法topic_ServerValidate 专门绑定到checkboxlistCategories 字段,您不需要设置ControlToValidate 属性。

    添加ControlToValidate 属性时它“爆炸”的原因是您引用的控件的类型-CheckBoxList。将ControlToValidate 分配给任何类型的验证器时,该验证器将在执行实际验证逻辑之前自动对引用的控件进行“非空”检查。如果该字段为空,则不会进行验证(即验证成功)。当然,除非您设置ValidateWhenEmpty = true。显然,验证器不知道如何检查 CheckBoxList 是否为空,而是抛出异常。

    在您的特定情况下,CustomValidator 实际上只是用作非空检查,即使引用的控件“空”,您也绝对希望验证器出现。正如我的回答的第一段所述,实现这一目标的最简单方法是删除有问题的 - 和不必要的 - 属性。

    【讨论】:

    • 当我尝试不使用 ControlToValidate="checkboxlistCategories" 时,OnServerValidate 方法不会触发。
    • @Neil:你确定吗?我刚刚使用包含CustomValidator(只有ServerValidate 事件处理程序集)、CheckBoxListButton 的精简表单进行了测试。单击按钮肯定会在此处触发验证事件处理程序。
    • 如果我在 if (!IsPostBack) 中将 Page.Validate() 添加到 page_load 并且每次都会触发 OnServerValidate 事件,但不会在 (IsPostBack) 或按钮单击事件中触发
    • @Neil:我不确定我是否完全关注你。为什么要显式调用Page.Validate()?单击按钮时应自动进行验证,您只需在单击事件处理程序中检查Page.IsValid
    • 我在按钮事件中调用 Page.Validate(),就在 Page.IsValid 之前,以确保执行服务器端事件。有什么想法吗?
    【解决方案3】:

    只是一个建议,但您可以改用单选按钮并定义组名。这将消除验证 b/c 的需要,组内只能选中一个单选按钮。

    【讨论】:

    • 如果选中了一个或多个复选框,问题中的代码将设置IsValid。单选按钮在任何时候都只接受一个选择。
    【解决方案4】:

    也许我错过了什么。但是CheckBoxList 控件没有ValidationPropertyAttribute。因此,您不能将其用作 ControlToValidate 属性。试试这个:

    CheckBoxList.cs

    [ValidationProperty("SelectedIndex")]
    public class CheckBoxList : System.Web.UI.WebControls.CheckBoxList
    {
    }
    

    Web.Config

    <tagMapping>
      <add tagType="System.Web.UI.WebControls.CheckBoxList, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mappedTagType="Namespace.CheckBoxList, Assembly"/>
    </tagMapping>
    

    无论如何,Scott Mitchell 写了一篇很棒的文章 here

    【讨论】:

      【解决方案5】:

      正如 Mehdi 提到的,4 Guys 在他的回答中链接到的文章中提到了这一点。

      为简洁起见,这是代码清单-

      public class CheckBoxListRequiredFieldValidator : BaseValidator
      {
          private ListControl _listctrl;
      
          public CheckBoxListRequiredFieldValidator()
          {
              base.EnableClientScript = false;
          }
      
          protected override bool ControlPropertiesValid()
          {
              Control ctrl = FindControl(ControlToValidate);
      
              if (ctrl != null)
              {
                  _listctrl = (ListControl)ctrl;
                  return (_listctrl != null);
              }
              else
                  return false;  
          }
      
          protected override bool EvaluateIsValid()
          {
              return _listctrl.SelectedIndex != -1;
          }
      }
      

      把这个獾放到你的用户控件库中,然后就可以走了。

      HTH。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-27
        相关资源
        最近更新 更多