2008-11-19 8 views
0

J'ai une classe qui ressemble à ceci:sur mesure TextBox avec validateur intégré: validation côté serveur ne tirant

public class TextField : TextBox 
{ 
    public bool Required { get; set; } 
    RequiredFieldValidator _validator; 

    protected override void CreateChildControls() 
    { 
     base.CreateChildControls(); 


     _validator = new RequiredFieldValidator(); 
     _validator.ControlToValidate = this.ID; 
     if(Required) 
      Controls.Add(_validator); 
    } 

    public override void Render(HtmlTextWriter tw) 
    { 
     base.Render(tw); 

     if(Required) 
     _validator.RenderControl(tw); 
    } 
} 

Cela a travaillé pendant un certain temps dans une application interne où le javascript est toujours activé. J'ai récemment remarqué qu'une erreur javascript en amont peut empêcher les validateurs de se déclencher, donc la validation côté serveur devrait démarrer ... non? droite?

Ainsi, la propriété Page.IsValid renvoie toujours la valeur true (j'ai même essayé d'appeler explicitement Page.Validate() before-hand). Après quelques recherches, j'ai trouvé que la méthode init de validator devrait ajouter le validateur à la page, mais en raison de la façon dont je le construis, je ne pense pas que cela arrive jamais. Ainsi, la validation côté client fonctionne, mais pas la validation côté serveur.

J'ai essayé ceci:

protected override OnInit() 
{ 
    base.OnInit(); 

    Page.Validators.Add(_validator); // <-- validator is null here 
} 

Mais bien sûr, le validateur est nul ici (et parfois il n'est pas nécessaire donc il ne doit pas être ajouté) ... mais OnInit() est très tôt pour moi de prendre ces décisions (la propriété Required n'aura pas été chargée à partir de ViewState par exemple).

Des idées?

Répondre

1

Le CreateChildControls est essentiellement pour les contrôles qui ont des enfants. RequiredFieldValidator est comme un frère de TextBox.

Voici le code qui fonctionne pour moi:

public class RequiredTextBox : TextBox 
    { 
     private RequiredFieldValidator _req; 
     private string _errorMessage; 

     public string ErrorMessage 
     { 
      get { return _errorMessage; } 
      set { _errorMessage = value; } 
     } 

     protected override void OnInit(EventArgs e) 
     { 
      _req = new RequiredFieldValidator(); 
      _req.ControlToValidate = this.ID; 
      _req.ErrorMessage = _errorMessage; 
      Controls.Add(_req); 
      base.OnInit(e); 
     }  

     protected override void Render(System.Web.UI.HtmlTextWriter writer) 
     { 
      base.Render(writer); 
      _req.RenderControl(writer); 
     } 
    } 

Et voilà la page ASP.NET derrière:

protected void SubmitClick(object sender, EventArgs e) 
     { 
      if(Page.IsValid) 
      { 
       // do something 
      } 
     } 

Et voici le code ASPX:

<MyControl:RequiredTextBox runat="server" ErrorMessage="Name is required!" ID="txtName"></MyControl:RequiredTextBox> 

    <asp:Button ID="Btn_Submit" runat="server" Text="Submit" OnClick="SubmitClick" /> 
+0

En fait, ce qui a fonctionné moi en utilisant votre exemple comme un guide est d'appeler simplement EnsureChildControls() avant l'appel de base.OnInit (e). Merci! –

0

Les validateurs doivent hériter de BaseValidator.

+0

Je n'écris pas mon propre validateur, j'utilise le RequiredFieldValidator. –

+0

TextBox n'est pas un contrôle Composite et votre contrôle n'hérite pas de BaseValidator, donc le framework ne trouvera jamais votre validateur. Vous pouvez réécrire votre contrôle en tant que CompositeControl ou en tant que BaseValidator. Votre implémentation ne fonctionnera jamais. –

+0

Si le contrôle est ajouté à la collection de contrôles, le cycle de vie sera exécuté et le validateur devrait s'ajouter à la collection page.validators sur init. –

Questions connexes