如何编写服务器控件以使其支持ASP中的部分回发?净WebForms
本文关键字:WebForms 服务器控件 何编写 ASP 支持 | 更新日期: 2023-09-27 17:49:23
我有以下问题:我有一个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总是反应良好,并重新加载其整个内容。
谁能给我一些有用的建议,告诉我如何正确地做这件事?服务器控件的创建过程如下:
//下面的函数调用OnLoad/IndexChanged on ComboBox/TabChanged on Tabs on page
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 :
正如Alexander指出的,我看过这个,这正是我的问题。我继续,用这个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像按钮一样工作,需要对它进行哪些必要的更改?
这行得通:
然而,我不确定是否这是打算的方式去做一个服务器控制更新最近的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;
}
}
}