我试图了解一些使用updatepanels的部分回发,虽然很多事情让我感到困惑,但这让我感到困惑。
我在UpdatePanel中使用选项卡,因为这是一个数据输入应用程序,我将内容放入用户控件,因此每个选项卡都有自己的用户控件。另外,我正在为每个用户控件添加自定义javascript,以处理该控件中的东西的特定客户端事物。
在执行此操作时虽然我注意到用户控件中的javascript不会触发部分页面回发。
为了模拟这个,我在VS2010中创建了一个非常简单的应用程序(在主页面上使用带有ScriptManager控件的母版页)。
默认页面的内容面板具有以下内容
<asp:UpdatePanel runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:Button runat="server" ID="Button1" Text="Partial postback" />
<br />
<asp:Panel runat="server" ID="panel"></asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
然后我创建了一个用户控件,只是添加了一些纯文本和一个javascript警报
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="UC1.ascx.vb" Inherits="TestWebApp_VB.UC1" %>
This is user control 1
<script> alert('control 1'); </script>
然后在Content页面的页面加载事件中,我将控件加载到面板中。
Panel.Controls.Add(LoadControl("UC1.ascx"))
此外,在按钮的单击处理程序中,我还加载了控件(或切换时的不同控件,如下所述)
Button_Click
Panel.Controls.Clear()
Panel.Controls.Add(LoadControl("SomeControl.ascx"))
因此,当首次加载页面时,警报会触发,但是当您单击该按钮并且页面被部分回发时,警报将永远不会触发。
我向前迈了一步,创建了第二个用户控件,并按下切换按钮加载控件,并在UpdatePanel外添加了一个普通按钮。每次我完成回发时,加载的用户控件中的javascript都会触发,但它永远不会触发部分回发。
然后我向前迈出了一步,将控件中的javascript移动到一个函数中,这样我就可以从PageRequestManager或者document.ready中调用该函数。
所以现在我的两个控件包含这个脚本(警报包含每个控件的不同消息)
<script type="text/javascript">
function userLoad() {
alert("Identify control");
}
</script>
因此我将其添加到我的内容面板的末尾
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance().add_endRequest(userLoad);
</script>
现在,javascript会在每个部分回发时触发,但是它会触发最后由完整回发加载的控件的javascript。
示例:
---编辑----
我尝试过的一件事,与Scotts的建议一起工作。 将每个控件的javascript保存在一个单独的文件中,并将其全部放入一个名为函数UC1Load(){}的函数中(如果我感觉活泼,可能会在它周围粘贴一个命名空间),添加对脚本文件的引用内容页面通过
<script src='UC1.js'>
然后注册启动脚本以调用此函数
ScriptManager.RegisterStartupScript(ctrl, ctrl.GetType(), "UserJS", "UC1Load()", True)
最大的问题是我现在不得不下载一堆不会被使用的脚本,这就是为什么我首先将脚本放在用户控件中。
答案 0 :(得分:2)
您可以采用的另一种方法是使用jQuery的.on()
方法。
提供选择器时,事件处理程序称为 授权。直接在事件发生时不会调用处理程序 绑定元素,但仅适用于后代(内部元素) 匹配选择器。 jQuery从事件目标起泡事件 到附加处理程序的元素(即最里面的) 最外面的元素)并为其中的任何元素运行处理程序 匹配选择器的路径。
事件处理程序仅绑定到当前选定的元素;他们 在您的代码调用.on()时页面上必须存在。
...
委派事件的优势在于它们可以处理来自的事件 稍后添加到文档中的后代元素。通过 选择一个保证在当时存在的元素 委托事件处理程序附加,您可以使用委托事件 避免频繁附加和删除事件处理程序的需要。这个 element可以是a中视图的容器元素 例如,模型 - 视图 - 控制器设计,或者如果事件是文档 handler希望监视文档中的所有冒泡事件。该 文档元素在之前的文档头部中可用 加载任何其他HTML,因此可以安全地在那里附加事件 等待文件准备好。
因此,例如,您可以使用相同的类包装您的UserControls,如下所示:
<div class="userControl">
<span>This is UserControl 1</span>
</div>
<div class="userControl">
<span>This is UserControl 2</span>
</div>
然后,在您的MasterPage中,在</body>
标记之前的最底部,包含您的jQuery引用和您的jQuery脚本。在我的示例中,我在单击<span />
时打印出UserControl内部<span />
的内容。
<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js"></script>
<script>
$("div[id$=UpdatePanel1]")
.on("click", "div.userControl span", function() {
alert($(this).html().trim());
});
</script>
</body>
</html>
答案 1 :(得分:1)
好的,在创建了自己的测试网站并修补后,这就是我的工作:
<%@ Control Language="C#"
AutoEventWireup="true"
CodeFile="TestControl1.ascx.cs"
Inherits="Controls_TestControl1" %>
This is Test Control 1
<%@ Control Language="C#"
AutoEventWireup="true"
CodeFile="TestControl2.ascx.cs"
Inherits="Controls_TestControl2" %>
This is Test Control 2
<%@ Page Language="C#"
MasterPageFile="~/Site.master"
AutoEventWireup="true"
CodeFile="10049777.aspx.cs"
Inherits="_10049777" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="Server" />
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="Server">
<asp:UpdatePanel ID="UpdatePanel1" runat="server"
UpdateMode="Conditional"
ChildrenAsTriggers="true">
<ContentTemplate>
<asp:Button ID="Button1" runat="server"
Text="Partial postback"
OnClick="Button1_Click" />
<br /><br />
<asp:Panel runat="server" ID="Panel1" />
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var TestControl1 = LoadControl("Controls\\TestControl1.ascx");
Panel1.Controls.Add(TestControl1);
ScriptManager.RegisterStartupScript(TestControl1,
TestControl1.GetType(),
"TestControl1Script",
"alert(\"control 1\");",
true);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
var TestControl2 = LoadControl("Controls\\TestControl2.ascx");
Panel1.Controls.Clear();
Panel1.Controls.Add(TestControl2);
ScriptManager.RegisterStartupScript(TestControl2,
TestControl2.GetType(),
"TestControl2Script",
"alert(\"control 2\");",
true);
}
答案 2 :(得分:0)
找到内联脚本问题的一个很好的解释
http://veskokolev.blogspot.com/2009/03/inline-scripts-in-updatepanel-doesnt.html
简而言之:部分回发更新了更新面板的innerHtml,因此它将html的blob视为直文,因此不会在html中注册任何脚本标记。
所以我的最终解决方案就是这样。
每个控件都有一个自己的javascript文件,其函数名称类似于
function controlNameLoad() { ..do your stuff }
在内容面板代码中(在case语句中确定要加载哪个控件)
dim ctrl = LoadControl("UCName.ascx")
panel.Controls.Add(ctrl)
ScriptManager.RegisterClientScriptInclude(ctrl, ctrl.GetType(), "UserJS", "UCName.js")
ScriptManager.RegisterStartupScript(ctrl, ctrl.GetType(), "UserJS", "controlNameLoad()", True)
这适用于我的测试项目,稍后会看到我是否可以实现我的真实代码。