【发布时间】:2011-08-04 21:07:59
【问题描述】:
关于 SO(1、2、3、4 等)和网络上(1、2 等)有很多类似的问题,但没有一个相应的答案能说明问题我的情况。
我有一个由两个下拉列表组成的简单自定义用户控件。在一个下拉列表中选择一个值应该会导致另一个下拉列表的填充。只要我在 .aspx 代码中声明用户控件,一切都会按预期工作。
现在我想以编程方式在页面上添加用户控件(单击按钮时)。尽管正在添加控件,但在一个下拉列表中的选择只会导致回发,而不会导致另一个下拉列表的操作。
在调试时,我发现不仅OnSelectedIndexChanged 不会触发,OnLoad 和所有其他事件也会触发。
在我浏览过的所有讨论中,出现这种行为的常见原因如下:
DropDownList的AutoPostBack未设置为 true,或者数据绑定的DropDownList在每次回发时都被反弹,导致事件丢失。 //这里不是个例,更可能是指动态添加的下拉列表ID在每次回发时自动分配给动态添加的控件(并且每次都分配一个不同的控件,这样ViewState就不会正确持久化,并且事件不知道应该触发)。 // 好的,我已经检查过了,现在手动分配 ID该控件只添加一次(与每次回发时添加相反,这是必要的,因为在
ViewState中仅存储服务器控件的状态(值),而不是控件本身)和/或在每次回发时添加控件,但在页面生命周期中为时已晚。 //好的,我现在在
OnInit事件处理程序中添加我的控件
为了让页面知道添加了控件(以及添加了多少),我使用Session。下面是一些代码,最后是问题:)
.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>
以及背后的代码:
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();
}
(我很确定用户控件本身的代码与案例并不真正相关,但我可以稍后根据要求添加)。
所以现在的问题是:通过反复试验,我发现如果我将新添加的控件存储在 Session 和 OnInit 的集合中,只需从该集合中取出控件并再次添加到控件中我的占位符的集合,在下一次回发时不会触发此控件的任何事件(与调用回发的方式无关)。否则,如果我 创建 OnInit 为每个存储在 Session 中的新控件,并将这个新创建的控件添加到占位符控件集合中 - 一切正常!那么存储在Session 控件中有什么问题,为什么它们会丢失事件?
还有一个小问题。为此类控件创建 ID 的最佳做法是什么?我使用特定格式的字符串和计数器,但我怀疑这是最好的方法。例如,如果我添加了不同类型的控件,我会遇到这种方法的麻烦。
感谢大家阅读这么长的问题并提出宝贵意见!
【问题讨论】:
标签: asp.net events session user-controls