Der er masser af muligheder for at folde sig ud i .Net, og der masser af muligheder for at bygge nogle stærke web sider udfra solide design principper. Følgende indlæg kommer til at omhandle, hvordan man dynamisk kan indlæse usercontrols (*.ascx) ind i en anden 'UserControl', og hvordan man kan neste 'UserControls, og tilgå deres postede væerdier fra et ydre niveau.

Følgende illustration kan virke en smule overdrevet. I mit lille projekt giver det dog god mening, hvorimod man nok kunne fjerne 'SubControl.ascx' fra dette eksempel. Dog kan overdrivelsen somme tider fremme forståelsen. Eksemplet synliggør i virkeligheden hierakiet af kontrollerne.

Som man kan se ligger det væsentlige i de inderste filer ('UsrControl01.ascx' og 'UsrControl02.ascx'). Ideen er at man skal kunne udvikle flere komponenter med tiden og kunne tilføje dem dynamisk. Jeg har undladt at vise håndtering af fremtidige 'UserControls'. Definition og lokation kan gemmes i en xml fil, man så kan indlæse og dynamisk løbe alle de definerede UserControls i xml filen igennem.
I dette eksempel viser jeg hvordan, man kan tilføje dem og arbejde med deres indhold.

Side struktur

'Main.Master' er blot en master side.
'Default.aspx' baserer sig på master sidens definition af ContentPlaceHolders.
'MainControl.ascx' er den første userkontrol hvor jeg i dette eksempel har en registrering af 'SubControl.ascx' og en 'asp.net button' kontrol som fungerer som en submit knap.
'SubControl.ascx' sørger for at (fx. indlæse en xml fil med en liste af UserControls) dynamisk indlæse diverse UserControls.
'UsrControlxx.ascx' repræsenterer små komponenter eller samling af logiske form felter.

I de enkelte 'UserControls' filer har jeg i dette eksempel en TextBox kontrol i 'UsrControl01.ascx' og i 'UsrControl02.ascx'har jeg en simpel DropDownList.

Disse to UserControls bliver indlæst i 'SubControl.ascx' på følgende måde:

   1:  namespace NestedUserControls.Controls {
   2:      public partial class SubControl : System.Web.UI.UserControl {
   3:          protected void Page_Load(object sender, EventArgs e) {
   4:              Controls.Add(LoadControl("~/Controls/UsrControl01.ascx"));
   5:              Controls.Add(LoadControl("~/Controls/UsrControl02.ascx"));
   6:          }
   7:      }
   8:  }


Igen istedet for at skrive dem ind én af gangen kan man sagtens læse dem ind fra en xml fil og løbe antallet igennem og tilføje dem dynamisk. Jeg har simplificeret for eksemplets skyld.
I 'MainControl.ascx' er 'SubControl.ascx' registreret. 'MainControl.ascx' indeholder 'SubControl.ascx' og en submit knap:

   1:  <uc1:SubControl ID="SubControl" runat="server" />
   2:  <asp:Button ID="SubmitBtn" runat="server" Text="Send data" 
   3:      onclick="SubmitBtn_Click" />


I 'MainControl.ascx.cs' håndteres Submit knappens onclick event, hvor jeg vha. LINQ løber kontrol hierakiet igennem og herefter gennem generics returnerer værdien af asp.net kontrollen i det format den eksisterer i.

   1:  protected TT GetControl<T, TT>(string controlId) 
   2:   where T : UserControl 
   3:   where TT : class {
   4:     var res = Controls.OfType<T>().Select(s => s.FindControl(controlId)).Single();
   5:     return res as TT;
   6:  }


Værdierne tilgås på følgende vis:

   1:  var value1 = GetControl<UsrControl01, TextBox>("MyTextBox").Text;
   2:  var value2 = GetControl<UsrControl02, DropDownList>("DropDownList1").SelectedItem;


Meget elegant og stærk brug af kombination af generics og LINQ. Man kan spørge sig selv, hvornår man har brug for at klippe ting i x antal 'Usercontrols'. Det gør man, hvis man vil lave en wizard, hvilket i virkeligheden mit lille projekt går ud på. Frameworket baserer sig på ovenstående, og antal af steps i wizard bestemmes af antallet af 'UsrControlxx.ascx'. I mit lille wizard projekt ligger defintionerne af 'UserControls' i en xml fil.

Der vil inden længe komme et JQuery baseret wizard eksempel sat sammen med ASP.Net.