IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ASP.NET Discussion :

Templated User Control


Sujet :

ASP.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut Templated User Control
    Bonjour à tous,

    J'ai créé des user controls qui implémentent un template (comme les UpdatePanels, les LoginView ou les Repeater). Ils fonctionnent parfaitement au run-time mais je n'arrive pas à ce qu'ils soient rendus sur la page en mode design.

    L'IDE ne connait pas le tag <Template> (qui est une propriété ITemplate Template au niveau de mon contrôle) car il essaie de faire le rendering de la classe de base (UserControl) et non de ma classe.

    Est-ce que l'un d'entre vous aurait une piste pour améliorer cela?

    Merci d'avance!

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Novembre 2007
    Messages : 68
    Par défaut Exemple de code
    Allez voir ici, j'ai placé un exemple de code qui vous aidera peut-être. Sinon, il serait bien de nous transmettre votre code car sinon on travail en aveugle.

    http://www.developpez.net/forums/sho...09&postcount=7

  3. #3
    Membre émérite Avatar de neptune
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    835
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2003
    Messages : 835
    Par défaut
    Merci pour votre intervention, mais je re-précise le contexte: ce n'est ni un CompositeControl, ni un WebControl, mais bien un UserControl (fichier ascx).

    J'anticipe la question "Pourquoi un UserControl?": et bien parce que la partie HTML est très complexe, contient beaucoup d'image et de style. Par contre, c'est un composent qui sera souvent utilisé.

    Voici un exemple trivial d'un templated user control:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="WelcomeMessage.ascx.cs" Inherits="Components_WelcomeMessage" %>
     
    <%-- Décor HTML --%>
     
    <asp:PlaceHolder ID="CustomContent" runat="server"></asp:PlaceHolder>
     
    <%-- Décor HTML --%>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     
    [Designer(typeof(WelcomeMessageDesigner))]
    public partial class Components_WelcomeMessage : System.Web.UI.UserControl
    {
        private ITemplate m_morningTemplate;
        private ITemplate m_afternoonTemplate;
        private ITemplate m_eveningTemplate;
     
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        [TemplateContainer(typeof(WelcomeMessageContainer))]
        public ITemplate MorningTemplate
        {
            get { return m_morningTemplate; }
            set { m_morningTemplate = value; }
        }
     
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        [TemplateContainer(typeof(WelcomeMessageContainer))]
        public ITemplate AfternoonTemplate
        {
            get { return m_afternoonTemplate; }
            set { m_afternoonTemplate = value; }
        }
     
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        [TemplateContainer(typeof(WelcomeMessageContainer))]
        public ITemplate EveningTemplate
        {
            get { return m_eveningTemplate; }
            set { m_eveningTemplate = value; }
        }
     
        void Page_Init()
        {
            ITemplate template = SelectedTemplate();
            WelcomeMessageContainer container = new WelcomeMessageContainer();
            template.InstantiateIn(container);
            CustomContent.Controls.Add(container);
        }
     
        private ITemplate SelectedTemplate()
        {
            DateTime now = DateTime.Now;
     
            if (now.Hour < 12)
            {
                return MorningTemplate;
            }
            else if (now.Hour < 18)
            {
                return AfternoonTemplate;
            }
     
            return EveningTemplate;
        }
    }
     
    public class WelcomeMessageContainer : Control, INamingContainer
    {
     
    }
     
    public class WelcomeMessageDesigner : UserControlDesigner
    {
        public override string GetDesignTimeHtml()
        {
            StringWriter stringWriter = new StringWriter(CultureInfo.CurrentCulture);
            HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
     
            Literal literal = new Literal();
            literal.Text = "Design";
     
            literal.RenderControl(htmlWriter);
     
            return stringWriter.ToString();
        }
    }
    Et son utilisation dans une page:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test.aspx.cs" Inherits="Test" %>
    <%@ Register TagPrefix="uc" TagName="WelcomeMessage" src="~/Components/WelcomeMessage.ascx" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <uc:WelcomeMessage ID="WelcomeMessage" runat="server">
    	        <MorningTemplate>
    	            <h1><asp:Literal ID="WelcomeLiteral" runat="server" Text="Matin"></asp:Literal></h1>
    	        </MorningTemplate>
    	        <AfternoonTemplate>
    	            <h1><asp:Literal ID="WelcomeLiteral" runat="server" Text="Après-midi"></asp:Literal></h1>
    	        </AfternoonTemplate>
    	        <EveningTemplate>
    	            <h1><asp:Literal ID="WelcomeLiteral" runat="server" Text="Soir"></asp:Literal></h1>
    	        </EveningTemplate>
    	    </uc:WelcomeMessage>
        </div>
        </form>
    </body>
    </html>
    Comme je l'ai précisé dans mon post initial, l'IDE veut absolument utiliser UserControlDesigner (qui, évidement, en connait pas mes propriétés Template) pour dessiner le controle, même si je spécifie un Designer dédié.

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    68
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Novembre 2007
    Messages : 68
    Par défaut 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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

Discussions similaires

  1. Réponses: 0
    Dernier message: 02/05/2011, 17h37
  2. [C#] User control
    Par Verboz dans le forum ASP.NET
    Réponses: 4
    Dernier message: 27/04/2005, 22h46
  3. [C#] User Control dynamic
    Par Erakis dans le forum ASP.NET
    Réponses: 10
    Dernier message: 21/10/2004, 18h54
  4. [C#] DateTimePicker web user control
    Par titi29 dans le forum ASP.NET
    Réponses: 8
    Dernier message: 29/06/2004, 18h38
  5. [VB.NET] Provoquer le rechargement d'un user control..
    Par didoboy dans le forum ASP.NET
    Réponses: 7
    Dernier message: 30/04/2004, 14h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo