动态添加ListBox的EventHandler不会在ASP.Net上触发

时间:2010-11-20 18:14:42

标签: c# asp.net event-handling listbox

首先,我很抱歉,如果我的问题可能重复,但我搜索得太多了,我找不到解决方案。 scenerio是我有一个UserControl。如果给定List的计数>该用户控件将动态创建ListBoxes。 0.控件是动态添加的,添加它们没有问题,但事件处理程序没有添加。如果我在第一个listBox中选择一个项目,则会动态添加第二个ListBox,并且项目也会动态添加。出现第一个listBox,但selectedIndexChanged事件处理程序不起作用。我的代码有什么问题?

编辑:我尝试添加

li.Attributes.Add("onselectedindexchanged","selectedIndexChanged");

li.AutoPostBack = true;

但仍未解雇...

private List<string> myList = new List<string>() { "Serkan", "Kadir" };
    private List<string> mySecondList = new List<string>() { "Istanbul", "Ankara" };

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            if (myList.Count > 0)
            {
                ListBox li = new ListBox();
                li.ID = Guid.NewGuid().ToString();
                li.SelectedIndexChanged += new EventHandler(this.selectedIndexChanged);
                foreach (string item in myList)
                {
                    li.Items.Add(item);
                }

                this.Controls.Add(li);
            }
        }
    }

    private void selectedIndexChanged(object sender, EventArgs e)
    {
        ListBox li2 = new ListBox();
        li2.ID = Guid.NewGuid().ToString();

        foreach (string item in mySecondList)
        {
            li2.Items.Add(item);
        }
        this.Controls.Add(li2);
    }

4 个答案:

答案 0 :(得分:0)

li.Attributes.Add("onselectedindexchanged","selectedIndexChanged"); 

添加客户端HTML属性。您在此处显示的selectedIndexChanged方法是服务器端方法。您需要向控件添加自动回发,并向控件添加服务器端事件处理程序以使其在服务器上调用C#函数,或者创建客户端JavaScript函数来处理客户端事件

编辑---

当页面回发到服务器时,控件不再存在。 Page是一个新的isntance,它没有将列表框添加到其控件集合中。当auto-postback为true时调用事件IS,但服务器的Page对象中不存在该控件,如果删除If Page.IsPostBack块,则重新创建控件,因此控件不是事件被提出的人,而且这种控制仍然不存在。

这个控件的实际目的是什么?它只是提供一个主要的细节吗?

编辑2 ---

为您创建的解决方案:

页:

<asp:ListBox ID="ListBox1" runat="server" AutoPostBack="true" Visible="false" OnSelectedIndexChanged="ListBox1_SelectedIndexChanged"></asp:ListBox>
<br />
<asp:ListBox ID="ListBox2" runat="server" Visible="false"></asp:ListBox>

代码隐藏:

private List<string> myList = new List<string> {
    "Serkan",
    "Kadir"
};
private List<string> mySecondList = new List<string> {
    "Istanbul",
    "Ankara"

};
protected void Page_Load(object sender, System.EventArgs e)
{
    if (!Page.IsPostBack) {
        if (myList.Count > 0) {
            ListBox1.DataSource = myList;
            ListBox1.DataBind();
            ListBox1.Visible = true;
        }
    }
}

protected void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    ListBox2.DataSource = mySecondList;
    ListBox2.DataBind();

    ListBox2.Visible = true;
}

答案 1 :(得分:0)

您的活动未发生的原因是您误解了ASP.Net页面生命周期。当您请求页面时,ASP.Net会创建相应页面类的新实例。此实例对过去创建的任何其他实例一无所知。它使用Page类的实例生成一堆HTML,并将其作为响应发送回浏览器。然后销毁服务器上的Page类实例及其状态。

当页面回发时,ASP.Net将使用viewstate,ids等进行读取,并将发回的HTML元素映射到新创建的Page实例中的服务器控件。您添加到上一个实例的Controls集合中的元素在此新实例中不存在,因此ASP.Net无法识别它们或在它们上触发事件。

这篇文章演示了我认为你想要实现的目标,尽管使用GridViews,它使用了与我之前发布的解决方案类似的方法。

http://www.codeproject.com/KB/aspnet/MultiNestMDGridview.aspx

也许您可以准确地解释最终目标是什么,因为可能有更好的解决方案?我完全接受我之前发布的方法和该链接中的解决方案的限制是,可用的细节级别有限,这可能是也可能不是问题,这取决于您实际尝试做什么

编辑 -

如果你改为@Microgen建议的Page_Init事件,删除if(!Page.IsPostBack),设置AutoPostBack = true,并为动态添加的控件使用非易失性ID,这将调用服务器端事件并渲染第二个列表框。它不适用于Guid.New(),因为新创建的Page上的Controls集合不包含任何具有匹配ID的集合,因此事件处理程序不会被连接起来。这将回答最初发布的问题。但是,你的第二个列表框不会触发事件,除非你创建它并以相同的方式将它添加到Page_Init中的Page.Controls等等,所有这些都是由于上述原因。

答案 2 :(得分:0)

1 - 动态添加控件必须在page_init事件中加载而不是在page_load中 2个选中的列表框不能与.attributes.add(“selectedindexchanged”,“...”)一起使用,因为复选框列表是一个asp.net控件,但它在html中呈现为常规输入

答案 3 :(得分:0)

伙计们,我的代码运作良好。我今天刚刚在一个差异视觉工作室试过这个,一切都很好。 @ RichardW1001和@Microgen感谢您的关注和帖子。