代码之家  ›  专栏  ›  技术社区  ›  zgorawski

在更新面板内动态创建控件?

  •  7
  • zgorawski  · 技术社区  · 15 年前

    我想创建控件,允许用户设计自己的网站结构。我想象里面 UpdatePanel 是否控制 TextBox (用于页面名称)和 Button “添加下面”。它看起来像:

    |   "Questions" |
    | [ add below ] |
    
    |     "Tags"    |
    | [ add below ] |
    
    |    "Badges"   |
    | [ add below ] |
    

    现在,当用户点击“标签”元素中的按钮时,应该会在“标签”和“徽章”之间出现一个新的按钮,名称可以编辑,这样用户就可以将其命名为“用户”。它应该在没有完整回发的情况下完成(以避免页面闪烁)。

    现在是我的问题:我不能在OnInit中加载这些控件(最后不是全部),因为它们不存在,但是我必须处理它们的单击事件,所以我应该附加事件侦听器,在初始化阶段应该做什么。 如何实现所描述的功能?

    我玩了太久了,我很困惑。我很感激你给我小费。

    3 回复  |  直到 12 年前
        1
  •  14
  •   Chris Mullins    15 年前

    这是一个棘手的情况,因为您要处理动态控件,需要在页面init上填充它们以保持视图状态,而且在按钮单击期间添加到更新面板中的控件的事件似乎在下一次回发之前不会注册,因此正常的按钮单击事件仅在您每次单击时触发一次在新添加的控件上。也许还有别的方法可以解决这个问题,而不是我的方法。如果有人知道我想知道。

    我的解决方案是保留动态添加内容的列表,并将其存储在会话变量中(因为在page in it期间未加载viewstate)。然后在页面init上加载您先前添加的所有控件。然后在页面加载期间用一些自定义代码或普通的单击事件处理单击事件。

    我创建了一个示例页面来帮助测试这个问题。

    以下是ASPX页的代码(默认.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;
    
        }    
    }
    

    如果此代码对您有任何帮助,请通知我。我试着在理解发生了什么以及如何工作的情况下添加评论。

        2
  •  0
  •   aas    12 年前

    这样对我有效

       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();
            }
        }
    

    在调用方法之前,请清除控件,否则它将加载两次

        3
  •  -1
  •   pavanred    15 年前

    如果要为控件动态事件处理程序,则可以尝试此操作-

    考虑到按钮控件,

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

    您可以在按钮单击事件中输入代码,

    void btnTest_Click(object sender, EventArgs e)
    {
        //your code
    }
    
    推荐文章