为什么不回发动态添加用户控件火灾事件? [英] Why don't events of dynamically added user control fire on postback?

查看:96
本文介绍了为什么不回发动态添加用户控件火灾事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有很多类似的问题对SO(<一个href=\"http://stackoverflow.com/questions/3528683/dynamically-displayed-usercontrol-not-firing-postback-event-on-select\">1, <一href=\"http://stackoverflow.com/questions/5120695/dynamically-created-dropdownlist-no-firing-event-yes-autopostback-is-set-to-tru\">2, <一href=\"http://stackoverflow.com/questions/355673/how-do-i-get-dynamically-added-asp-net-buttons-to-fire-events\">3, <一href=\"http://stackoverflow.com/questions/2304602/dropdownlist-onselectedindexchanged-event-in-a-usercontrol-is-not-firing-on-post\">4等),并在网络上( 1 ,<一个href=\"http://www.pcreview.co.uk/forums/dynamically-created-dropdownlist-not-firing-events-persisting-viewstate-t1292501.html\"相对=nofollow> 2 等),但没有相应的回答澄清我的处境。

There are plenty of similar questions on SO (1, 2, 3, 4 etc) and on the web (1, 2 etc) but none of the corresponding answers clarifies my situation.

我有包含两个下拉列表的一个简单的自定义用户控件。在一个下拉列表中值的选择应导致另一个的填充。只要我宣布在.aspx code一切用户控件按预期工作。

I have a simple custom user control consisting of two drop-down lists. Selection of a value in one drop-down list should lead to the populating of the other one. As long as I declare the user control in the .aspx code everything works as expected.

现在我想要添加的页面上的用户控件编程方式(按钮点击)。虽然添加的控制,在一个下拉列表中选择不仅造成回发,但没有其他的下拉列表中的动作。

Now I want to add the user control on the page programmatically (on button click). Although the control is being added, the selection in one drop-down list causes only a postback but no action of the other drop-down list.

调试时,我发现,不仅 OnSelectedIndexChanged 不火,也的OnLoad 和所有的其他事件。

While debugging I've found out that not only OnSelectedIndexChanged does not fire, but also OnLoad and all the other events.

对于这样的行为对于所有我看了都通过以下讨论的常见原因:

Common reasons for such a behaviour regarding all the discussions I've looked through are the following:


  1. 的AutoPostBack 的DropDownList 未设置为true或数据绑定 DropDownList的正在每个导致事件的丢失回发的反弹。 //这里没有的情况下,更可能是指动态地添加下拉列表

  1. AutoPostBack of the DropDownList is not set to true or the databound DropDownList is being rebound on each postback which causes the losing of events. //not a case here, more likely refers to dynamically added drop-down lists

ID 每次都分配到动态在每次回发自动添加控件(和一个不​​同的,这样的ViewState 不正确地持久化和事件不知道自己应该解雇)。 //好,我检查了,现在手动分配ID

ID is assigned to the dynamically added control automatically on each postback (and every time a different one so that ViewState is not persisted correctly and events do not know that they should fire). // ok I've checked it and now assign the ID manually

的控制是仅加入一次(而不是在每次回发加入这是必要的,因为在视图状态仅状态(服务器控制值)的被存储,但不是控件本身)和/或

The control is added only once (as opposed to the addition on every postback which is necessary because in the ViewState only the state (values) of server controls are stored, but not the controls themselves) and/or

控件在页面生命周期在每次回发添加,但为时已晚。 // OK,我将我的的OnInit 事件处理程序的控制现在

the control is added on each postback but too late in the Page Life Cycle. //ok I'm adding my control in OnInit event handler now

为了让页面知道添加了控制(以及其中有多少)我使用会话。下面有点code,然后最后一个问题:)

In order to let the page know that the control was added (and how many of them) I use Session. Below a bit of code and then finally the question :)

的.aspx:

<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
    <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
</asp:Content>

和背后的code:

protected void Page_Load(object sender, EventArgs e)
        {
            if(!this.IsPostBack)
            {
            Session.Remove("Childcontrols");
            }
        }

        private void AddTransitControl()
        {
            List<Control> controls = (List<Control>)Session["Childcontrols"];
            AddTransitPoint atp = (AddTransitPoint)LoadControl("~/UserControls/AddTransitPoint.ascx");
            string id = this.ID + "_eb" + (controls.Count).ToString();
            atp.ID = id;
            controls.Add(atp);

            PlaceHolder1.Controls.Add(atp);
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            if (Page.IsPostBack)
            {
                if (Session["Childcontrols"] == null)
                {
                    Session["Childcontrols"] = new List<Control>();
                }

                List<Control> controls = (List<Control>)Session["Childcontrols"];
                int count = 0;
                foreach (Control c in controls)
                {
//                    AddTransitPoint atp = (AddTransitPoint) c; //mystically not working (fires no events)
                    AddTransitPoint atp = (AddTransitPoint)LoadControl("~/UserControls/AddTransitPoint.ascx"); //it is working!

                    string id = this.ID + "_eb" + count;
                    count++;
                    atp.ID = id;
                    PlaceHolder1.Controls.Add(atp);
                }
            }
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            AddTransitControl();
        }

(我pretty确保用户控件本身的code是不是这样确实相关,但要求以后我可以添加它)。

(I'm pretty sure that the code of the user control itself is not really relevant for the case but on request I can add it later).

所以,现在的问题是:经过反复试验,我发现,如果我存储在集合中的会话新添加的控制 OnInit的只是采取控制了这个集合,然后再重新添加到我的占位符的控件集合,这种控制火灾对下一回发任何事件(独立的方式回传被调用)。其他的方式,如果我的创建 的OnInit 每个存储在会话一个新的控制,并加入到占位符控件集合这个新创建的控制 - 一切正常!因此,与存储在会话控制,为什么他们失去了他们的活动有什么不好?

So now the question: Through trial and error I've found out that if I store the newly added control in the collection in Session and OnInit just take the control out of this collection and add again to the control collection of my placeholder, no events of this control fire on the next postback (independent of the way the postback is called). Other way if I create OnInit a new control for each stored in Session and add to the placeholder control collection this newly created control - everything works! So what is wrong with stored in the Session controls and why do they lose their events?

在这里多了一个小问题。什么是对这种控制创建一个ID的最佳做法?我使用的特定格式的字符串与计数器一起,但我怀疑它要做到这一点的最好办法。例如,如果我添加不同类型的控件我将面临的麻烦与此方法。

And one more small question here. What is the best practice for creating IDs for such controls? I use a string of particular format along with a counter, but I doubt it is the best way to do it. For example if I added different types of controls I would face trouble with this method.

感谢您为大家看完这么长的问题,并为您的宝贵意见!

Thank you everybody for reading such a long question and for your valuable input!

推荐答案

我的理解是这样的:在每个回发事件必须被重新建立。你得到这个免费的,如果事件在ASPX文件中定义的,因为这些属性(的OnClick,OnSelectionChanged等),当页面对象实例化时重新处理。

My understanding is this: events must be re-established on every postback. You get this for free if the event is defined in the the ASPX file, because those attributes (OnClick, OnSelectionChanged, etc.) are re-processed when the page object is instantiated.

您不动态地构建控件,或者是在ASPX文件中定义,但在其codebehind他们对事件的有线式的控制得到这个免费的。对于那些控件,事件不会在实例化时已知的,因此页面无法自动重新建立它们。对于那些控件,您必须重新建立在每次回发的事件。

You do not get this for free with dynamically-built controls, or controls which are defined in the ASPX file but have their events wired-up in the codebehind. For those controls, the events are not known at instantiation time, thus the page can not automatically re-establish them for you. For those controls, you must re-establish your events on every postback.

我的会话存储数据的理解是:当你把一个对象在会话中,该对象本身不是保留在内存中活着。相反,它是系列化,和序列化的数据被存储在会话。当你的对象背出会话,它是反序列化。

My understanding of session-stored data is: when you put an object in the session, that object itself is not kept alive in memory. Instead, it is serialized, and the serialized data is stored in the session. When you get the object back out of the session, it is deserialized.

对象'事件没有生存的序列化/反序列化往返,因为它们在逻辑上是函数指针 - 所以当对象从内存中删除,后来重新修建,整个内存风景发生了变化,所以这些事件/指针将不再有效。

Objects' events do not survive the serialization/deserialization round-trip because they are logically function pointers - so when the object is removed from memory and later re-built, the entire memory "landscape" has changed, so those events/pointers would no longer be valid.

我没有做了很多动态生成控件的工作,所以我不能告诉你最有效的方式来管理他们和他们的活动。但我知道,它们存储在会话是不是真的你买了什么好处重新建立他们在每次回发;并且它不必要腹胀建立会话内存。希望在此线程其他一些SO'ers可以指向你管理它们的最佳实践方法。

I haven't done a lot of work with dynamically-generated controls, so I can't tell you the most effective pattern to managing them and their events. But I know that storing them in the session isn't really buying you any benefit over re-creating them on each postback; and it is bloating up the session memory unnecessarily. Hopefully some other SO'ers on this thread can point you to the best-practices way of managing them.

这篇关于为什么不回发动态添加用户控件火灾事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆