jeudi 1 avril 2010

Asp.net 3.5 - Custom control dynamique, PostBack et ViewState

Un exemple est toujours mieux qu’un long discours, ci dessous une page asp.net faisant l’affichage dynamique de custom contrôle en fonction du type de données récupéré.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="EditDashBoard.aspx.cs" Inherits="Admin_Dashboard_EditDashBoard" %>
<%@ Register TagPrefix="uc1" TagName="uCtrlTitle" Src="../../Include/UserControls/uCtrlTitle.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">
    <META HTTP-EQUIV="Pragma" CONTENT="no-cache" />
    <META HTTP-EQUIV="Expires" CONTENT="-1" />
    <title>EditDashboard</title>
    <link href="../../Css/standard/standard.css" type="text/css" rel="stylesheet" />
</head>
<body>
    <form id="form1" runat="server">
    <div style="text-align:center;margin-top:10px" align="center">
            <table align="center" width="95%" border="0">
              <tr>
                    <td align="center"><uc1:uctrltitle id="UCtrlTitle1" runat="server"></uc1:uctrltitle></td>
              </tr>
        </table>
    </div>
    <div style="text-align:center;margin-top:10px" align="center">
        <asp:Panel id="Panelcontent" runat="server">
         
        </asp:Panel>
    </div>   
    </form>
</body>
</html>
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MonProjet.Business.DashBoard;
using MonProjet.DAL.Objects;
using MonProjet.DAL.DatasContexts.DashBoard;
using MonProjetV2.Include.Controls.Dashboard;
 
/// <summary>
/// Page d'édition de control panel
/// </summary>
public partial class Admin_Dashboard_EditDashBoard : BasePage
{
    /// <summary>
    /// Liste servant a recréer des controles dynamiques
    /// </summary>
    List<DynamicControlForViewState> DynamicControls
    {
        get
        {
            if (ViewState["DynamicControls"] == null)
            {
                ViewState["DynamicControls"] = new List<DynamicControlForViewState>();
            }
            return (List<DynamicControlForViewState>)ViewState["DynamicControls"];
        }
        set
        {
            ViewState["DynamicControls"] = value;
        }
    }
 
 
    /// <summary>
    /// Chargement de la page, récupération de l'id du dashboard à éditer
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Page_Load(object sender, EventArgs e)
    {
 
        Translation();
 
        if (!Page.IsPostBack)
        {
            if (PreviousPage != null)
            {
                try
                {
                    //Récupération de l'id du control panel
                    int l_DashBoardId = -1;
                    string l_Tmp = ((HiddenField)Page.PreviousPage.Controls[0].FindControl("Hd_DashBoardId")).Value;
                    if (!int.TryParse(l_Tmp, out l_DashBoardId))
                    {
                        //TODO error
                        Response.Write("ERROR");
                    }
                    else
                    {
                        if (l_DashBoardId > 0)
                        {
                            //TODO affichage
                            LoadControls(l_DashBoardId, GetLanguageId());
                            return;
                        }
                        else
                        {
                            //TODO error
                            Response.Write("ERROR");
                        }
                    }
                }
                catch
                {
                    //TODO error
                    Response.Write("ERROR");
                }
 
            }
        }
        else {
            ReLoadDynamicControls();
        }
     
 
    }
 
    #region private
 
    /// <summary>
    /// Traduction
    /// </summary>
    private void Translation()
    {
        UCtrlTitle1.SetTitle(Translate("EDITDASHBOARD"));
 
    }
 
 
    /// <summary>
    /// Rechargement des controls apres un postback par exemple
    /// </summary>
    private void ReLoadDynamicControls()
    {
        foreach (DynamicControlForViewState val in DynamicControls)
        {
            //Création des parties à afficher en fonction de leur type
            //NB : Ne pas oublier de rattacher les Events si besoins.
            switch (val.ControlType)
            {
                case 1: //Cokpit Main part
                    var CockpitPart = new DashBoardMainPart();
                    CockpitPart.ID = val.ControlId;
                    Panelcontent.Controls.Add(CockpitPart);
                    break;
                case 2: //Detail Main part
                    var DetailPart = new DashBoardMainPart();
                    DetailPart.ID = val.ControlId;
                    Panelcontent.Controls.Add(DetailPart);
                    break;
                case 3: //Titre
                    var TitrePart = new DashBoardtitle();
                    TitrePart.ID = val.ControlId;
                    Panelcontent.Controls.Add(TitrePart);
                    break;
                case 4: //Section
                    var SectionPart = new DashBoardMainPart();
                    SectionPart.ID = val.ControlId;
                    Panelcontent.Controls.Add(SectionPart);
                    break;
                default: //Default part
                    var DefaultPart = new DashBoardMainPart();
                    DefaultPart.ID = val.ControlId;
                    Panelcontent.Controls.Add(DefaultPart);
                    break;
            }
        }
    }
 
    /// <summary>
    /// Charge les controles depuis une liste
    /// </summary>
    /// <param name="l_Res"></param>
    private void LoadControlsFromList(List<DashBoardLine> l_Res)
    {
        List<DynamicControlForViewState> l_ControlList = new List<DynamicControlForViewState>();
        foreach (DashBoardLine val in l_Res)
        {
            //Création des parties à afficher en fonction de leur type
            switch (val.TypCtrlPanelLgn_Id)
            {
                case 1: //Cokpit Main part
                    var CockpitPart = new DashBoardMainPart();
                    CockpitPart.ID = string.Format("{0}{1}","CockpitPart",val.CtrPanelLgn_Id.ToString());
                    CockpitPart.Text = val.CtrPanelLgnTrans_Label;
                    CockpitPart.LigneId = val.CtrPanelLgn_Id;
                    CockpitPart.DashBoardId = val.CtrlPanel_Id;
                    Panelcontent.Controls.Add(CockpitPart);
                    l_ControlList.Add(new DynamicControlForViewState(1, CockpitPart.ID));
                    break;
                case 2: //Detail Main part
                    var DetailPart = new DashBoardMainPart();
                    DetailPart.ID = string.Format("{0}{1}", "DetailPart", val.CtrPanelLgn_Id.ToString());
                    DetailPart.Text = val.CtrPanelLgnTrans_Label;
                    DetailPart.LigneId = val.CtrPanelLgn_Id;
                    DetailPart.DashBoardId = val.CtrlPanel_Id;
                    Panelcontent.Controls.Add(DetailPart);
                    l_ControlList.Add(new DynamicControlForViewState(2, DetailPart.ID));
                    break;
                case 3: //Titre
                    var TitrePart = new DashBoardtitle();
                    TitrePart.ID = string.Format("{0}{1}", "TitrePart", val.CtrPanelLgn_Id.ToString());
                    TitrePart.Text = val.CtrPanelLgnTrans_Label;
                    Panelcontent.Controls.Add(TitrePart);
                    l_ControlList.Add(new DynamicControlForViewState(3, TitrePart.ID));
                    break;
                case 4: //Section
                    var SectionPart = new DashBoardMainPart();
                    SectionPart.ID = string.Format("{0}{1}", "SectionPart", val.CtrPanelLgn_Id.ToString());
                    SectionPart.Text = val.CtrPanelLgnTrans_Label;
                    Panelcontent.Controls.Add(SectionPart);
                    l_ControlList.Add(new DynamicControlForViewState(4, SectionPart.ID));
                    break;
                default: //Default part
                    var DefaultPart = new DashBoardMainPart();
                    DefaultPart.ID = string.Format("{0}{1}", "DefaultPart", val.CtrPanelLgn_Id.ToString());
                    DefaultPart.Text = val.CtrPanelLgnTrans_Label;
                    Panelcontent.Controls.Add(DefaultPart);
                    l_ControlList.Add(new DynamicControlForViewState(1, DefaultPart.ID));
                    break;
            }
 
        }
        //Svg dans le viewstate la liste des controles de la page
        //On ne sauvegarde que le type, le contenu des controles est conservé par le viewstate de ses controles enfants
        DynamicControls = l_ControlList;
    }
 
    /// <summary>
    /// Chargement des lignes
    /// </summary>
    /// <param name="DashBoardId">Id du dashboard</param>
    /// <param name="LangueId">Langue devant être chargé</param>
    private void LoadControls(int DashBoardId, int LangueId)
    {
        var L_LstLines = Dashboard.Get_DashBoardLines(DashBoardId, LangueId);
        LoadControlsFromList(L_LstLines);
      
    }
   
 
    #endregion
}
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
/// <summary>
/// Objet permettant de Sauvegarder l'id et le type d'un control,
/// utilisé par exemple dans des listes de controles dynamique stockées en viewstate
/// </summary>
[Serializable]
public class DynamicControlForViewState
{
    public int ControlType { get; set; }
    public string ControlId { get; set; }
 
    public DynamicControlForViewState()
    {
 
    }
 
    public DynamicControlForViewState(int NType,String NId)
    {
        ControlId = NId;
        ControlType = NType;
    }
}
 
using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
 
namespace MonProjetV2.Include.Controls.Dashboard
{
   
    /// <summary>
    /// Control utlisé dans le dashboard pour affiché les titres de grandes parties
    /// </summary>  
    public class DashBoardMainPart : WebControl, IPostBackEventHandler
    {
        /// <summary>
        /// Constructeur, maintient également les controles
        /// </summary>
        public DashBoardMainPart()
            : base()
        {
            //Maintient le contenu des controls
            this.EnsureChildControls();
        }
 
        #region properties
 
        /// <summary>
        /// Nom utilisé à la génération des Id des controles enfants
        /// </summary>
        private string ControlDisplayTypeName = "DashBoardMainPartControl";
 
        /// <summary>
        /// Image button permettant d'ajouter un titre
        /// </summary>
        protected ImageButton AddTitleButton = new ImageButton();
 
        /// <summary>
        /// Text principal affiché dans l'encadré
        /// </summary>
        protected Literal MainText = new Literal();
 
        /// <summary>
        /// Conserve le contenue du MainText à travers les postback
        /// </summary>
        protected HiddenField HDMainTextValue = new HiddenField();
 
        /// <summary>
        /// Champs caché permettant de maintenir le numéro de ligne
        /// </summary>
        protected HiddenField HDLigneId = new HiddenField();
 
        /// <summary>
        /// Champs caché permettant de maintenir le numéro de dashboard
        /// </summary>
        protected HiddenField HDDashBoardId = new HiddenField();
 
 
        /// <summary>
        /// Control de test pour vérifier que le viewstate d'un contrôle est bien conservé après un postback
        /// </summary>
        protected TextBox TxtTest  = new TextBox();
 
 
        [      
        Description("Le texte affiché dans l'encadré principal"),
        DefaultValue(""),
        Localizable(true)
        ]
        public string Text
        {
 
            get {
                if (string.IsNullOrEmpty(MainText.Text))
                    if (!string.IsNullOrEmpty(HDMainTextValue.Value))
                        MainText.Text = HDMainTextValue.Value;
                    else
                        MainText.Text = string.Empty;
                return this.MainText.Text;
            }
            set {
                HDMainTextValue.Value = value;
                this.MainText.Text = value;
            }
        }
 
 
        [
        Description("Identifiant de la ligne"),
        DefaultValue(-1),
        Localizable(true)
        ]
        public int LigneId
        {
 
            get
            {
                string s = HDLigneId.Value;
                if (!string.IsNullOrEmpty(s))
                {
                    int OutResult;
                    if (int.TryParse(s, out OutResult))
                        return OutResult;
                    else
                        return 0;
                }
                else
                    return 0;
            }
            set
            {
                this.HDLigneId.Value = value.ToString();
            }
        }
 
        [
        Description("Identifiant du DashBoard"),
        DefaultValue(-1),
        Localizable(true)
        ]
        public int DashBoardId
        {
            get
            {
                string s = HDDashBoardId.Value;
                if (!string.IsNullOrEmpty(s))
                {
                    int OutResult;
                    if (int.TryParse(s, out OutResult))
                        return OutResult;
                    else
                        return 0;
                }
                else
                    return 0;
            }
            set
            {
                this.HDDashBoardId.Value = value.ToString();
            }
        }
 
        #endregion
 
        #region Gestion des controles enfants
        /// <summary>
        /// Ajout des controles enfants à la collection du custom control,
        /// permet de maintenir le control apres un postback(Viewstates etc.etc.)
        /// </summary>
        protected override void CreateChildControls()
        {
            //Init
            AddTitleButton.ImageUrl = ResolveUrl("~/Images/icons/icon_add.gif");
 
            //AddControls     
            this.Controls.Add(AddTitleButton);
            this.Controls.Add(MainText);
            this.Controls.Add(HDLigneId);
            this.Controls.Add(HDDashBoardId);
            this.Controls.Add(HDMainTextValue);
 
          
        }
        #endregion
 
        #region EventsHandler
 
        /// <summary>
        /// EventHandler déclenché à l'ajout d'un titre
        /// </summary>
        public event EventHandler CreateTitle;
 
        /// <summary>
        /// Evenement déclenché par le click de l'ajout de titre
        /// </summary>
        /// <param name="Sender"></param>
        /// <param name="e"></param>
        protected virtual void AddTitleButton_Click(object Sender, EventArgs e)
        {
            //Si des méthodes sont abonnées alors on déclenche l'événement
            if (CreateTitle != null)
            {
                CreateTitle(this, e);
            } 
            //Traitement systematique
            HttpContext.Current.Response.Write("POSTBACK ADD TITLE!!!! de "+this.ID.ToString()+" valeur post : "+TxtTest.Text );
          
        }
 
        // Remonté du posteBack, gestion manuel
        public void RaisePostBackEvent(string eventArgument)
        {
            AddTitleButton_Click(this,new EventArgs());
        }
 
       
        /// <summary>
        /// Ajout des références de postback sur les controles concernés
        /// </summary>
        /// <param name="writer"></param>
        private void AddPostBackReference(HtmlTextWriter writer)
        {
            //L'ajout de return false permet d'empecher le postback de formulaire au profit de notre postback
            writer.AddAttribute(HtmlTextWriterAttribute.Onclick,
                   Page.ClientScript.GetPostBackEventReference(this, "CreateTitle")+";return false;");
            AddTitleButton.Attributes.AddAttributes(writer);
           
 
        }
        #endregion
        /// <summary>
        /// Gestion du rendu graphique du control
        /// </summary>
        /// <param name="writer"></param>
        protected override void RenderContents(HtmlTextWriter writer)
        {
 
            //Render
            if (Visible)
            {
                //Postback, gestion manuel des liaisons
                AddPostBackReference(writer);
 
                //Init des valeurs
                MainText.Text = Text;
 
                //Header
                writer.Write(@"           
            <!-- Control DashBoardMainPart-->
            <div style='text-align:center;margin-top:10px' align='center'>
            <LINK href='" + ResolveUrl("~/Css/standard/standard.css") + @"' type='text/css' rel='stylesheet'>
            ");
                //Bandeaux
                writer.Write(@"           
            <TABLE id='tblzTitre' cellSpacing='0' cellPadding='0' width='95%' align='center' border='0'>
                  <TR>
                        <TD><table width='100%' class='cTblTitle'>
                                    <tr>
                                          <td align='center' valign='middle'>
                                        <B>");
                MainText.RenderControl(writer);
                writer.Write(@"</B>
                                          </td>
                                    </tr>
                              </table>
                        </TD>
                        <TD class='cLngBorderRightS1' width='3'></TD>
                  </TR>
                  <TR>
                        <TD class='cLngBorderBottomS1' colSpan='2' height='3' width='100%'></TD>
                  </TR>
            </TABLE>
            ");
                //Rendu des controles enfants
                writer.Write("<div style='text-align:right;margin-top:10px' align='right'>");
                AddTitleButton.RenderControl(writer);
                writer.Write("</div>");
 
                TxtTest.RenderControl(writer);
                HDMainTextValue.RenderControl(writer);
                HDLigneId.RenderControl(writer);
                HDDashBoardId.RenderControl(writer);
                //Footer
                writer.Write(@"
            </div>
            <!-- / Control DashBoardMainPart -->
            ");
            }
 
        }
    }
}

Aucun commentaire:

Enregistrer un commentaire