2015-06-16 3 views
26

I, wie der Wert dynamisch bevölkerten Kontrollen bekommen

<div id="divNameofParticipants" runat="server"> 
    <asp:Panel ID="panelNameofParticipants" runat="server"> 
    </asp:Panel> 
</div> 

Ich bin Bestücken der Platte dynamisch aus Code-Behind mit dem folgenden Code conatining ein Panel in aspx Seite ein div haben: Jetzt

void btnSubmitCountParticipant_Click(object sender, EventArgs e) 
    { 
     StringBuilder sbparticipantName=new StringBuilder(); 

     try 
     { 
      int numberofparticipants = Convert.ToInt32(drpNoofparticipants.SelectedValue); 
      ViewState["numberofparticipants"] = numberofparticipants; 
      Table tableparticipantName = new Table(); 
      int rowcount = 1; 
      int columnCount = numberofparticipants; 
      for (int i = 0; i < rowcount; i++) 
      { 
       TableRow row = new TableRow(); 
       for (int j = 0; j < columnCount; j++) 
       { 
        TableCell cell = new TableCell(); 
        TextBox txtNameofParticipant = new TextBox(); 
        txtNameofParticipant.ID = "txtNameofParticipant" + Convert.ToString(i); 
        cell.ID = "cell" + Convert.ToString(i); 
        cell.Controls.Add(txtNameofParticipant); 
        row.Cells.Add(cell); 


       } 
       tableparticipantName.Rows.Add(row); 
       panelNameofParticipants.Controls.Add(tableparticipantName); 

      } 

     } 
     catch(Exception ex) 
     { 


     } 
    } 

Ich möchte auf den Wert dieser dynamisch generierten Textbox im Codebehind zugreifen. Für den i ist mein Code wie folgt:

aber ich bin nicht in der Lage, die Werte im Codebehind zu erhalten.

TextBox txtParticipantName = (TextBox)panelNameofParticipants.FindControl(findcontrol); 

der obige Code ist auch nicht in der Lage, die Kontrolle und es ist immer zu finden null geben .Was mache ich wrong.i die Steuerelemente im Laden der Seite neu erstellt, da Postbacks staatenlos ist, aber immer noch kein Erfolg.

Vielen Dank im Voraus

+7

das Problem auf die Erstellung dynamischer Kontrollen in Server-Seite ist müssen Sie sie auf jeder Seite Initialisierung neu erstellen, wenn im nicht wron g, OnInit-Methode. – Sherlock

+0

sind Sie offen für etwas wie die Gridview? es wird Ihnen eine Last von Codierung sparen – naveen

+0

Dies könnte helfen: http://geekswithblogs.net/shahed/archive/2008/06/26/123391.aspx – sr28

Antwort

5

Wenn Sie eine DataPresentation Kontrolle wie asp:GridView wird es viel einfacher sein.

Markup

<asp:GridView ID="ParticipantsGrid" runat="server" AutoGenerateColumns="false"> 
    <Columns> 
     <asp:TemplateField HeaderText="Participants"> 
      <ItemTemplate> 
       <asp:TextBox ID="txtNameofParticipant" runat="server" 
        Text='<%# Container.DataItem %>'> 
       </asp:TextBox> 
      </ItemTemplate> 
     </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

-Code-behind

protected void btnSubmitCountParticipant_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     var selectedParticipantCount = Convert.ToInt32(drpNoofparticipants.SelectedValue); 
     var items = Enumerable.Repeat(string.Empty, selectedParticipantCount).ToList(); 
     ParticipantsGrid.DataSource = items; 
     ParticipantsGrid.DataBind(); 
    } 
    catch (Exception ex) 
    { } 
} 
public void CreateControls() 
{ 

    try 
    { 
     var participants = ParticipantsGrid.Rows 
      .Cast<GridViewRow>() 
      .Select(row => ((TextBox)row.FindControl("txtNameofParticipant")).Text) 
      .ToList(); 
    } 
    catch (Exception ex) 
    { } 
} 
7

Sie dynamische Steuerelemente in PreInit nicht in OnLoad erstellen müssen. Siehe Dokumentation hier: https://msdn.microsoft.com/en-us/library/ms178472.aspx

Re/Das Erstellen der Steuerelemente beim Laden der Seite bewirkt, dass ViewState nicht an die Steuerelemente gebunden wird, da die Bindung des Ansichtsstatus vor OnLoad erfolgt.

+0

Dynamische Steuerelemente sollten in LoadViewState, nicht in PreInit, Init oder Laden erstellt werden. Sie haben keinen Zugriff auf den Ansichtszustand aus der vorherigen Anforderung in PreInit und Init. –

+0

Nein, sie sollten zuvor erstellt werden. Wenn der Ladezustand angezeigt wird, können die Steuerelemente automatisch an den Ansichtszustand gebunden werden. Siehe Microsoft-eigene Dokumentation in dem bereitgestellten Link. –

+0

Die Dokumentation ist falsch: Die integrierten datengebundenen ASP.NET-Steuerelemente erstellen dynamische Steuerelemente in LoadViewState neu. (Die LoadViewState-Methode eines übergeordneten Steuerelements wird aufgerufen, bevor der Ansichtszustand für untergeordnete Steuerelemente geladen wird.) –

3

Dynamische Steuerelemente müssen für jedes Post-Back neu erstellt werden. Der einfachste Weg, dies in Ihrem Code zu erreichen, wäre, die Kontrollstruktur zwischenzuspeichern und neu zu füllen. Diese, wie es getan werden kann:

void btnSubmitCountParticipant_Click(object sender, EventArgs e) 
{ 
    StringBuilder sbparticipantName=new StringBuilder(); 
    Panel p1 = new Panel(); 

    try 
    { 
     int numberofparticipants = Convert.ToInt32(drpNoofparticipants.SelectedValue); 
     ViewState["numberofparticipants"] = numberofparticipants; 
     Table tableparticipantName = new Table(); 
     int rowcount = 1; 
     int columnCount = numberofparticipants; 
     for (int i = 0; i < rowcount; i++) 
     { 
      TableRow row = new TableRow(); 
      for (int j = 0; j < columnCount; j++) 
      { 
       TableCell cell = new TableCell(); 
       TextBox txtNameofParticipant = new TextBox(); 
       txtNameofParticipant.ID = "txtNameofParticipant" + Convert.ToString(i); 
       cell.ID = "cell" + Convert.ToString(i); 
       cell.Controls.Add(txtNameofParticipant); 
       row.Cells.Add(cell); 


      } 
      tableparticipantName.Rows.Add(row); 
      p1.Controls.Add(tableparticipantName); 
     } 
     Cache["TempPanel"] = p1; 
     panelNameofParticipants.Controls.Add(p1); 

    } 
    catch(Exception ex) 
    { 


    } 
} 

Suchen Sie nach dem p1-Panel in dem obigen Code, um die Änderungen zu sehen. Nun der Code für die Funktion Create müssen wie folgt geändert werden:

public void CreateControls() 
{ 

    try 
    { 

     Panel p1= (Panel)Cache["TempPanel"]; 
     panelNameofParticipants.Controls.Add(p1); 

     //String test1 = test.Value; 
     List<string> listParticipantName = new List<string>(); 
     if (ViewState["numberofparticipants"] != null) 
     { 
      int numberofparticipants = Convert.ToInt32(ViewState["numberofparticipants"]); 
      for (int i = 0; i < numberofparticipants; i++) 
      { 
       string findcontrol = "txtNameofParticipant" + i; 
       TextBox txtParticipantName = (TextBox)panelNameofParticipants.FindControl(findcontrol); 
       listParticipantName.Add(txtParticipantName.Text); 

      } 
     } 
    } 
    catch (Exception ex) 
    { 

    } 
} 

Hoffnung, das hilft.

4

Ich denke, dass Sie das richtig machen. In asp.net Webforms, gibt es viele Male, dass Sie seltsame Dinge erlebt haben, die passieren. Vor allem mit dem Vorhandensein von ViewState. Zuerst müssen wir unseren Code untersuchen und verschiedene Tests und Ansätze ausprobieren. Das wird mein Rat für Sie, verwenden Bitten diesen Code und Debug wenn das, was wirklich passiert:

void btnSubmitCountParticipant_Click(object sender, EventArgs e) 
{ 
    StringBuilder sbparticipantName=new StringBuilder(); 

    try 
    { 
     int numberofparticipants = Convert.ToInt32(drpNoofparticipants.SelectedValue); 
     ViewState["numberofparticipants"] = numberofparticipants; 
     Table tableparticipantName = new Table(); 
     int rowcount = 1; 
     int columnCount = numberofparticipants; 

     TableRow row = new TableRow(); 
     TableCell cell = new TableCell(); 
     TextBox txtNameofParticipant = new TextBox(); 
     txtNameofParticipant.ID = "NameTest"; 
     txtNameofParticipant.Text = "This is a textbox"; 
     cell.ID = "cellTest"; 
     cell.Controls.Add(txtNameofParticipant); 
     row.Cells.Add(cell); 

     tableparticipantName.Rows.Add(row); 
     panelNameofParticipants.Controls.Add(tableparticipantName); 

    } 
    catch(Exception ex) 
    { // please put a breakpoint here, so that we'll know if something occurs, 
    } 
} 


public void CreateControls() 
{ 
    try 
    { 
     //String test1 = test.Value; 
     List<string> listParticipantName = new List<string>(); 
     //if (ViewState["numberofparticipants"] != null) 
     //{ 
     string findcontrol = "NameTest"; 
     TextBox txtParticipantName = (TextBox)panelNameofParticipants.Controls["NameText"]; 
     //check if get what we want. 
     listParticipantName.Add(txtParticipantName.Text); 
     //} 
    } 
    catch (Exception ex) 
    {// please put a breakpoint here, so that we'll know if something occurs, 
    } 
} 
1

dynamisch erstellte Steuerelemente verschwinden würde, wenn Seite Beiträge zurück, dieser Artikel here erklärt, warum es passiert.

Also, um dynamische Steuerelemente von asp.net-Seite erkannt werden, müssen Sie es in preinit Event-Handler neu erstellen, aber ich denke, es ist schwierig, da diese dynamischen Steuerelemente in Ihrem Fall auf ein anderes Webformular-Element wie Als DropDownlist ist drpNoofparticipants und auch ViewState zu diesem Zeitpunkt nicht verfügbar.

Mein Vorschlag ist, dass wir es auf eine andere Weise tun, jeder Post zurück ist eigentlich ein Formular Post, also anstatt das dynamische Textfeld zu finden, können Sie den Wert direkt über Request.Form Sammlung. Hier ist der Code-Schnipsel:

 var list = Request.Form.AllKeys.Where(x => x.Contains("txtNameofParticipant")); 
     foreach (var item in list) 
     { 
      var value = Request.Form[item]; 
     } 

Auf diese Weise können Sie den Wert bekommen und da Sie nicht auf ASP.NET Motor verlassen müssen, um den Wert von dynamisch erstellten Steuerung abzurufen, können Sie die Erschaffungs verschieben könnte die Tabelle im Ereignishandler page_load.

Ich hoffe, es hilft.

1

Setzen Sie Ihre btnSubmitCountParticipant_Click Methode, um Daten in andere Funktion mit dem Namen Ihrer Wahl. Rufen diese Funktion in btnSubmitCountParticipant_Click Verfahren und in Verfahren Create(). Auch schneiden die Code unten in btnSubmitCountParticipant_Click Methode Paste

int numberofparticipants = Convert.ToInt32 (drpNoofparticipants.SelectedValue); Viewstate [ "numberofparticipants"] = numberofparticipants;

. Dies funktioniert in meiner Maschine. Hoffe, das hilft

-1

Ich bin mir nicht sicher, ob dies gewünscht wird, aber Sie fügen mehrere Tabellen zu Ihrem Panel, aber ich denke, dass Sie nur eine Tabelle wollen/müssen. Also diese Zeile sollte wie so außerhalb der äußeren for-Schleife sein:

for (int i = 0; i < rowcount; i++) 
{ 
    TableRow row = new TableRow(); 
    for (int j = 0; j < columnCount; j++) 
    { 
      TableCell cell = new TableCell(); 
      TextBox txtNameofParticipant = new TextBox(); 
      txtNameofParticipant.ID = "txtNameofParticipant" + Convert.ToString(i); 
      cell.ID = "cell" + Convert.ToString(i); 
      cell.Controls.Add(txtNameofParticipant); 
      row.Cells.Add(cell); 
    } 
    tableparticipantName.Rows.Add(row); 
} 

panelNameofParticipants.Controls.Add(tableparticipantName); 

Zusätzlich wird Findcontrol nur die direkten Kinder des Behälters suchen, in diesem Fall ist es nur die Tabelle finden, sonst wird es null zurück. Sie müssen also Kinder des Panels suchen, um das Steuerelement zu finden, z. Tisch:

foreach (TableRow row in tableparticipantName.Rows) 
{ 
    TextBox txtParticipantName = (TextBox)row.FindControl(findcontrol); 
    listParticipantName.Add(txtParticipantName.Text); 
} 

Wenn das nicht funktioniert, dann tut es besser rekursiv funktionieren könnte: ASP.NET Is there a better way to find controls that are within other controls?

1

Ja, dynamische Kontrollen in Postbacks verloren, also müssen wir in Viewsate und wieder dynamische Steuerwerte speichern erzeugen dynamische control.I hinzugefügt Code hier, das adaequat

//Create Button Dynamic Control 
      protected void btnDyCreateControl_Click(object sender, EventArgs e) 
        { 

         try 
         { 
          int numberofparticipants = 5; 
          ViewState["numberofparticipants"] = numberofparticipants; 
          int test = (int)ViewState["numberofparticipants"]; 
          int rowcount = 1; 
          int columnCount = numberofparticipants; 
          CreateDynamicTable(rowcount, columnCount); 


         } 
         catch (Exception ex) 
         { 


         } 
        } 
       //submit values 
      protected void btnSave_Click(object sender, EventArgs e) 
       { 
        try 
       { 

        List<string> listParticipantName = new List<string>(); 
        if (ViewState["numberofparticipants"] != null) 
        { 
         int numberofparticipants = Convert.ToInt32(ViewState["numberofparticipants"]); 

          foreach (Control c in panelNameofParticipants.Controls) 
          { 
           if (c is Table) 
           { 
            foreach (TableRow row in c.Controls) 
            { 
             int i = 0; 
             foreach (TableCell cell in row.Controls) 
             { 

              if (cell.Controls[0] is TextBox) 
              { 
               string findcontrol = "txtNameofParticipant" + i; 
               TextBox txtParticipantName = (TextBox)cell.Controls[0].FindControl(findcontrol); 
               listParticipantName.Add(txtParticipantName.Text); 

              } 
              i++; 

             } 


            } 
           } 
          } 

        } 
       } 
       catch (Exception ex) 
       { 

       } 
       } 

       //Save ViewState 
     protected override object SaveViewState() 
       { 
        object[] newViewState = new object[3]; 

        List<string> txtValues = new List<string>(); 
        foreach (Control c in panelNameofParticipants.Controls) 
        { 
         if (c is Table) 
         { 
          foreach (TableRow row in c.Controls) 
          { 
           foreach (TableCell cell in row.Controls) 
           { 
            if (cell.Controls[0] is TextBox) 
            { 
             txtValues.Add(((TextBox)cell.Controls[0]).Text); 
            } 
           } 
          } 
         } 
        } 

        newViewState[0] = txtValues.ToArray(); 
        newViewState[1] = base.SaveViewState(); 
        if (ViewState["numberofparticipants"] != null) 
         newViewState[2] = (int)ViewState["numberofparticipants"]; 
        else 
         newViewState[2] = 0; 
        return newViewState; 
       } 
    //Load ViewState 

    protected override void LoadViewState(object savedState) 
      { 
       //if we can identify the custom view state as defined in the override for SaveViewState 
       if (savedState is object[] && ((object[])savedState).Length == 3 && ((object[])savedState)[0] is string[]) 
       { 
        object[] newViewState = (object[])savedState; 
        string[] txtValues = (string[])(newViewState[0]); 
        if (txtValues.Length > 0) 
        { 
         //re-load tables 
         CreateDynamicTable(1, Convert.ToInt32(newViewState[2])); 
         int i = 0; 
         foreach (Control c in panelNameofParticipants.Controls) 
         { 
          if (c is Table) 
          { 
           foreach (TableRow row in c.Controls) 
           { 
            foreach (TableCell cell in row.Controls) 
            { 
             if (cell.Controls[0] is TextBox && i < txtValues.Length) 
             { 
              ((TextBox)cell.Controls[0]).Text = txtValues[i++].ToString(); 

             } 
            } 
           } 
          } 
        } 
        } 
        //load the ViewState normally 
        base.LoadViewState(newViewState[1]); 
       } 
       else 
       { 
        base.LoadViewState(savedState); 

       } 
      } 
//Create Dynamic Control 

public void CreateDynamicTable(int rowcount, int columnCount) 
     { 
      Table tableparticipantName = new Table(); 

      for (int i = 0; i < rowcount; i++) 
       { 
        TableRow row = new TableRow(); 
        for (int j = 0; j < columnCount; j++) 
        { 
         TableCell cell = new TableCell(); 

         TextBox txtNameofParticipant = new TextBox(); 
         txtNameofParticipant.ID = "txtNameofParticipant" + Convert.ToString(j); 
         cell.ID = "cell" + Convert.ToString(j); 
         cell.Controls.Add(txtNameofParticipant); 
         row.Cells.Add(cell); 
        } 
        tableparticipantName.Rows.Add(row); 
        tableparticipantName.EnableViewState = true; 
        ViewState["tableparticipantName"] = true; 
     } 
      panelNameofParticipants.Controls.Add(tableparticipantName); 
     } 

Referenz Link, MSDN Link, hofft, dass es hilft.

1

Wenn Ihre Textfelder zu schaffen machen, dass Sie die ClientIDMode setze ich auf etwas vor kurzem arbeitete ähnlich. Ich habe Checkboxen in GridView-Zeilen dynamisch erstellt und es hat für mich funktioniert.

TextBox txtNameofParticipant = new TextBox(); 
txtNameofParticipant.ID = "txtNameofParticipant" + Convert.ToString(i); 
txtNameOfParticipant.ClientIDMode = System.Web.UI.ClientIDMode.Static; 
6

Wie von anderen Personen erwähnt. Um dynamische Steuerelemente zu erstellen, müssen Sie dies für jeden Postback und zur richtigen Zeit tun. Um dynamische Steuerelemente zu machen, verwenden Sie die PreInit Ereignis. Ich schlage vor, dass Ihr einen Blick auf https://msdn.microsoft.com/en-us/library/ms178472(v=vs.80).aspx haben, um mehr darüber zu erfahren.

MSDN - PreInit: Verwenden Sie dieses Ereignis für die folgenden: Überprüfen Sie die IsPostBack Eigenschaft, um zu bestimmen, ob dies das erste Mal ist die Seite bearbeitet wird. Erstellen oder erstellen Sie dynamische Steuerelemente neu. Legen Sie eine Masterseite dynamisch fest. Legen Sie die Design-Eigenschaft dynamisch fest. Lesen oder Festlegen von Profileigenschaftswerten. NoteNote Wenn es sich bei der Anforderung um ein Postback handelt, wurden die Werte der Steuerelemente aus dem Ansichtszustand noch nicht wiederhergestellt. Wenn Sie zu diesem Zeitpunkt eine Steuerelementeigenschaft festlegen, wird ihr Wert möglicherweise beim nächsten Ereignis überschrieben.

Die nächste interessante Veranstaltung ist Preload, die besagt:

MSDN - PreLoad Verwenden Sie dieses Ereignis, wenn Sie die Verarbeitung auf Ihrer Seite oder die Kontrolle vor dem Load-Ereignis ausführen müssen. Nachdem die Seite dieses Ereignis ausgelöst hat, lädt sie den Ansichtszustand für sich selbst und alle Steuerelemente und verarbeitet dann alle Postback-Daten, die in der Request-Instanz enthalten sind.

Was bedeutet, dass in der nächsten Veranstaltung Load (Page_Load) der Ansichtszustand geladen werden soll, hier also sollten Sie effektiv in der Lage sein, Ihre Werte zu überprüfen.

Sie müssen auch sicherstellen, dass Ansichtszustand aktiviert ist und die einfachste ist wahrscheinlich in der Seitenebene Richtlinie:

<%@Page EnableViewState="True" %> 

Werfen Sie einen Blick auf den Artikel https://msdn.microsoft.com/en-us/library/ms972976.aspx2, die mehr in die Tiefe alles geht

Hinweis

Wenn Ihr Problem ist, dass Sie Steuerelemente dynamisch auf eine Schaltfläche klicken erstellen müssen, und es wird viele Kontrollen c sein Sie sollten wahrscheinlich zu jQuery ajax wechseln und das Attribut [WebMethod] für eine öffentliche Funktion in Ihrem Code verwenden. Das Erstellen dynamischer Steuerelemente und das Beibehalten des ViewState ist ziemlich kostspielig, also empfehle ich es wirklich, für eine bessere Benutzererfahrung.

1

Dynamisch hinzugefügte Steuerelemente müssen beim Postback neu erstellt werden, andernfalls geht der Status der dynamisch hinzugefügten Steuerelemente verloren (wenn die Steuerelemente verloren haben, kann der alte Zustand beibehalten werden). Jetzt die Frage. Wann wird der Viewstate geladen? Es wird zwischen den beiden Ereignissen Page_Init und Load geladen.

folgenden Codebeispiele sind ein wenig Modifikation des Codes für Ihr Verständnis

Die aspx Markup gleiche wie Sie, aber mit einigen zusätzlichen Kontrollen

<form id="form1" runat="server"> 
    <asp:DropDownList ID="drpNoofparticipants" runat="server" > 
     <asp:ListItem>1</asp:ListItem> 
     <asp:ListItem>2</asp:ListItem> 
     <asp:ListItem>3</asp:ListItem> 
     <asp:ListItem>4</asp:ListItem> 
     <asp:ListItem>5</asp:ListItem> 
     <asp:ListItem>6</asp:ListItem> 
     <asp:ListItem>7</asp:ListItem> 
     <asp:ListItem>8</asp:ListItem> 
     <asp:ListItem>9</asp:ListItem> 
     <asp:ListItem>10</asp:ListItem> 
    </asp:DropDownList> 
    <br /><asp:Button ID="btnCreateTextBoxes" runat="server" OnClick="btnSubmitCountParticipant_Click" Text="Create TextBoxes" /> 
    <div id="divNameofParticipants" runat="server"> 
     <asp:Panel ID="panelNameofParticipants" runat="server"> 
     </asp:Panel> 
    </div> 
    <div> 
     <asp:Button ID="btnSubmitParticipants" runat="server" Text="Submit the Participants" OnClick="BtnSubmitParticipantsClicked" /> 
    </div> 
</form> 

auf Click-Ereignis der btnCreateTextBoxes Taste Ich erstelle die Kontrollen unter Verwendung des folgenden Codes

Wie oben erwähnt den Steuerzustand aufrechtzuerhalten, i die Neuschöpfung der Kontrollen auf der Seite Load-Ereignis auf dem Ansichtszustand [ „numberofparticipants“]

protected void Page_Load(object sender, EventArgs e) 
    { 
     if (ViewState["numberofparticipants"] != null) 
     { 
      CreateTheControlsAgain(Convert.ToInt32(ViewState["numberofparticipants"])); 
      CreateControls(); 

     } 

    } 

auf Click-Ereignis von btnSubmitParticipants Schaltfläche basierend enthalten schrieb ich das folgende Ereignis und Schreiben die Teilnehmer-Namen an die Konsole

try 
     { 
      //String test1 = test.Value; 
      List<string> listParticipantName = new List<string>(); 
      if (ViewState["numberofparticipants"] != null) 
      { 
       int numberofparticipants = Convert.ToInt32(ViewState["numberofparticipants"]); 
       for (int i = 0; i < numberofparticipants; i++) 
       { 
        string findcontrol = "txtNameofParticipant" + i; 
        var txtParticipantName = panelNameofParticipants.FindControl(string.Format("txtNameofParticipant{0}", i)) as TextBox; 
        listParticipantName.Add(txtParticipantName.Text); 

       } 
      } 
      foreach (var item in listParticipantName) 
      { 
       Response.Write(string.Format("{0}<br/>", item)); 
      } 
     } 
     catch (Exception ex) 
     { 

     } 

hoffe, das hilft

Verwandte Themen