Oui mais, et si, pourquoi pas...
Je comprends tout à fait la problématique liée à l'utilisation d'un WebControl pour y avoir été confronté.
Cependant, le WebControl ne vous apportera pas entière satisfaction.
Voila ce que je vous propose, un vrai Control (CompositeControl, WebControl peut importe). Simplement, il suffit de surcharger CreateChildControl et de charger (soit un WebControl, soit même un fichier Html) dans la collection Controls.
La problématique c'est de trouver un moyen pour que cela fonctionne en mode design sinon ont ne peut pas utiliser le template.
Voici un morceau de code récupéré dans un de mes anciens projets. Je ne peux pas vous livrer les codes avec lequels je travail mainteant car 1) Ils sont trop volumineux 2) Ils implémentes des mécanismes beaucoup plus sophistiquer qu'il me faudrait détailler 3) Je vie de ces codes donc je veux attendre un peu avant de les lacher dans la nature. Mais vous trouverez tout de même de quoi faire avec ce qui suit, même si depuis j'ai amélioré et optimisé ma technique (vous gagnerez tout de même un temps de travail considérable, même si vous avez à adapter ces codes à vos besoins) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
protected override void CreateChildControls()
{
string pageSkeletonFileName = "CTRLCNTNT_PageSkeleton.ascx";
HelperLoadControl(this, pageSkeletonFileName);
_CellLeftPanel = ((System.Web.UI.HtmlControls.HtmlTableCell)(FindControl("cellLeftPanel")));
_CellPagePanel = ((System.Web.UI.HtmlControls.HtmlTableCell)(FindControl("cellPagePanel")));
_CellPageNavigator = ((System.Web.UI.HtmlControls.HtmlTableCell)(FindControl("cellPageNavigator")));
_LinkPageFirst = ((System.Web.UI.HtmlControls.HtmlAnchor)(FindControl("linkPageFirst")));
_LinkPagePrevious = ((System.Web.UI.HtmlControls.HtmlAnchor)(FindControl("linkPagePrevious")));
_LinkPageNext = ((System.Web.UI.HtmlControls.HtmlAnchor)(FindControl("linkPageNext")));
_LinkPageLast = ((System.Web.UI.HtmlControls.HtmlAnchor)(FindControl("linkPageLast")));
// Grâce aux FindControl, je récupère des références sur les controls
// Qui ont été chargés depuis le fichier ascx.
// Vous faites ensuite votre travail habituel pour implémenter vos templates
} |
L'avantage de cela, c'est qu'avec une simple propriété ont peut changer l'ascx qui sera chargé et donc modifier le design tout en gardant le même contrôle.
Vous noterez que j'utilise un méthode HelperLoadControl, cette méthode implémente un mécanisme de lecture qui est opérationnel tant en mode design que lors de l'exécution.
Voici la méthode que le Helper appel :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public static void LoadControl(System.Web.UI.Control HostControl, string VirtualFileName)
{
string FileContent = System.IO.File.ReadAllText(MapPath(HostControl,VirtualFileName), System.Text.Encoding.UTF7);
System.Text.RegularExpressions.Regex rega = new System.Text.RegularExpressions.Regex(@"[#]ROOT[/]", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Multiline);
FileContent = rega.Replace(FileContent, RootPath(HostControl));
if (HostControl.Site!=null)
{
System.ComponentModel.Design.IDesignerHost host = (System.ComponentModel.Design.IDesignerHost)(HostControl.Site.GetService(typeof(System.ComponentModel.Design.IDesignerHost)));
Control[] ctrls = System.Web.UI.Design.ControlParser.ParseControls(host, FileContent);
int pos = HostControl.Controls.Count;
for (int i = ctrls.Length - 1; i >= 0; i--)
{
HostControl.Controls.AddAt(pos, ctrls[i]);
}
}
else
{
Control ctrl = HostControl.Page.ParseControl(FileContent);
int pos = HostControl.Controls.Count;
for (int i = ctrl.Controls.Count - 1; i >= 0; i--)
{
HostControl.Controls.AddAt(pos, ctrl.Controls[i]);
}
}
} |
Notez l'utilisation du #ROOT qui permet de rendre relatifs à la racine les urls dans les attributs style="" (très pratique, parceque notre contrôle est suceptible d'être utilisé en de nombreux endroits de la hierarchie du site).
Cette méthode fait aussi référence à d'autres méthodes dont voici le code :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
public static string MapPath(System.Web.UI.Control Ctrl, string VirtualFileName)
{
if (Ctrl.Site!=null)
{
System.Web.UI.Design.IWebApplication webApp = (System.Web.UI.Design.IWebApplication)(Ctrl.Site.GetService(typeof(System.Web.UI.Design.IWebApplication)));
if (webApp != null)
{
try
{
System.Web.UI.Design.IProjectItem item = webApp.GetProjectItemFromUrl(VirtualFileName);
return item.PhysicalPath;
}
catch
{
throw new Exception("Le fichier '" + VirtualFileName + "' n'existe pas.");
}
}
else
{
throw new Exception("Impossible de localiser l'application Web");
}
}
else
{
return Ctrl.Page.Server.MapPath(VirtualFileName);
}
}
public static string RootPath(System.Web.UI.Control Ctrl)
{
if (Ctrl.Site!=null)
{
System.Web.UI.Design.IWebApplication webApp = (System.Web.UI.Design.IWebApplication)(Ctrl.Site.GetService(typeof(System.Web.UI.Design.IWebApplication)));
if (webApp != null)
{
return webApp.RootProjectItem.PhysicalPath;
}
else
{
throw new Exception("Impossible de localiser l'application Web");
}
}
else
{
if (Ctrl.Page != null)
{
string r = Ctrl.Page.Request.Url.AbsoluteUri;
int i = r.LastIndexOf(Ctrl.Page.Request.ApplicationPath);
if (i > 0)
{
return r.Substring(0, i + Ctrl.Page.Request.ApplicationPath.Length) + "/";
}
return string.Empty;
}
else
{
throw new Exception("Page inexistante");
}
}
} |
Avec ces 3 méthodes, vous retrouvez la racine d'un site, vous pouvez mapper un chemin virtuel, charger un fichier sous forme de contrôles, tant en mode design qu'en exécution.
Normelement vous devez pouvoir vous en sortir ainsi. Avec tout cela, je fais de magnifiques contrôles à tous mes clients parfois en quelques minutes. Je modèlise l'ensemble de mes site web 100% WYSIWYG. Ainsi, des nons développeurs peuvent concevoir des pages. Du coup, mes clients m'adorent...
Bon courage.