我遇到了以下问题:我有一个WebForms页面,其中包含在占位符ph1中重新加载自定义服务器控件时闪烁的列布局。
为了避免这种情况,我正在考虑改进我们的服务器控制以支持部分回发。我不太清楚如何做到这一点。因此,当控件触发回发时,我只希望udp2更新其内容,而不是udp1对引发的回发做出反应。
我的页面结构如下:
<updatepanel id="udp1">
<tree>
</tree>
<updatepanel id="udp2">
<ContentTemplate>
<div id="ph1" runat="server"></div> <!--- receives generated servercontrol's
</ContentTemplate>
</updatepanel>
</updatepanel>
到目前为止,我尝试完成这项工作并没有成功,udp1也一直反应并重新加载其整个内容。
有人可以给我任何有关如何正确执行此操作的有用提示吗?
创建servercontrol就像这样:
//跟随在页面选项卡上的ComboBox / TabChanged上的OnLoad / IndexChanged中调用的函数
public void CreateControls()
{
var dataItems = GetData();
foreach(var data in dataItems)
{
var control = CreateServerControl(data); // typeof CustomServerControl
control.ID = "generated"+data.Identifier.ToString();
ph1.Controls.Add(control);
}
}
我是否需要在CustomServerControl上实现某种类型的接口,以便在下一个可用的UpdatePanel中引发回发时更新此控件(但只有udp2,而不是upd1)
CustomServerControl中用于在客户端上启动回发的代码:
var options = new PostBackOptions(this, "update");
// turns into javascript:__doPostBack('somerenderedid','update');
link.href = string.Format("javascript:{0};", this.Page.ClientScript.GetPostBackEventReference(options));
编辑1 :
亚历山大指出我看了this,这是我的问题。我继续,使用此ServerControl创建了一个示例项目:并将其放在Page
中[ParseChildren(false)]
public class TestControl : WebControl
{
protected override HtmlTextWriterTag TagKey
{
get { return HtmlTextWriterTag.A; }
}
protected override void OnPreRender(EventArgs e)
{
var pbo = new PostBackOptions(this, "update");
this.Attributes.Add("href", string.Format("javascript:{0};", this.Page.ClientScript.GetPostBackEventReference(pbo)));
base.OnPreRender(e);
}
}
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Register TagPrefix="a" Namespace="NestedUpdatePanelTest" Assembly="NestedUpdatePanelTest" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="frmMain" runat="server">
<asp:ScriptManager runat="server" EnablePartialRendering="true" ID="TheScriptManager" />
<asp:UpdatePanel ID="aupParent" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<a:TestControl runat="server">outer</a:TestControl>
<asp:Button ID="btnParent" runat="server" Text="Update the parent (and all childs of course)" />
<%= "Parent panel last updated at:" + DateTime.Now.ToString( ) %>
<asp:UpdatePanel ID="aupChild" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<a:TestControl runat="server">inner</a:TestControl>
<asp:Button ID="btnChild" runat="server" Text="Update only the child" />
<%= "Child panel last updated at:" + DateTime.Now.ToString( ) %>
</ContentTemplate>
</asp:UpdatePanel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
按下asp:Button元素确实是我想要的。但是,单击链接不会。对TestControl进行必要的更改以使其像按钮一样工作?
答案 0 :(得分:0)
这有效:
但是我不确定是否打算使servercontrol更新最近的UpdatePanel?欢迎更正和反馈。否则我会将此标记为答案。
(我希望我早点知道这件事)
[ParseChildren(false)]
public class TestControl : WebControl, IPostBackEventHandler
{
protected override HtmlTextWriterTag TagKey
{
get { return HtmlTextWriterTag.A; }
}
protected override void OnPreRender(EventArgs e)
{
var pbo = new PostBackOptions(this, "update");
this.Attributes.Add("href", string.Format("javascript:{0};", this.Page.ClientScript.GetPostBackEventReference(pbo)));
ScriptManager.GetCurrent(this.Page).RegisterAsyncPostBackControl(this);
base.OnPreRender(e);
}
// works when used in UpdatePanel.Triggers property.
public event EventHandler SomeEvent;
public void RaisePostBackEvent(string eventArgument)
{
var h = SomeEvent;
if(h != null)
h(this, EventArgs.Empty);
UpdatePanel p;
Control parent = this.Parent;
while (parent != null)
{
p = parent as UpdatePanel;
if (p != null)
{
p.Update();
return;
}
parent = parent.Parent;
}
}
}