ASP .Net中使用控件时按钮点击事件无法触发

5
我正在开发一个asp网页,在其中有一个下拉组合框和一个占位符。当用户从下拉组合框中选择一个项目时,将向服务器端进行回发,并在父页面的占位符中加载一个asp用户控件。到目前为止,一切都运行良好。
在用户控件中,我有一个按钮,用户控件代码后台被实现来处理按钮单击事件。问题是,当我单击此按钮时,我可以看到回发被发送到服务器端(即调试模式下父页面Page_Load()被调用),但是用户控件的Page_Load()或按钮单击事件处理程序都没有被调用。
请帮助解决。
一些附加信息: 1.我的父页面不是asp主页面。只是一个简单的asp页面。 2.我正在使用VS2008和.Net 3.5 SP1和C#。

一些额外的信息,比如一些代码会有所帮助。 - JConstantine
在页面顶部的<%@ Page %>指令中,AutoEventWireup="true"吗?如果您想了解AutoEventWireup是什么,请参阅此链接:http://msdn.microsoft.com/en-us/library/59t350k3%28vs.71%29.aspx - Amir
3个回答

8

确保您的UserControl存在,这样在重新构建视图状态时才会触发按钮单击事件。

在Page_Load中加载您的UserControl将在第一次起作用。当您单击按钮并发生post_back时,Page_Load尚未发生。这意味着UserControl不存在,也就是说按钮不存在,无法将其连接到事件以触发单击事件。

建议在此事件中加载您的用户控件。

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    //-- Create your controls here
}

尝试沙盒测试。在Page_Load中动态创建一个带有点击事件的按钮。你会发现点击事件并没有触发。现在将按钮移到OnLoad事件中,点击事件将会被触发。还要注意,点击事件将在Page_Load事件之前发生。更进一步的证明,该按钮并不存在正确的时间点上。

另一个想法...

在按钮事件发生之前,您在页面上重新加载了用户控件。请确保您的LoadControl方法在If块内部。

if (!IsPostBack)
{
    //load usercontrol
}

尝试过这个方法。问题在于,这个改变后,组合框的SelectedIndexChanged事件最后才触发。以前我在这个组合框的SelectedIndexChanged事件处理程序中加载用户控件,因为根据所选索引,我需要加载不同的用户控件。现在我将SelectedIndexChanged更改为仅将当前索引分配给父页面代码后面的公共属性,并在OnLoad()事件处理程序中切换此属性以加载所需的用户控件。但是由于SelectedIndexChanged最后才触发,所以无法正常工作。 - Bathiya Priyadarshana
你能在OnLoad中访问combobox.SelectedIndex吗?如果可以,就加载控件。 - Valamas
1
谢谢Valamas..我可以在OnLoad中访问SelectedIndex..它起作用了.. :) - Bathiya Priyadarshana

3

Default.aspx

<asp:PlaceHolder runat="server" ID="ph1">
</asp:PlaceHolder>

Default.aspx.cs

 protected void Page_Load(object sender, EventArgs e)
 {
     var ctl = LoadControl("Controls/UserControl.ascx");
     ph1.Controls.Add(ctl);
}

UserControl.ascx

<h3>User control</h3>
<asp:Button ID="btn1" runat="server" OnClick="btn1_Click" Text ="Click me" />

UserControl.ascx.cs

protected void btn1_Click(object s, EventArgs e)
{
    Response.Write("You clicked me, yay");
}

所有的工作都非常顺利。当我点击按钮时,我看到了“你点击了我,耶”的文字。
需要注意的是,如果您尝试在下拉控件的SelectedItemChanged事件处理程序中动态加载控件,则会失败,因为ASP.Net页面的生命周期方式。相反,您应该在页面的PageLoad事件中处理这样的控件创建,像下面这个例子一样。
Default.aspx
<asp:DropDownList ID="ddl1" runat="server" AutoPostBack="true">
    <asp:ListItem Value="0" Text="--select a value--" />
    <asp:ListItem Value="1" Text="User control 1" />
    <asp:ListItem Value="2" Text="User control 2" />
</asp:DropDownList>
<asp:PlaceHolder runat="server" ID="ph1">
</asp:PlaceHolder>   

Default.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        switch (ddl1.SelectedValue)
        {
            case "1":
                var ctl = LoadControl("Controls/UserControl.ascx");
                ph1.Controls.Add(ctl);
                break;
            case "2":
                ctl = LoadControl("Controls/UserControl2.ascx");
                ph1.Controls.Add(ctl);
                break;
        } 
    }
}

提供一个很好的例子,点赞!希望原帖作者在此之后能够发现问题所在。 - Valamas
1
这能够工作是因为您在每个 postback 上都加载了相同的用户控件。我需要做的是根据下拉列表框的选择索引加载不同的用户控件。因此,我在下拉列表框的 SelectedIndexChanged 事件处理程序中加载用户控件。 - Bathiya Priyadarshana
我明白了。那么,这就是你的问题 - 你正在使用SelectedIndexChanged事件。相反,在Page_Load事件期间应该完成所有动态控件的加载。 - Trogvar
我提供了一个扩展示例。 - Trogvar
@Trogvar:在测试时,请确保正确的用户控件显示“耶,我是UC1,你点击了我”或“耶,我是UC2,你点击了我”,并确保正确的用户控件与所点击的按钮相对应。 - Valamas
我已经测试过了,正确的用户控件对应于点击事件,并且显示了正确的消息。由于更改非常明显,我没有放下所有的源代码。因此,我不太理解你在这里评论的目的。 - Trogvar

0
在我的特定情况下,我发现问题是UserControl ID(或者说是缺乏)。
当UserControl第一次被实例化时,我的按钮ID为ctl00$ctl02$btnContinue,但在postback后,它已经变成了ctl00$ctl03$btnContinue,因此按钮事件处理程序未触发。
我改为使用固定的ID添加我的UserControl,因此该按钮现在始终使用ID ctl00$myUserControl$btnContinue加载。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接