none
Récupération de valeur de textbox créés à la volée. RRS feed

  • Question

  • Bonjour à tous. J'utilise un Wizard, la première étape de ce wizard me permet d'introduire un nombre. La secondé étape contient ensuite autant de textbox que le nobre introduit précédement. Voici le code correspondant à la création de ces textbox:

    protected void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
        {
          
          for (int cpt = 1; cpt <= int.Parse(edt_nombre_video.Text); cpt++)
          {
            Pan_code.Controls.Add(new Label { Text = "Code de la Video " + cpt + "<br/>" });
            TextBox t = new TextBox { TextMode = TextBoxMode.MultiLine, Height = 100, Width = 400, ID=("code_video_"+cpt.ToString()) };
            Pan_code.Controls.Add(t);
            Pan_code.Controls.Add(new Label { Text = "<br/>" });
            
          }
    


    Cette partie de code fonctionne parfaitement, mes textbox sont bien créés. Cependant lors di click sur finish de mon wizzard, je ne parvient pas à récupérer les données introduites dans les différents textbox créés à la volée. J'ai essayé avec:

    for (int cpt = 1; cpt <= int.Parse(edt_nombre_video.Text); cpt++)
          {
            
            string id_textbox = "code_video_" + cpt.ToString();
            string code_video = (Pan_code.FindControl(id_textbox) as TextBox).Text;
            
            
            service.insert_code(new Code_video { Code = Server.HtmlEncode(code_video), VideoID = ID_Video });
          }
    
          
    

    Malheureusement Findcontrol ne toruve jamais le controle recherché. J'ai également essayé:

    foreach (TextBox t in Pan_code.Controls.OfType<TextBox>())
          {
            service.insert_code(new Code_video { Code = Server.HtmlEncode(t.Text), VideoID = ID_Video });
          }
    
    Dans ce dernier cas, je ne rentre jamais dans la boucle c comme si mon pannel dans lequel j'ai créé les textbox à la volée plus haut ne contenait aucun texbox. Pourtant en exécution, ces textbox sont bien créés et je peux même écrire dedans.

    Quelqu'un peut-il m'aider à comprendre pourquoi en procédant comme je le fais, je ne parviens pas à récupérer le contenu de ces textbox. Dans mon cas, il s'agit d'ASP C#.

     


    Cédric Yumba
    mercredi 13 juillet 2011 10:23

Réponses

Toutes les réponses

  • Bonjour,

    Vous créez vos textbox dynamiquement lorsque l'évènement click sur le bouton Wizard1_NextButton est géré dans le postback consécutif. Or lorsque vous cliquez sur le bouton finish vous provoquez un nouveau postback vers le serveur et ne passez plus par cet évènement. Vos textbox ne sont donc plus (re)créées dans votre panel et forcément vous ne les retrouvez plus.

    Pour vous en sortir, vous pourriez créer vos textbox dans l'évènement PreInit de la page en cas de postback

                if (Page.IsPostBack)
                {
                    for (int cpt = 1; cpt <= nombre; cpt++)
                    {
                        Pan_code.Controls.Add(new Label { Text = "Code de la Video " + cpt + "<br/>" });
                        TextBox t = new TextBox { TextMode = TextBoxMode.MultiLine, Height = 100, Width = 400, ID = ("code_video_" + cpt.ToString()) };
                        Pan_code.Controls.Add(t);
                        Pan_code.Controls.Add(new Label { Text = "<br/>" });

                    }
                }

    Cela veut dire qu'à chaque retour vers le serveur, vos textbox seront recréées et ensuite le vieuwstate jouera son rôle pour reremplir les zones. Mais j'ai l'impression que vous devrez prévoir un mécanisme pour conserver le nombre d'itérations de votre boucle. Par exemple via une variable en session.

     


    jeudi 14 juillet 2011 18:20
  • Bonjour,

    C’est vrai qu’on utilise l’évènement Page_PreInit pour créer ou recréer des contrôles dynamiques, mais vu qu’il faut aussi utiliser la valeur d’edt_nombre_video il faut s’assurer que cette information peut être utilisé. Mais, si on utilise une variable en Session il faut le modifier chez le client avant la clique sur NextButton et il n’existe pas une méthode directe pour le faire, vu que les variables Sessions sont gérées vers le serveur.

    Si on consulte le cycle de vie des pages ASP.NET on observera que les données de publication (postback) sont traitées avant l’évènement Page_PreLoad, donc il n’est pas possible construire les contrôles TextBox avant cet évènement parce qu’on ne sait pas leur nombre, mais on peut les créer dans Page_PreLoad et on peut récupérer aussi les valeurs correctes après le clique sur finish.

    Cordialement,

    Cipri


    Suivez MSDN sur Twitter   Suivez MSDN sur Facebook


    Ciprian DUDUIALA, MSFT  
    •Nous vous prions de considérer que dans le cadre de ce forum on n’offre pas de support technique et aucune garantie de la part de Microsoft ne peut être offerte.

    • Marqué comme réponse cced mardi 19 juillet 2011 15:44
    vendredi 15 juillet 2011 09:06
  • Bonjour, je comprend mieux comment cela fonctionne. Je dois utiliser la methode PreInit pour créer les différents controls. Le problème est que cette méthode s'éxécutant avant le chargement de la page, je n'ai pas accès aux autres controls de cette page. Par exemple dans mon cas cette methode ne reconnait pas mon pannel Pan_code auquel je désire ajouter mes différents contrôles. Dans la methode Preinit tout les autres controls sont null. Je ne peux donc pas ajouter mes textbox à un pannel qui n'a pas encore été instancié.

    D'un autre côté j'ai testé la méthode page_preload  recommandé par Ciprian. Avec cette méthodes tout les contrôles de la page sont bien chargés et je parvient à rajouter à mon pannel les textbox que je désire, malheureusement quand il s'agit de récupérer les valeurs de ceux-ci, j'en reviens à mon problème de départ, je ne parvient pas à récupérer le contenu de ces textbox en utilisant les méthodes présentées dans mon post de départ.


    Cédric Yumba
    vendredi 15 juillet 2011 14:58
  • Bonjour,

    Est-ce qu’on peut voir le code complet de votre page ?

     

    Cordialement,

    Cipri


    Suivez MSDN sur Twitter   Suivez MSDN sur Facebook


    Ciprian DUDUIALA, MSFT  
    •Nous vous prions de considérer que dans le cadre de ce forum on n’offre pas de support technique et aucune garantie de la part de Microsoft ne peut être offerte.

    lundi 18 juillet 2011 07:05
  • Voici le code de ma page aspx qui hérite d'une master page. VOus remarquerez les trois steps défini dans mon wizzard. Le premier me permet de récupérer entre aure le nombre de textbox que je désire créer à la volée dans le pannel contenu dans le dernier step du wizzard.

    <%@ Page Title="" Language="C#" MasterPageFile="~/Template.Master" AutoEventWireup="true" CodeBehind="Ajouter_Doc.aspx.cs" validateRequest="false" Inherits="Nemesis_project_web.WebForm4" %>
    <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    </asp:Content>
    <asp:Content ID="Content3" ContentPlaceHolderID="Contenu" runat="server">
      <asp:Panel ID="Pan_Add_Video" runat="server">
         <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
      </asp:ToolkitScriptManager>
         <div class="post-169 post type-post status-publish format-standard hentry category-graphic-design category-resources category-web-design tag-brushes tag-collection tag-grunge tag-inspiration tag-resources first">
            <h1 class="post-title">
              Poster un documentaire</h1>
           <asp:Wizard ID="Wizard1" runat="server" ActiveStepIndex="0" 
              onnextbuttonclick="Wizard1_NextButtonClick" 
              onfinishbuttonclick="Wizard1_FinishButtonClick" >
            
             <NavigationButtonStyle BackColor="White" BorderColor="#CC9966" 
               BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em" 
               ForeColor="#990000" />
             <SideBarButtonStyle ForeColor="White" />
             <SideBarStyle BackColor="#813618" VerticalAlign="Top" />
             <WizardSteps>
               <asp:WizardStep ID="wstep_Docu_Meta" runat="server" Title="Informations">
                 Titre<br />
                 <asp:TextBox ID="edt_titre" runat="server" CssClass="textbox"></asp:TextBox>
                 <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" 
                   ControlToValidate="edt_titre" ErrorMessage="*"></asp:RequiredFieldValidator>
                 <br />
                 Description<br />
                 <asp:TextBox ID="edt_description" runat="server" CssClass="textbox" 
                   Height="150" TextMode="MultiLine" Width="100%"></asp:TextBox>
                 <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" 
                   ControlToValidate="edt_description" ErrorMessage="*"></asp:RequiredFieldValidator>
                 <br />
                 Nombre de Parties<br />
                 <asp:TextBox ID="edt_nombre_video" runat="server" CssClass="textbox" 
                   OnTextChanged="edt_nombre_video_TextChanged"></asp:TextBox>
                 <asp:NumericUpDownExtender ID="NumericUpDownExtender1" runat="server" 
                   Minimum="1" TargetControlID="edt_nombre_video" Width="100">
                 </asp:NumericUpDownExtender>
                 <br />
                
               </asp:WizardStep>
               <asp:WizardStep runat="server" Title="Image" ID = "wstep_Docu_image">
               Image<br />
                 <asp:FileUpload ID="FileUpload1" runat="server" CssClass="textbox" />
                 <br />
               </asp:WizardStep>
    
               <asp:WizardStep ID="wstep_Code_video" runat="server" Title="Code video">
                 <asp:Panel ID="Pan_code" runat="server">
                 </asp:Panel>
               </asp:WizardStep>
             </WizardSteps>
    
           </asp:Wizard>
            
          </div>
      </asp:Panel>
      <asp:Panel ID="Pan_Denied_Access" runat="server">
        
      </asp:Panel>
    </asp:Content>
    <asp:Content ID="Content4" ContentPlaceHolderID="user" runat="server">
    </asp:Content>
    
    

    Ci-dessous mon code cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Nemesis_project_web.Nemesis_Service;
    using System.Text;
    
    namespace Nemesis_project_web
    {
      public partial class WebForm4 : System.Web.UI.Page
      {
        private int nbr_video;
        protected void Page_Load(object sender, EventArgs e)
        {
    
          Utilisateur utilisateur = (Utilisateur)Session["utilisateur"];
          if (utilisateur == null)
          {
            Pan_Add_Video.Visible = false;
            Pan_Denied_Access.Visible = true;
          }
          else
          {
            Pan_Add_Video.Visible = true;
            Pan_Denied_Access.Visible = false;
          }
        }
        protected void Page_PreLoad(object sender, EventArgs e)
        {
          //if ((edt_nombre_video.Text) != "")
          //{
          //  if (Wizard1.ActiveStep != wstep_Code_video)
          //  {
          //    for (int cpt = 1; cpt <= int.Parse(edt_nombre_video.Text); cpt++)
          //    {
          //      Pan_code.Controls.Add(new Label { Text = "Code de la Video " + cpt + "<br/>" });
          //      TextBox t = new TextBox { TextMode = TextBoxMode.MultiLine, Height = 100, Width = 400, ID = ("code_video_" + cpt.ToString()) };
          //      Pan_code.Controls.Add(t);
          //      Pan_code.Controls.Add(new Label { Text = "<br/>" });
          //    }
          //  }
          //}
        }
    
    
        protected void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)
        {
          Session["nbr_video"] = int.Parse(edt_nombre_video.Text);      
        }
    
        protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)
        {
          createVideo();
        }
        private void createVideo()
        {
          Nemesis_ServiceClient service = new Nemesis_ServiceClient();
          Video video = new Video();
          video.Titre = edt_titre.Text;
          video.Description = edt_description.Text;
          video.Rating = 0;
          video.Nombre_de_vues = 0;
          video.Status = "waiting";
          video.Date_de_post = DateTime.Now;
          video.UtilisateurID = ((Utilisateur)Session["utilisateur"]).ID;
          video.AdminID = 1;
          if ((FileUpload1.PostedFile != null))
          {
            upload();
            string fn = System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName);
            video.Url_image = ("img\\Video_img") + "\\" + fn;
          }
          else
          {
            video.Url_image = "URL DE LA PHOTO PAR DEFAULT";
          }
          service.insert_video(video);
          Video video_from_Database = service.get_video_by_titre(video.Titre);
          Set_Code_List(video_from_Database.ID);
          service.Close();
    
        }
        protected void upload()
        {
          if ((FileUpload1.PostedFile != null) && (FileUpload1.PostedFile.ContentLength > 0))
          {
            string fn = System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName);
            string SaveLocation = Server.MapPath("img\\Video_img") + "\\" + fn;
            try
            {
              FileUpload1.PostedFile.SaveAs(SaveLocation);
              Response.Write("The file has been uploaded.");
            }
            catch (Exception ex)
            {
              Response.Write("Error: " + ex.Message);
              //Note: Exception.Message returns a detailed message that describes the current exception. 
              //For security reasons, we do not recommend that you return Exception.Message to end users in 
              //production environments. It would be better to put a generic error message. 
            }
          }
          else
          {
            Response.Write("Please select a file to upload.");
          }
        }
        private void Set_Code_List(int ID_Video)
        {
          Nemesis_ServiceClient service = new Nemesis_ServiceClient();
    
          foreach (TextBox t in Pan_code.Controls.OfType<TextBox>())
          {
            service.insert_code(new Code_video { Code = Server.HtmlEncode(t.Text), VideoID = ID_Video });
          }
          //for (int cpt = 1; cpt <= int.Parse(edt_nombre_video.Text); cpt++)
          //{
          //  //TextBox t = new TextBox();
          //  string id_textbox = "code_video_" + cpt.ToString();
          //  string code_video = (Pan_code.FindControl(id_textbox) as TextBox).Text;
            
            
          //  service.insert_code(new Code_video { Code = Server.HtmlEncode(code_video), VideoID = ID_Video });
          //}
    
          service.Close();
        }
        protected override void OnPreInit(EventArgs e)
        {
          base.OnPreInit(e);
          if (Page.IsPostBack)
          {
            if (Session["nbr_video"] != null)
            {
              
                for (int cpt = 1; cpt <= (int)Session["nbr_video"]; cpt++)
                {
                  Pan_code.Controls.Add(new Label { Text = "Code de la Video " + cpt + "<br/>" });
                  TextBox t = new TextBox { TextMode = TextBoxMode.MultiLine, Height = 100, Width = 400, ID = ("code_video_" + cpt.ToString()) };
                  Pan_code.Controls.Add(t);
                  Pan_code.Controls.Add(new Label { Text = "<br/>" });
                }
                Session["nbr_video"] = null;
              
            }
          }
        } 
      }
    }
    

    Vous remarquerez la methode create video qui est appellée sur le finish du wizzard. Cette methode contient elle même une methode Set_Code_List qui elle va parcourir le pannel du dernier step de mon wizzard et y récupérer tout les text box.

    Malheureusement dans mon cas lorsque je crée mes texbox à partir des methodes Wizard1_NextButtonClick ou Page_PreLoad , ces textbox sont bien créés, je peux écrire dedans mais je ne parviens pas à les récupérer dans ma méthode Set_Code_List.

    D'un autre côté, si j'utilise la méthode OnPreInit comme dans le code ci dessus, j'ai une erreur, pas moyen de créer les textbox car dans preinit mon pannel est null.

     

     


    Cédric Yumba
    lundi 18 juillet 2011 16:00
  • Bonjour,

    Votre code avec la création des contrôles TextBox dans Page_PreLoad ne fonctionne pas à cause de cette condition :

     

    if (Wizard1.ActiveStep != wstep_Code_video)

     

    Quand vous cliquez sur le bouton “Finish” Wizard1.ActiveStep est wstep_Code_video et les TextBoxes ne sont pas créés, donc vous ne pouvez pas récupérer leurs valeurs, car ils n’existent pas. J’ai teste le code après supprimer cette condition et j’ai obtenu le bon résultat.

     

    Cordialement,

    Cipri


    Suivez MSDN sur Twitter   Suivez MSDN sur Facebook


    Ciprian DUDUIALA, MSFT  
    •Nous vous prions de considérer que dans le cadre de ce forum on n’offre pas de support technique et aucune garantie de la part de Microsoft ne peut être offerte.

    • Marqué comme réponse cced mardi 19 juillet 2011 15:43
    mardi 19 juillet 2011 07:56
  • Effectivement, le code fonctionne désormais après avoir retiré le code indiqué, c'est donc bien la méthode prelod que je devais utiliser. 
    Merci encore pour votre aide Ciprian 
    Cédric Yumba
    mardi 19 juillet 2011 15:43