C# – Custom formatting of validation errors & control tree issues – ASP.NET

asp.netcvalidationweb-controls

I have a WebControl library I'm using to render out our stylized form elements. The library also contains some overriden validators, so that when used together, I can render out some nicer validation HTML/CSS than the default validator's red-star-next-to-a-field. Namely, I'd like to highlight the entire line.

At its most basic level, the 'form line' could render out:

  • Outer <div class="hasError">
    • <asp:Label>
    • <asp:TextBox>

(From there, there's all sorts of extra whistles, AssociatedControlID…)

The issue I'm having is that when having the control create its own overriden validator (e.g. controlled with a IsRequiredField property), I'm unable to get the validator's ControlToValidate to target the control itself.

It would seem the validator's target
ControlToValidate needs to be at the same level in the control tree.
And I can't add it to the Parent's
control tree during
CreateChildControls, as it gives an error.

… So I have a class like this:

[DefaultProperty("Value"), ValidationProperty("Value")]  
public class BasicTextInputLine : WebControl, INamingContainer  
{  
  ...
  private Label _someLabel;
  private TextBox _someTextBox;
  private MyRequiredFieldValidator _someValidator;

  public string Value  
  public bool IsRequiredField  
  ...  
}  

(Note – The ValidationProperty("Value") flag allows a validator to point at it)

and

public class MyRequiredFieldValidator : RequiredFieldValidator
{
  ...
  protected override void OnPreRender(EventArgs e)
  {
    ...
    if (foundControlToValidate is BasicTextInputLine)
      (foundControlToValidate as BaseFormEntry).IsValid = false;
}

Which I can happily works in markup like so:

<custom:BasicTextInputLine ID="foo" ... />
<custom:MyRequiredFieldValidator ControlToValidate="foo" ... />

Issue:
Unfortunately, I have a catch-22 when adding things to the control tree:

Adding it to the parent (which would give a working control tree) gives an error about not being able to interfere with its control set.

protected override void CreateChildControls()
{
  ...
  Parent.Controls.Add(_someValidator);
}

And adding it to the control gives an error about the ControlToValidate not being able to be found.

protected override void CreateChildControls()
{
  ...
  Controls.Add(_someValidator);
}

How can I structure this so I can have BasicTextInputLine create its own validator, and have it validate itself, not its inner TextBox?

Much appreciated.

Best Answer

I'm not sure whether I fully understand the problem, but as I interpret your code snippets, you are mixing two concepts here:

  1. The BasicTextInputLine contains the validator directly. I derive that information in particular by the variable in the class:

    private MyRequiredFieldValidator _someValidator;

    and you trying to add it to the list of child controls.

  2. The validator is a completely separated control, which refers to the main BasicTextInputLine. I can see that in your markup:

I think these two approaches are contradictory and you have two options:

  1. Stick to approach 1. In that case, you should create the validator instance in your code, and remove the markup part.

  2. Stick to approach 2. In that case, the BasicTextInputLine class does not need to know about the validator, i.e., remove the variable inside the class and don't create it as child control. You simply do not need it.