我有一个自定义复合控件,其中包含一个文本框,一些验证器以及几个UI组件。我无法让客户端验证工作。回发后服务器端验证工作正常。我最终计划通过挂钩验证API在验证失败时向TextBox添加自定义CSS,但我甚至无法运行客户端验证。
由于此控件是通用的,因此验证器不是从复合控件本身生成的,而是从外部传递,如下所示。
<mycontrol:HighlightedTextbox ID="HighlightedTextbox1" runat="server" Label="test" CssClass="generalText" FocusedCssClass="highlightText" ErrorCssClass="errorText">
<validators>
<asp:RequiredFieldValidator ID="required1" runat="server" ErrorMessage="Field is required" EnableClientScript="true" />
</validators>
<prompttemplate><span>this is a prompt</span></prompttemplate>
</mycontrol:HighlightedTextbox>
我指定了persistchildren属性(我相信),以便验证器实际上已添加到Validators属性中。这似乎也很好。
[PersistChildren(true, true), ParseChildren(true), PersistenceMode(PersistenceMode.InnerProperty)]
public abstract class BaseHighlightedControl<TControl> : CompositeControl
where TControl : Control
我有一个派生控件,它将标准TextBox指定为TControl以及公开文本属性,但实际上所有派生类型都是如此。复合控件依赖于CreateChildControls方法来构建控件并配置验证器。这似乎在生命周期中应该是合适的,因为我已经看到了在CreateChildControls方法中创建验证器的复合控件的示例。
public List<BaseValidators> Validators { get; private set; }
/// <summary>
/// Create the child controls
/// </summary>
protected override void CreateChildControls()
{
base.CreateChildControls();
this.MainControl.ID = "HighlightControl";
this.PromptTemplate.InstantiateIn(this.Prompt);
this.Prompt.Style.Add(HtmlTextWriterStyle.Display, "inline");
this.FieldLabel.Text = this.Label;
if (!this.DesignMode)
{
this.Controls.Add(this.FieldLabel);
this.Controls.Add(this.MainControl);
this.Controls.Add(this.Prompt);
AddValidators();
}
}
private void AddValidators()
{
foreach (var validator in this.Validators.OfType<BaseValidator>())
{
validator.ControlToValidate = this.MainControl.ID;
validator.ValidationGroup = this.ValidationGroup;
validator.Display = ValidatorDisplay.Dynamic;
this.Controls.Add(validator);
}
}
同样,服务器端验证发生得很好。 javascript中的Page_Validators集合不包含我的验证器。我添加到我的控件之外的标记的任何验证器都会出现在javascript集合中,并且运行正常。
我做错了什么?
答案 0 :(得分:0)
问题是由于我尝试在asp.net标记内创建验证器控件然后将它们传递到复合控件中引起的。由于某种原因,我不太明白,验证器控件的生命周期似乎有点混乱,即使它们从未实际添加到控制树,直到复合控件将它们放在那里。目的是它们将在标记中创建,并由复合控件进行配置和加载。我只是使用模板系统而不是控件集合属性。它不是我想要的,因为可以添加其他控件,但它完美无缺,因为控件现在在CreateChildControls方法中实例化。它现在看起来像这样。
public ITemplate Validators { get; set; }
而不是
public List<BaseValidators> Validators { get; private set; }
CreateChildControls方法现在执行标准模板实例化
this.ValidatorsTemplate.InstantiateIn(this.ValidatorContainer);
然后我递归地遍历ValidatorContainer控件(小心避免无限递归),通过设置ControlToValidate和其他一些内容来查找我配置的验证器。