Peter Bucher - Mein Experiment, meine Spielereien, meine Welt...   ·   Stefan Falz   ·   Jürgen Gutsch   ·   Golo Roden   ·   ASP.NET Zone   ·   Microsoft ASP.NET
Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe

SelfValidatingControl - CustomControl selber validieren lassen

Ich bin in der Newsgroup über die Frage gestolpert, wie man ein sich selbst validierendes Control, ohne ein zusätzliches Custom Validator Control dazu bringen kann, die Eigenschaft IsValid von der aktuellen Page Instanz zu beeinflussen.

Nun, wenn man ein bisschen nachforscht, findet man in der MSDN oder aber dem Reflector die abstrakte Basisklasse BaseValidator.

Folgend die Definition dieser Basisklasse:

public abstract class BaseValidator : Label, IValidator

 

Eine Klasse die von BaseValidator erbt, so wie das bei allen Validator Controls ausser der ValiationSummary der Fall ist, erben also von Label und implementieren das Interface IValidator.
Okay, für einen Validator an sich, mag es sinnvoll sein, sich wie ein Label zu verhalten, denn wir wollen schliesslich eine Fehlermeldung ausgeben.
In einem CustomControl sieht das aber wieder anders aus, vorallem dann, wenn wir die Validation selber erledigen.

Man kann / könnte die benötigten und schon im Framework vorhandenen Validatoren zu seinem CustomControl hinzufügen, und schliesslich auch veranlassen, dass diese Validatoren bei der Seitenüberprüfung berücksichtigt werden.
Jedoch geht es m.E. leichter von der Hand, wenn man sein CustomControl validationsfähig macht, und die einzelnen Prüfungen, sowie auch die Fehlerausgabe im Control selber erledigt.

Ich möchte euch anhand eines einfachen uns ziemlich sinnfreien Beispiels zeigen, wie man so etwas implementieren könnte.
Eine Klasse das als Validator fungieren möchte, muss das Interface (Schnittstelle) IValidator implementieren, als Basisklasse wählen wir in diesem Fall Control, da wir kein einzelnes Haupt Element brauchen.
Definition unseres CustomControls:

public class SelfValidatingControl : Control, IValidator

Als nächstes definieren wir die benötigten privaten Felder.
_isValid brauchen wir als Hilfsvariable im Zusammenspiel mit der Validierung.

private bool    _isValid = false;
private TextBox _txtSurname;
private TextBox _txtName;

Und jetzt geht es an die Implementation des CustomControls, hierzu erstellen wir im Konstruktor zwei TextBoxen und fügen sie zur Controls Collection hinzu.
Zwischen die TextBoxen schieben der Einfachheit halber, LiteralControls, jeweils mit "Vorname", "Name" und den dazugehörigen Breaks dazu "<br />".

public SelfValidatingControl() {
    this._txtSurname = new TextBox();
    this._txtName    = new TextBox();
   
    this.Controls.Add(new LiteralControl("Vorname:"));
    this.Controls.Add(new LiteralControl("<br />"));
    this.Controls.Add(this._txtSurname);
    this.Controls.Add(new LiteralControl("<br />"));
    this.Controls.Add(new LiteralControl("Name:"));
    this.Controls.Add(new LiteralControl("<br />"));
    this.Controls.Add(this._txtName);
}

 

Jetzt fehlen noch zwei wichtige Dinge:

  • Implementation der IValidator Schnittstelle
  • Weitergabe des Validators an die Validator Collection der aktuellen Page Instanz

Wenn wir die Schnittselle in der Klassendefinition niederschreiben, gibt uns Visual Studio die Möglichkeit, automatisch ein Grundgerüst für diese Schnittstelle zu erstellen. Nette Sache, machen wir :-)
Die Eigenschaft "ErrorMessage" müssen wir implementieren, benutzen sie in diesem Fall aber nicht, deshalb ist auch der Setter leer.
Bei der Eigenschaft "IsValid", geben wir den aktuellen Status anhand der Instanzvariable "_isValid" zurück, oder ändern diese.
In der Validate Methode, wird die Validierung ausgeführt, und die Instanzvariable "_isValid" bei Erfolg auf true, und bei Misserfolg auf false gesetzt.
Im konkreten Fall überprüfen wir nur, ob beide TextBoxen nicht leer sind, thats it.


#region IValidator Members


public string ErrorMessage
{
    get
    {
        return "Surname or Name empty";
    }
    set { ; }
}

public bool IsValid
{
    get
    {
        return this._isValid;
    }
    set
    {
        this._isValid = value;
    }
}

public void Validate()
{
    if (this._txtSurname.Text != String.Empty
       &&
       this._txtName.Text != String.Empty)
    {
        this._isValid = true;
    } else {
        this._isValid = false;
    }
}

#endregion

Und jetzt kommt der ganze Clou an der Sache.
Wenn wir auf der aktuellen Page den Status per Page.IsValid abfragen, durchläuft die aktuelle Page Instanz ihre Validator Collection.
Unser Control muss dort jetzt natürlich rein, da es, ausser einem Control, zusätzlich auch noch die Rolle eines Validators eingenommen hat.
Dies erledigen wir, indem wir die OnInit Methode des Controls überschreiben und dort auf die aktuelle Page Instanz Zugreifen.
Über die .Add Methode der Validator Collection, fügen wir über "this", die aktuelle Instanz unserer Control Klasse hinzu, also das Objekt, in dem wir uns im Moment befinden.

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    this.Page.Validators.Add(this);
}

Auf der einer beliebigen Seite müssen wir nur noch unser Control deklerativ oder per Code einfügen.
Ab diesem Moment ist die Page.IsValid Eigenschaft auch auf den Zustand dieses Controls sensibel.

Beispielprojekt:

Quellen:

Veröffentlicht Freitag, 22. Juni 2007 00:24 von Peter Bucher

Kommentare

# Alles neu oder was?

Info &amp; Statistiken Ja, es gibt Neuigkeiten auf meinem Blog, aber es ist nicht alles neu ;-) Unter

Freitag, 24. August 2007 01:45 by Peter Bucher
Anonyme Kommentare sind nicht zugelassen