C# - Kollekció típusú property készítése web kontrolhoz

forráskód letöltése
Készítsünk most egy olyan webes kontrolt, melynek egyik property-je kollekció típusú lesz. E kollekcióba felsorolt szövegek felhasználásával pedig egy <UL>...</UL> HTML objektumot készítünk.
Mellékelt példa megnyitása előtt szükséges egy CollectionTest nevű virtuális könyvtár létrehozása, mely a példa könyvtárára mutat. Ehhez nyissa meg a mellékelt mappa Tulajdonság ablakát és itt a Webmegosztás lapon engedélyezze a mappa megosztását olvasási és parancsfájlok futtatási jogával.
A megvalósítás három új osztály létrehozásából áll. Az egyik osztály lesz a kollekció elemeit leíró osztály, mely a példánkban a CollectionItem nevet kapja.
A második osztály a kollekciót megvalósító osztály, mely felhasználja az előzőt. Ez a CollectionItems lesz.
Végül a harmadik maga a web kontrol, melybe beépítjük új property-ként az iménti CollectionItems osztályt. Ez lesz a CollectionControl.
CollectionItem osztály
Ezt az osztályt az IParserAccessor interfészből kell származtatnunk és el kell látnunk ControlBuilderAttribute attribútummal is, annak érdekében, hogy a kollekció egyes elemei megfelelő módon tárolásra kerüljenek a web lapon és onnan vissza is lehessen olvasni azokat.
  [ControlBuilderAttribute(typeof(ControlBuilder)), TypeConverterAttribute(typeof(ExpandableObjectConverter))]
  public class CollectionItem: IParserAccessor
  {
Az osztályban egyetlen property-t hozunk létre Text névvel. Minden felsorolt elemnél ez lesz majdan a megjelenő felirat a HTML lapon.
    private string text;
    public string Text
    {
      get
      {
        return text;
      }
      set
      {
        text = value;
      }
    }
Az IParserAccessor interfész AddParsedSubObject függvényét kell implementálnunk. Ez akkor kerül meghívásra, mikor egy-egy al objektum értelmezésre kerül. Itt kell gondoskodnunk az objektum értékének tárolásáról, melyre nyilván a Text property-nk szolgál.
    void IParserAccessor.AddParsedSubObject(object obj)
    {
      if (obj is LiteralControl)
      {
        Text = ((LiteralControl)obj).Text;
      }
    }
  }            
CollectionItems osztály
A CollectionItems osztályunkban készítjük el azt a kollekciót, mely a web kontrol property-jének alapjául szolgál majd. Ehhez három interfészt használunk fel: ICollection, IEnumerable, IList.
  public class CollectionItems: ICollection, IEnumerable, IList
  {
A kollekció egyes elemeit egy ArrayList osztályban fogjuk tárolni.
    private ArrayList al;
    public CollectionItems()
    {
      al = new ArrayList();
    }
A kollekció indexelőjénél az ArrayList megfelelő elemét adjuk vissza, illetve állítjuk be.
    object IList.this[int index]
    {
      get
      {
        return al[index];
      }
      set
      {
        al[index] = (CollectionItem)value;
      }
    }
A Count property-n a kollekció elemszáma kérdezhető le.
    public int Count
    {
      get
      {
        return al.Count;
      }
    }
    ...
  } 
A további property-knél egyszerűen csak az ArrayList megfelelő property-jét szolgáltatjuk.
CollectionControl osztály
A web kontrolunk létrehozásánál meg kell adnunk a ParseChildren attribútumot. Ennek első paraméterében igaz értéket adunk annak érdekében, hogy a kontrol gyermek elemei értelmezhetővé váljanak. Második paraméterben azt a property-t adjuk meg, melyhez a gyermek elemek tartoznak. Ez nem lesz más, mint a kollekció típusú property, az Items.
  [ParseChildren(true, "Items")]
  public class CollectionControl: System.Web.UI.WebControls.WebControl
  {
Az Items property lesz tehát a CollectionItems típusú.
    private CollectionItems ci = new CollectionItems();
    [MergableProperty(false), PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public CollectionItems Items
    {
      get
      {
        return ci;
      }
    }
A web kontrol HTML kódját kell előállítanunk a Render függvényben.
    protected override void Render(HtmlTextWriter output)
    {
Ha van eleme a kollekciónak, akkor kezdjük el az <ul> HTML objektumot, majd egy ciklus segítségével megadjuk az egyes szövegeket egy <li> tag után. A szövegeket a kollekcióból olvassuk ki. A ciklus végén egy </ul> elemmel zárjuk a HTML objektumot.
      if (ci.Count > 0)
      {
        output.Write("<ul>");
        for (int i = 0; i < ci.Count; i++)
        {
          output.Write("<li>" + ((CollectionItem)ci[i]).Text);
        }
        output.Write("</ul>");
      }
Ha nincs eleme a kollekciónak, akkor csak egy mínusz karaktert írunk ki.
      else
      {
        output.Write(" - ");
      }
    }
  }
Az eredmény
Miután feltettünk egy web kontrolt és feltöltöttük annak elemeit, váltsunk HTML nézetre, ahol jól látható, hogy milyen módon kerül tárolásra kollekciónk minden egyes Text property-je.
      <cc1:CollectionControl id="CollectionControl2" style="Z-INDEX: 102; LEFT: 32px; POSITION: absolute; TOP: 104px" runat="server">
        <cc1:CollectionItem Text="A"></cc1:CollectionItem>
        <cc1:CollectionItem Text="B"></cc1:CollectionItem>
        <cc1:CollectionItem Text="C"></cc1:CollectionItem>
        <cc1:CollectionItem Text="D"></cc1:CollectionItem>
        <cc1:CollectionItem Text="E"></cc1:CollectionItem>
      </cc1:CollectionControl>