2010-11-03 47 views
5

Ich möchte eine Steuerung erstellen, mit der Benutzer ihre eigene Website-Struktur entwerfen können. Ich stellte mir vor, dass innerhalb UpdatePanel ist Kontrolle (n) mit TextBox (für Seitenname) und Button "unten hinzufügen". Es wäre wie folgt aussieht:Dynamisch erstellte Steuerelemente in UpdatePanel?

| "Questions" | 
| [ add below ] | 

|  "Tags" | 
| [ add below ] | 

| "Badges" | 
| [ add below ] | 

jetzt, wenn Benutzer klicken Sie auf die Schaltfläche in „Variablen“ Element dort neu erscheinen soll, zwischen „Variablen“ und „Badges“, mit editierbaren Namen, so Benutzer es nennen kann „Benutzer“ beispielsweise. Es sollte ohne vollständige Postback (um Seitenblinker zu vermeiden) getan werden.

Jetzt ist mein Problem: Ich kann diese Steuerelemente (zuletzt nicht alle) in OnInit nicht laden, da sie nicht existieren, aber ich muss auf ihr click-Ereignis achten, also sollte ich Ereignis-Listener anhängen, was während Init getan werden sollte Phase. Wie erreiche ich die beschriebene Funktionalität?

Ich spielte zu viel herum und ich bin verwirrt. Ich wäre dankbar für irgendwelche Tipps.

Antwort

12

Dies ist eine knifflige Situation, da Sie mit dynamischen Steuerelementen arbeiten, die Sie auf Seiteninit füllen müssen, um Viewstate persistent zu machen, auch Ereignisse für Steuerelemente ad ded in einem Aktualisierungsbereich während Schaltflächenklicks werden erst beim nächsten Postback registriert, sodass das normale Schaltflächenklickereignis nur einmal jedes Mal ausgelöst wird, wenn Sie auf ein neu hinzugefügtes Steuerelement klicken. Es könnte einen anderen Weg geben, dies zu umgehen, als ich es getan habe. Wenn jemand weiß, würde ich gerne herausfinden.

Meine Lösung besteht darin, eine Liste dessen, was Sie dynamisch hinzugefügt haben, zu behalten und in einer Sitzungsvariablen zu speichern (weil der Viewstatus nicht während der Seiteninitialisierung geladen wird). Laden Sie dann auf der Seite alle Steuerelemente, die Sie zuvor hinzugefügt haben. Behandeln Sie dann das Klickereignis während des Ladens der Seite mit einem benutzerdefinierten Code oder mit dem normalen Klickereignis.

Ich habe eine Beispielseite erstellt, um dies zu testen. Hier

ist der Code für die aspx Seite (default.aspx):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 

<!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 id="Head1" runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> 
    <p>This only updates on full postbacks: <%= DateTime.Now.ToLongTimeString() %></p> 
    <asp:UpdatePanel ID="UpdatePanel1" runat="server"> 
     <ContentTemplate> 
      <asp:PlaceHolder ID="PlaceholderControls" runat="server"></asp:PlaceHolder> 
     </ContentTemplate> 
    </asp:UpdatePanel> 
    </form> 
</body> 
</html> 

Und hier ist der Code für die Code-Behind-Seite (default.aspx.cs):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

public partial class _Default : System.Web.UI.Page 
{ 
    /// <summary> 
    /// this is a list for storing the id's of dynamic controls 
    /// I have to put this in the session because the viewstate is not 
    /// loaded in the page init where we need to use it 
    /// </summary> 
    public List<string> DynamicControls 
    { 
     get 
     { 
      return (List<string>)Session["DynamicControls"]; 
     } 
     set 
     { 
      Session["DynamicControls"] = value; 
     } 
    } 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     PlaceholderControls.Controls.Clear(); 

     //add one button to top that will cause a full postback to test persisting values-- 
     Button btnFullPostback = new Button(); 
     btnFullPostback.Text = "Cause Full Postback"; 
     btnFullPostback.ID = "btnFullPostback"; 
     PlaceholderControls.Controls.Add(btnFullPostback); 

     PlaceholderControls.Controls.Add(new LiteralControl("<br />")); 

     PostBackTrigger FullPostbackTrigger = new PostBackTrigger(); 
     FullPostbackTrigger.ControlID = btnFullPostback.ID; 

     UpdatePanel1.Triggers.Add(FullPostbackTrigger); 
     //----------------------------------------------------------------------- 




     if (!IsPostBack) 
     { 
      //add the very first control   
      DynamicControls = new List<string>(); 

      //the DynamicControls list will persist because it is in the session 
      //the viewstate is not loaded yet 
      DynamicControls.Add(AddControls(NextControl)); 

     } 
     else 
     { 
      //we have to reload all the previously loaded controls so they 
      //will have been added to the page before the viewstate loads 
      //so their values will be persisted 
      for (int i = 0; i < DynamicControls.Count; i++) 
      { 
       AddControls(i); 
      } 
     } 


    } 

    protected void Page_Load(object sender, EventArgs e) 
    { 

     if (!IsPostBack) 
     { 
      //we have to increment the initial 
      //control count here here be cause we cannot persit data in the viewstate during 
      //page init 

      NextControl++; 

     } 
     else 
     { 
      HandleAddNextClick();   

     } 

    } 

    /// <summary> 
    /// this function looks to see if the control which caused the postback was one of our 
    /// dynamically added buttons, we have to do this because the update panel seems to interefere 
    /// with the event handler registration. 
    /// </summary> 
    private void HandleAddNextClick() 
    { 
     //did any of our dynamic controls cause the postback if so then handle the event 
     if (Request.Form.AllKeys.Any(key => DynamicControls.Contains(key))) 
     { 
      DynamicControls.Add(AddControls(NextControl)); 
      NextControl++; 
     } 
    } 



    protected void btnAddNext_Command(object sender, CommandEventArgs e) 
    { 
     //this is intentionally left blank we are handling the click in the page load 
     //because the event for controls added dynamically in the click does 
     //not get registered until after a postback, so we have to handle it 
     //manually. I think this has something to do with the update panel, as it works 
     //when not using an update panel, there may be some other workaround I am not aware of 

    } 

    /// <summary> 
    /// variable for holding the number of the next control to be added 
    /// </summary> 
    public int NextControl 
    { 
     get 
     { 
      return ViewState["NextControl"] == null ? 0 : (int)ViewState["NextControl"]; 
     } 
     set 
     { 
      ViewState["NextControl"] = value; 
     } 
    } 


    /// <summary> 
    /// this function dynamically adds a text box, and a button to the placeholder 
    /// it returns the UniqueID of the button, which is later used to find out if the button 
    /// triggered a postback 
    /// </summary> 
    /// <param name="ControlNumber"></param> 
    /// <returns></returns> 
    private string AddControls(int ControlNumber) 
    { 
     //add textbox 
     TextBox txtValue = new TextBox(); 
     txtValue.ID = "txtValue" + ControlNumber; 
     PlaceholderControls.Controls.Add(txtValue); 

     //add button 
     Button btnAddNext = new Button(); 
     btnAddNext.Text = "Add Control " + ControlNumber; 
     btnAddNext.ID = "btnAddNext" + ControlNumber; 
     int NextControl = ControlNumber + 1; 
     btnAddNext.CommandArgument = NextControl.ToString(); 

     btnAddNext.Command += new CommandEventHandler(btnAddNext_Command); 
     PlaceholderControls.Controls.Add(btnAddNext); 

     //add a line break 
     PlaceholderControls.Controls.Add(new LiteralControl("<br />")); 

     return btnAddNext.UniqueID; 

    }  
} 

Lassen Sie mich wissen, ob Ihnen dieser Code hilft. Ich habe versucht, Kommentare zu meinem Verständnis von dem, was vor sich geht und wie es funktioniert, hinzuzufügen.

+0

laden nach der Arbeit überprüfen und geben Ihnen mehr Feedback. Vielen Dank für die Probe, auch wenn ich nicht danach gefragt habe! – zgorawski

+0

Funktioniert wie ein Charme :) Ich vergaß/wusste nicht über einige Funktionen, die Sie verwendet, so dass meine Lösung unvollständig war. Danke vielmals! Sie haben mir sehr geholfen :) – zgorawski

+0

froh, dass ich helfen konnte, ich wünschte, es gäbe einen Weg, es ohne die Sitzung zu tun, aber ich kenne keine andere einfache Möglichkeit, Informationen zu speichern und abzurufen, bevor der Viewstate geladen wird. Sie könnten wahrscheinlich versteckte Felder oder Cookies verwenden, aber diese scheinen sogar Ideen zu tragen. Vielleicht gibt es eine Möglichkeit, den Viewstate manuell zu laden und in der Seiteninitialisierung zu verwenden. –

-1

Wenn Sie dynamische Eventhandler für Steuerelemente möchten, dann können Sie dies versuchen -

ein Button-Steuerelement Unter Berücksichtigung

Button btnTest = new Button(); 
btnTest .Click += new EventHandler(btnTest_Click); 

Sie Ihren Code in der Schaltfläche Click-Ereignis haben kann,

void btnTest_Click(object sender, EventArgs e) 
{ 
    //your code 
} 
0

für mich diese Weise arbeiten

protected void Page_Load(object sender, EventArgs e) 
    { 
     if (Page.IsPostBack) 
     { 
      Button_Click(null, null); 
     } 
    } 

In Ruftaste

protected void Button_Click(object sender, EventArgs e) 
    { 
      Panel1.Controls.Clear(); 
      this.YourMethod(); 
     } 
    } 

Bevor Sie die Methode löschen sonst die Kontrolle nennen wird es Ihnen auf jeden Fall Lösung, die ich zweimal

Verwandte Themen