UpdatePanel RadioButtonList AsyncPostback EventHandler 丢失
UpdatePanel RadioButtonList AsyncPostback EventHandler Lost
过去几个小时我一直在搜索,但找不到解决问题的方法。标题很罗嗦,但我认为它准确地描述了我的情况。请参阅下面的代码。我已经尝试在转发器的 ItemDataBound 事件上添加 SelectedIndexChanged 函数,但回发事件似乎导致页面忘记了处理程序。使用 Triggers.Add 添加 AsyncPostbackTrigger 也是如此。
有效的解决方案是 re-add 回发时的 EventHandler,但这对我来说不是一个可行的解决方案。我可以编写一个自定义函数来独立于实际的 DataBinding 循环遍历我的转发器数据源,然后在适用时特别 re-bind EventHandler,但这似乎是一种非常 brute-force 的方法。有没有更好的方法来完成我的 objective?
Front-end:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="smMain" runat="server" />
<div>
<asp:UpdatePanel ID="updTest" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Repeater ID="rptTest" runat="server" OnItemDataBound="rptTest_ItemDataBound">
<ItemTemplate>
<asp:RadioButtonList ID="rblTest" runat="server" RepeatDirection="Horizontal" ClientIDMode="AutoID" />
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Back-end:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
DataTable dt = new DataTable();
dt.Columns.Add("Test");
DataRow dr = dt.NewRow();
dr["Test"] = "FirstRow";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Test"] = "SecondRow";
dt.Rows.Add(dr);
rptTest.DataSource = dt;
rptTest.DataBind();
}
else
{
// This works, but it's very, very ugly. Also, I have no way of being able to test for which function I actually want to call!
((RadioButtonList)FindControl(Request.Params["__EVENTTARGET"])).SelectedIndexChanged += testFunction;
}
}
protected void rptTest_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RadioButtonList rbl = (RadioButtonList)e.Item.FindControl("rblTest");
DataTable dt = new DataTable();
dt.Columns.Add("ButtonName");
dt.Columns.Add("ButtonID");
DataRow dr = dt.NewRow();
dr["ButtonName"] = "Yes";
dr["ButtonID"] = "1";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ButtonName"] = "No";
dr["ButtonID"] = "2";
dt.Rows.Add(dr);
rbl.DataTextField = "ButtonName";
rbl.DataValueField = "ButtonID";
rbl.DataSource = dt;
rbl.DataBind();
rbl.AutoPostBack = true;
//This doesn't work. Even though it's set here, it doesn't "remember" the setting on postback
//rbl.SelectedIndexChanged += testFunction;
//This doesn't work either. Again, it doesn't "remember" the setting on postback
//updTest.Triggers.Add(new AsyncPostBackTrigger() { ControlID = rbl.UniqueID });
}
private void testFunction(object sender, EventArgs e)
{
}
}
找到问题的解决方案。本质上,我需要将 EventHandler 绑定到 ItemCreated 事件,而不是 ItemDataBound 事件。每次回发都会触发 ItemCreated 事件,而不仅仅是第一次回发,因此可以正确地重新绑定 EventHandler。
前端:
<asp:Repeater ID="rptTest" runat="server" OnItemCreated="rptTest_ItemCreated" OnItemDataBound="rptTest_ItemDataBound">
后端:
protected void rptTest_ItemCreated(object sender, RepeaterItemEventArgs e)
{
RadioButtonList rbl = (RadioButtonList)e.Item.FindControl("rblTest");
rbl.SelectedIndexChanged += testFunction;
}
过去几个小时我一直在搜索,但找不到解决问题的方法。标题很罗嗦,但我认为它准确地描述了我的情况。请参阅下面的代码。我已经尝试在转发器的 ItemDataBound 事件上添加 SelectedIndexChanged 函数,但回发事件似乎导致页面忘记了处理程序。使用 Triggers.Add 添加 AsyncPostbackTrigger 也是如此。
有效的解决方案是 re-add 回发时的 EventHandler,但这对我来说不是一个可行的解决方案。我可以编写一个自定义函数来独立于实际的 DataBinding 循环遍历我的转发器数据源,然后在适用时特别 re-bind EventHandler,但这似乎是一种非常 brute-force 的方法。有没有更好的方法来完成我的 objective?
Front-end:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="smMain" runat="server" />
<div>
<asp:UpdatePanel ID="updTest" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Repeater ID="rptTest" runat="server" OnItemDataBound="rptTest_ItemDataBound">
<ItemTemplate>
<asp:RadioButtonList ID="rblTest" runat="server" RepeatDirection="Horizontal" ClientIDMode="AutoID" />
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Back-end:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
DataTable dt = new DataTable();
dt.Columns.Add("Test");
DataRow dr = dt.NewRow();
dr["Test"] = "FirstRow";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Test"] = "SecondRow";
dt.Rows.Add(dr);
rptTest.DataSource = dt;
rptTest.DataBind();
}
else
{
// This works, but it's very, very ugly. Also, I have no way of being able to test for which function I actually want to call!
((RadioButtonList)FindControl(Request.Params["__EVENTTARGET"])).SelectedIndexChanged += testFunction;
}
}
protected void rptTest_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RadioButtonList rbl = (RadioButtonList)e.Item.FindControl("rblTest");
DataTable dt = new DataTable();
dt.Columns.Add("ButtonName");
dt.Columns.Add("ButtonID");
DataRow dr = dt.NewRow();
dr["ButtonName"] = "Yes";
dr["ButtonID"] = "1";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["ButtonName"] = "No";
dr["ButtonID"] = "2";
dt.Rows.Add(dr);
rbl.DataTextField = "ButtonName";
rbl.DataValueField = "ButtonID";
rbl.DataSource = dt;
rbl.DataBind();
rbl.AutoPostBack = true;
//This doesn't work. Even though it's set here, it doesn't "remember" the setting on postback
//rbl.SelectedIndexChanged += testFunction;
//This doesn't work either. Again, it doesn't "remember" the setting on postback
//updTest.Triggers.Add(new AsyncPostBackTrigger() { ControlID = rbl.UniqueID });
}
private void testFunction(object sender, EventArgs e)
{
}
}
找到问题的解决方案。本质上,我需要将 EventHandler 绑定到 ItemCreated 事件,而不是 ItemDataBound 事件。每次回发都会触发 ItemCreated 事件,而不仅仅是第一次回发,因此可以正确地重新绑定 EventHandler。
前端:
<asp:Repeater ID="rptTest" runat="server" OnItemCreated="rptTest_ItemCreated" OnItemDataBound="rptTest_ItemDataBound">
后端:
protected void rptTest_ItemCreated(object sender, RepeaterItemEventArgs e)
{
RadioButtonList rbl = (RadioButtonList)e.Item.FindControl("rblTest");
rbl.SelectedIndexChanged += testFunction;
}