2010-11-03 2 views
5

Я хочу создать элемент управления, который позволит пользователю создавать собственную структуру веб-сайта. Я предположил, что внутри UpdatePanel есть элемент управления с TextBox (для названия страницы) и Button «добавить ниже». Это будет выглядеть так:Динамические созданные элементы управления внутри UpdatePanel?

| "Questions" | 
| [ add below ] | 

|  "Tags" | 
| [ add below ] | 

| "Badges" | 
| [ add below ] | 

теперь, когда пользователь нажимает на кнопку в элементе «Метки» должен появиться новый, между «Теги» и «Значки», с редактируемой именем, так что пользователь может назвать его «Пользователи» например. Это должно быть сделано без полной обратной передачи (чтобы избежать мигания страницы).

Теперь моя проблема: я не могу загрузить эти элементы управления (наконец, не все из них) в onInit, так как они не существуют, но я должен следить за их клик-событием, поэтому я должен подключить прослушиватель событий, что должно быть сделано во время Init фаза. Как достичь описанной функциональности?

Я играл вокруг него слишком много времени, и я смущен. Я был бы благодарен за любые советы.

ответ

12

Это сложная ситуация, потому что вы имеете дело с динамическими элементами управления, которые вам нужно заполнить в начале страницы, чтобы сохранить статус просмотра, а также события для элементов управления. выведенные внутри панели обновления во время нажатия кнопки, похоже, не регистрируются до следующей обратной передачи, поэтому обычное событие нажатия кнопки запускается только один раз, когда вы нажимаете на новый добавленный элемент управления. Возможно, есть какой-то другой способ обойти это, чем то, как я это сделал. Если кто-нибудь знает, что я хотел бы узнать.

Мое решение состоит в том, чтобы сохранить список того, что вы добавили динамически, и сохранить его в переменной сеанса (поскольку во время запуска страницы не отображается окно просмотра). Затем на странице init загрузите все элементы управления, которые вы ранее добавили. Затем обработайте событие click во время загрузки страницы с помощью какого-либо специального кода или обычного события click.

Я создал образец страницы, чтобы помочь проверить это.

Вот код страницы ASPX (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> 

А вот код для кода позади страницы (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; 

    }  
} 

Дайте мне знать, поможет ли вам этот код. Я попытался добавить комментарии с моим пониманием того, что происходит и как это работает.

+0

Я обязательно проверить Yours решение после работы и дать вам больше отзывов. Большое спасибо за образец, даже если я не просил об этом! – zgorawski

+0

Работает как шарм :) Я забыл/не знал о нескольких функциях, которые вы использовали, поэтому мое решение было неполным. Большое спасибо! Вы мне очень помогли :) – zgorawski

+0

рад, что я мог бы помочь, я бы хотел, чтобы был способ сделать это, не используя сеанс, но я не знаю ни о каком другом простом способе хранить и извлекать информацию перед загрузкой viewstate. Вероятно, вы могли бы использовать скрытые поля или куки-файлы, но они, похоже, даже носили идеи. Возможно, есть способ загрузить окно просмотра вручную и использовать его в странице init. –

-1

Если вы хотите динамические eventhandlers для элементов управления, то вы можете попробовать это -

Учитывая кнопку управления,

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

Вы можете иметь свой код в случае нажатия кнопки,

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

Этот способ работает для меня

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

В кнопку вызова

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

Перед тем, как вызвать метод очистки контроль в противном случае она будет загружаться в два раза

Смежные вопросы