I programmatori Asp.Net Web Form conoscono bene il concetto di User Control grazie al quale è possibile creare dei propri controlli raggruppando quelli già esistenti, non tutti invece conoscono la possibilità di creare dei Templated User Control in cui non siamo noi a creare l’interfaccia che avrà il controllo ma è l’utente del nostro controllo che, attraverso la definizione di un template, può definire il rendering del controllo, un po’ come fa il controllo asp:repeater.
Nonostante possa spaventare a primo impatto, la realizzazione di questi controlli è più semplice di quello che si crede una volta capito il meccanismo. Si parte dai dati che si vogliono rappresentare, supponiamo una news:
1: using System;
2:
3: namespace WebApplication1
4: {
5: public class News
6: {
7: public string Titolo { get; set; }
8: public DateTime Data { get; set; }
9: public string Testo { get; set; }
10: public string Link { get; set; }
11: }
12: }
Creiamo uno user control come siamo abituati a fare, aggiungendolo come nuovo item, e nel markup l’unica cosa che dobbiamo fare è creare un PlaceHolder:
1: <%@ Control Language="C#" AutoEventWireup="true"
2: CodeBehind="NewsTemplateContoller.ascx.cs"
3: Inherits="WebApplication1.UC.NewsTemplateContoller" %>
4:
5: <asp:PlaceHolder id="PlaceHolderNewsTemplate" runat="server">
6: </asp:PlaceHolder>
Definiamo nel code behind del controllo due property, una del nostro tipo News e l’altra di tipo ITemplate che chiameremo LayoutTemplate:
1: using System;
2: using System.Web.UI;
3:
4: namespace WebApplication1.UC
5: {
6: public partial class NewsTemplateContoller : System.Web.UI.UserControl
7: {
8: [PersistenceMode(PersistenceMode.InnerProperty)]
9: [TemplateContainer(typeof(NewsUcContainer))]
10: public ITemplate LayoutTemplate { get; set; }
11:
12: public News News { get; set; }
13: }
14: }
La property ITemplate deve essere decorata con due attributi:
-
PersistenceMode, che specifica come un controlo asp.net persiste le proprietà a design time, nel nostro caso InnerDefaultProperty specifica che le proprietà saranno persistite all'interno del tag di apertura e chiusura del controllo
-
TemplateContainer, che serve a indicare che è un contenitore, nel nostro caso, di contenuti di tipo NewsUcContainer
A questo punto dobbiamo creare il nostro container, che chiameremo NewsContainer e che, oltre ad essere un Control, implementerà l’interfaccia INamingContainer che è vuota e serve solo a marcare la classe come contenitore:
1: public class NewsUcContainer : Control, INamingContainer
2: {
3: public News News { get; set; }
4:
5: public NewsUcContainer(News news)
6: {
7: this.News = news;
8: }
9: }
A questo punto basta implementare il Page_Init del nostro controllo per legare quanto realizzato fino a questo momento:
1: protected void Page_Init(object sender, EventArgs e)
2: {
3: PlaceHolderNewsTemplate.Controls.Clear();
4:
5: if(LayoutTemplate != null)
6: {
7: if (this.News == null) this.News = new News();
8: NewsUcContainer container = new NewsUcContainer(this.News);
9: this.LayoutTemplate.InstantiateIn(container);
10: PlaceHolderNewsTemplate.Controls.Add(container);
11: }
12: }
In pratica svuotiamo il placeholder da eventuali contenuti e se il LayoutTemplate non è vuoto istanziamo il container e lo riversiamo nel LayoutTemplate, dopodichè non ci resta che aggiungere il container ai controlli del placeholder.
Usare il nostro controllo significa come al solito registrarlo nella pagina…
1: <%@ Register src="UC/NewsTemplateContoller.ascx" tagname="NewsTemplateContoller" tagprefix="uc1" %>
e creare il template per la nostra news all’interno del LayoutTemplate:
1: <uc1:NewsTemplateContoller ID="NewsTemplateContoller1" runat="server">
2: <LayoutTemplate>
3: <h3><% 1: # Container.News.Titolo
%></h3>
4: <p style="font-style:italic"><% 1: # Container.News.Data.ToString("dd-MM-yyyy")
%></p>
5: <p><% 1: # Container.News.Testo
%></p>
6: <asp:hyperlink navigateurl='<%# Container.News.Link %>' runat="server" />
7: </LayoutTemplate>
8: </uc1:NewsTemplateContoller>
Bindiamo qualche dato di prova nella Page_Load:
1: protected void Page_Load(object sender, EventArgs e)
2: {
3: NewsTemplateContoller1.News.Data = DateTime.Now;
4: NewsTemplateContoller1.News.Link = "http://www.dotnetcampania.org";
5: NewsTemplateContoller1.News.Titolo ="DotNetCampania on line!";
6: NewsTemplateContoller1.News.Testo = "Finalmente On Line il primo User Group tutto campano sulle tecnologie .NET ! Nati nel Giugno 2009 e costituitici nel Gennaio 2010 come Associazione no-profit legalmente riconosciuta, ci poniamo come obiettivo quello di riunire tutti gli appassionati di tecnologie .NET residenti in campania; anche se naturalmente possono iscriversi tutti quelli che reputeranno utile fare community con noi.";
7: NewsTemplateContoller1.DataBind();
8: }
Ed ecco il favoloso risultato:
Il consiglio è: provateci! Sembra più complicato di quello che effettivamente è quindi non lasciatevi intimorire!
-- Michele