7

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

|   "Questions" |
| [ add below ] |

|     "Tags"    |
| [ add below ] |

|    "Badges"   |
| [ add below ] |

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

现在是我的问题:我无法在 onInit 中加载这些控件(最后不是全部),因为它们不存在,但我必须关注他们的点击事件,所以我应该附加事件侦听器在 Init 阶段应该做什么。我怎样才能实现描述的功能?

我玩了太多时间,我很困惑。我将不胜感激任何提示。

4

3 回答 3

15

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

我的解决方案是保留您动态添加的内容的列表,并将其存储在会话变量中(因为在页面初始化期间未加载视图状态)。然后在页面上初始化加载您之前添加的任何控件。然后在页面加载期间使用一些自定义代码或正常的点击事件来处理点击事件。

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

这是 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;

    }    
}

让我知道这段代码是否对您有帮助。我试图根据我对正在发生的事情及其工作方式的理解添加评论。

于 2010-11-03T14:38:53.770 回答
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();
        }
    }

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

于 2013-10-29T12:20:26.590 回答
-1

如果你想为你的控件动态事件处理程序,那么你可以试试这个 -

考虑一个按钮控件,

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

您可以在按钮单击事件中使用您的代码,

void btnTest_Click(object sender, EventArgs e)
{
    //your code
}
于 2010-11-03T11:31:24.820 回答