2

我向您展示一个小谜团......以下控件旨在每次验证失败,无论如何,但它不会:

public class Test : CompositeControl
{
    protected override void CreateChildControls()
    {
        Controls.Clear();
        CreateControlHierachy();
        ClearChildViewState();
    }

    void CreateControlHierachy()
    {
        var validator = new CustomValidator
        {
            ErrorMessage = "Can't do that!"
        };

        validator.ServerValidate += (sender, e) =>
        {
            e.IsValid = false;
        };

        Controls.Add(validator);
    }
}

要“修复”该问题,请将以下行添加到 CreateControlHierachy 并且所有工作都按预期进行:

Controls.Add(new TextBox());

该控件在 web.config 中注册并放置在一个简单的页面上,如下所示:

<uc:Test runat="server" />

在回发事件上使用调试器会显示以下内容:

  • 正如预期的那样,验证器位于页面上的控件层次结构中。
  • 验证器未在 Page.Validators 中注册。
  • Page.IsValid 和 validator.IsValid 仍然为真。

TextBox 对验证器有什么影响,解决此问题的正确方法是什么?

4

1 回答 1

1

我找到了一个可能的解释。TextBox 的存在向您的控件添加了一个子控件,即 IPostbackDataHandler。为了加载发布数据,页面必须首先通过调用 FindControl 找到控件。当 FindControl 做它的事情时,它最终会访问你的控件的 Controls 集合。因为您的控件是 CompositeControl,所以它调用 EnsureChildControls,后者调用 CreateChildControls。

所有这些都发生在验证之前。取出 TextBox 并且在验证之前不再访问 Controls 集合,因此直到验证之后才创建验证器(很可能在预渲染期间)

由于您的验证器在验证阶段不存在,因此不会被调用。我建议在验证发生之前添加对 EnsureChildControls 的调用。

    protected override void OnLoad(EventArgs e)
    {
        EnsureChildControls();
        base.OnLoad(e);
    }
于 2009-07-31T03:54:46.500 回答