Mit validál a validator?

"Hát a Text property-t, nem?" Na ennyire nem egyszerű a helyzet, de kezdjük inkább az elején. Ha írunk egy saját kontrollt, majd feldobunk belőle egy példányt az egyik WebFormunkra, majd mellérakunk például egy RequiredFieldValidatort, akkor futtatáskor először a következő hibaüzenetet fogjuk kapni:

The ControlToValidate property of 'rfvPhone' cannot be blank.

Nincs semmi meglepetés, mindenki tudja, hogy a ControlToValidate tulajdonságot be kell állítani, mégis mindenki elfelejti az első fordítás előtt ;-) Amikor azonban megpróbáljuk beállítani ennek a tulajdonságnak az értékét, csalódottan fogjuk tapasztalni, hogy a Studioban a Properties ablakban nem tudjuk kiválasztani a saját vezérlőnket. Ne adjuk fel, bátran írjuk be a nevét mezőbe! Következő futtatás, következő hibaüzenet:

Control 'ctrlPhone' referenced by the ControlToValidate property of 'rfvPhone' cannot be validated.

Na, itt már valami gond van, nem lehet validálni a kontrollunkat. Idézzük fel, mit tanultunk a validátorokról: ha sajátot akarunk írni, akkor a BaseValidatorból kell származtatni kell és felül kell definiálni az EvaluateIsValid metódust. Nézzük mit találunk ebben, ha a RequiredFieldValidator az alany:

    protected override bool EvaluateIsValid()
    {
        string controlValidationValue = base.GetControlValidationValue( base.ControlToValidate );
        return ( ( controlValidationValue == null ) || 
!controlValidationValue.Trim().Equals( this.InitialValue.Trim() ) ); }

Az a bizonyos kutya tehát a BaseValidator osztály GetControlValidationValue metódusában van elásva, hantoljuk ki:

    protected string GetControlValidationValue( string name )
    {
        Control component = this.NamingContainer.FindControl( name );
        if( component == null )
        {
            return null;
        }
        PropertyDescriptor validationProperty = GetValidationProperty( component );
        if( validationProperty == null )
        {
            return null;
        }
        object obj2 = validationProperty.GetValue( component );
        if( obj2 is ListItem )
        {
            return ( (ListItem) obj2 ).Value;
        }
        if( obj2 != null )
        {
            return obj2.ToString();
        }
        return string.Empty;
    }

Tehát valahogy megszerezzük a tulajdonságot és elkérjük az értékét. Ha az érték típusa ListItem, akkor annak a Value tulajdonsága a fontos, egyébként egyszerűen megToStringezzük. Ebből tehát az következik, hogy bármilyen típusú tulajdonságot lehet validálni, hiszen ToString metódusa mindennek van.

Hogyan lesz meg a validálandó tulajdonság? A legelső sorban megkeressük magát a kontrollt. Itt érdemes megfigyelni, hogy csak az aktuális naming containeren belül keresünk, ezért kell a validátort a kontroll "közelébe" tenni. A keresett tulajdonságot a BaseValidator GetValidationProperty metódusa adja vissza, mégpedig így:

    public static PropertyDescriptor GetValidationProperty( object component )
    {
        ValidationPropertyAttribute attribute = 
(ValidationPropertyAttribute) TypeDescriptor.GetAttributes( component )[
typeof( ValidationPropertyAttribute ) ];
if( ( attribute != null ) && ( attribute.Name != null ) ) { return TypeDescriptor.GetProperties( component, (Attribute[]) null )[ attribute.Name ]; } return null; }

Keressük tehát azt a tulajdonságot, amelyet az osztályhoz rendelt ValidationPropertyAttribute Name tulajdonsága meghatároz. Magyarul nem csak a Text property-t lehet validálni, hanem bármit, csak mondjuk meg szegény validátornak, mégpedig a kontrollunkhoz rendelt attribútummal:

    [ValidationProperty( "LocalNumber" )]
    public partial class PhoneControl : System.Web.UI.UserControl
    {...}

Ha ezt megtesszük, eltűnik a hibaüzenet, a kontrollunkhoz már nyugodt szívvel tehetünk validátorokat. Ennek az attribútumnak egyébként a következő a szintaxisa az MSDN-ben:

    [AttributeUsageAttribute( AttributeTargets.Class )] 
    public sealed class ValidationPropertyAttribute : Attribute

Mivel az attribútumot osztályhoz rendeljünk és nem lehet több példányban felhasználni, csak egy tulajdonságot validálhatunk. Ha mégis megpróbáljuk többszörösen használni, fordítási hibát kapunk:

error CS0579: Duplicate 'ValidationProperty' attribute

Ezek után joggal merül fel a kérdés, vajon a Properties ablak is ez alapján dolgozik? Reflectorral megnézve a BaseValidator ControlToValidate tulajdonságát azt vehetjük észre, hogy egy ValidatedControlConverternevű TypeConverter van hozzárendelve, aminek a FilterControl metódusát a következőképpen implementálták:

    protected override bool FilterControl( Control control )
    {
        ValidationPropertyAttribute attribute = 
(ValidationPropertyAttribute) TypeDescriptor.GetAttributes( control )[
typeof( ValidationPropertyAttribute ) ];
if( attribute != null ) { return ( attribute.Name != null ); } return false; }

Tehát azok a kontrollok fognak kiválaszthatóként megjelenni a Properties ablakban a ControlToValidate tulajdonságnál, amelyekhez van ilyen attribútum és annak a Name tulajdonsága is meg van adva. Reflectorral keresgélve a következő típusokat és validálandó tulajdonságaikat találtam:

  • HtmlInputFile: Value
  • HtmlInputPassword: Value
  • HtmlInputText: Value
  • HtmlSelect: Value
  • HtmlTextArea: Value
  • DropDownList: SelectedItem
  • FileUpload: FileName
  • ListBox: SelectedItem
  • RadioButtonList: SelectedItem
  • TextBox: Text

Na, ezért nem tudunk validátort tenni egy CheckBoxListre, amikor rá akarjuk kényszeríteni a felhasználót, hogy legalább egy elemet válasszon ki.

Ennyi tudással felvértezve visszemehetünk a Properties ablakba és megnézhetjük, hogy már ki lehet-e választani a saját kontrollunkat a validálandó kontrollok listájából, majd joggal kérdezhetjük, hogy miért nem? Aki tudja, kérem írja meg. Köszönöm!



Balássy György (MS RD, ASP.NET MVP, MCTS)

Balássy György (MS RD, ASP.NET MVP, MCTS) Villamosmérnök, a BME Automatizálási és Alkalmazott Informatikai Tanszékén webportálok fejlesztését oktatja. 2000 óta foglalkozik a Microsoft .NET platformjával, melynek meghonosításában jelentős szerepet vállalt előadóként, konzulensként és A .NET Framework és programozása című könyv társszerzőjeként. Az MSDN Kompetencia Központon belül a Portál Technológiák Csoport vezetője, szakterülete web alapú rendszerek fejlesztése és üzemeltetése. 2004-ben Magyarországon elsőként kapta meg a Most Valuable Professional címet, majd 2005 óta a Microsoft magyarországi regionális igazgatója. Publikációi a Technet Magazinban, az MSDN Kompetencia Központ honlapján és szakmai blogjában olvashatóak.

2007.07.21. 1:04:01 | Permalink | Hozzászólások: 0 | Tárgyszavak: ,


  • Letölthető lesz a .NET Framework forráskódja

    Balássy György (MS RD, ASP.NET MVP, MCTS) Nagyon kellemes érzés tud lenni, amikor az ember mások előtt kap meg információkat, de ugyanakkor nagyon bosszantó is tud lenni, hogy az NDA miatt nem mondhatja el senkinek :( Az szintén bosszantó, ha arra kell várni, hogy valaki más hivatalosan lelője a poént, mint ahogy történt most is Scott Guthrie blogjában :( Tovább »
  • Ágykészítés 1.0

    Dávid Zoltán Újabban teljesen apatikussá váltam minden programozásjellegű tevékenységgel szemben. Ha meglátom a Visual Studiot, már indul is a kezem a jobb-felső sarok fele, úgy kell mindig visszatartanom. Ez pedig egy dolgot jelent: itt a nyár, itt a kikapcsolódás ideje. Ha szabadságra még nem is tudok elmenni, jó ilyenkor valami mást is csinálni a C# – SQL kombón kívűl. Hétvégente sokat megyünk Timivel a Mátrába, és már régóta szerettünk volna oda egy kényelmes ágyat. Innen jött az ötlet, hogy csináljunk egyet. Mi az ágykeretet készítettük, a rugozó cuccokat és a matracot vettük bele. Így sikerült. Tovább »


Írja meg Ön is véleményét!


Hozzászólásokat csak regisztrált, bejelentkezett felhasználóktól tudunk elfogadni!

Hozzászólások