Asp.NET 自定义服务器控件事件处理程序在第二次回发时未触发
我正在 Asp.NET (.NET 3.5) 中开发一个继承 CompositeControl 类的自定义服务器控件。在我的控件中,我重写 CreateChildControls()
方法来生成 html 和 Asp.NET 服务器控件的混合。添加的一些 Asp.NET 控件是 LinkButton
(每个控件都将其 Command
事件处理程序设置为我的控件内的方法)。我发现,第一次单击其中一个 LinkButton 时,会触发回发并且正确触发事件处理程序方法。在此事件处理程序中,显式调用 CreateChildControls() 方法来重新生成控件以响应回发。然后我发现,后续单击 LinkButton 回发无法引发事件处理程序方法。
我认为我处理回发时控件重新生成的方式一定有问题,但我不知道该怎么做 - 我知道在第一次回发时 CreateChildControls() 被调用了两次可能并不理想,但由于在引发任何事件之前调用 CreateChildControls,我没有看到解决此问题的方法。
我的控件类的简化版本如下所示:
public class SearchResults : CompositeControl
{
private int PageIndex = 0;
protected override void CreateChildControls()
{
//do stuff here e.g.
LinkButton prevLink = new LinkButton();
prevLink.Text = "< Prev";
prevLink.CommandArgument = (PageIndex - 1).ToString();
prevLink.Command += new CommandEventHandler(PagerLinkCommand);
this.Controls.Add(prevLink);
}
protected void PagerLinkCommand(object sender, CommandEventArgs e)
{
PageIndex = int.Parse(e.CommandArgument.ToString());
CreateChildControls();
}
}
编辑 这里的问题是由于该控件在 Sitecore 站点中使用这一事实引起的,而我忘记了在 web.config 文件中使用
条目注册控件类型。此条目用于防止服务器控件的事件被 Sitecore 搞乱 - 这可能会导致标准服务器控件(例如 ListView、GridView 和 Repeater 等)出现类似问题。我的 web.config 已修改如下:
<typesThatShouldNotBeExpanded>
<type>System.Web.UI.WebControls.Repeater</type>
<type>System.Web.UI.WebControls.DataList</type>
<type>System.Web.UI.WebControls.GridView</type>
<type>MyNamespace.MyCustomControl</type> <!-- This is the bit I added -->
</typesThatShouldNotBeExpanded>
I'm developing a custom server control in Asp.NET (.NET 3.5) which inherits the CompositeControl class. Inside my control I'm overriding the CreateChildControls()
method to generate a mixture of html and Asp.NET server controls. Some of the Asp.NET controls which are added are LinkButton
s (which each have their Command
event handler set to a method within my control). What I'm finding is that the first time one of these LinkButtons is clicked a postback is triggered and the event handler method is correctly fired. Inside this event handler method CreateChildControls() is explicitly called to regenerate the control in response to the postback. What I then find is that subsequent clicks of the LinkButton
s postbacks fail to raise the event handler method.
I assume that the way I'm handling the regeneration of the control on postback must be at fault, but I can't figure out what to do - I am aware of the fact that on that first postback CreateChildControls() is called twice which probably isn't ideal but since CreateChildControls is called before any events are raised, I don't see a way around this.
A simplified version of my control class is shown below:
public class SearchResults : CompositeControl
{
private int PageIndex = 0;
protected override void CreateChildControls()
{
//do stuff here e.g.
LinkButton prevLink = new LinkButton();
prevLink.Text = "< Prev";
prevLink.CommandArgument = (PageIndex - 1).ToString();
prevLink.Command += new CommandEventHandler(PagerLinkCommand);
this.Controls.Add(prevLink);
}
protected void PagerLinkCommand(object sender, CommandEventArgs e)
{
PageIndex = int.Parse(e.CommandArgument.ToString());
CreateChildControls();
}
}
EDIT
The problem here was caused by the fact that the control is used in a Sitecore site and I had forgotten to register the control type in the web.config file with a <typesThatShouldNotBeExpanded>
entry. This entry is used to prevent server controls from having their events messed up by Sitecore - this can cause similar problems for standard server controls such as ListView, GridView and Repeater etc. My web.config was modified as shown below:
<typesThatShouldNotBeExpanded>
<type>System.Web.UI.WebControls.Repeater</type>
<type>System.Web.UI.WebControls.DataList</type>
<type>System.Web.UI.WebControls.GridView</type>
<type>MyNamespace.MyCustomControl</type> <!-- This is the bit I added -->
</typesThatShouldNotBeExpanded>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据我的经验,此类问题通常是由于没有为动态生成的控件分配 ID 造成的。
In my experience this sort of problem is usually due to not assigning an ID to dynamically generated controls.
抱歉...这不是一个完整的答案,而是一个调试建议,对于评论来说太长了:
在浏览器中保存页面的 HTML 副本以进行初始加载、回发加载和第二次回发。然后使用您最喜欢的比较工具比较文件。消除明显的差异,例如搜索结果等。这可以帮助您查明控件 ID、缺少控件等方面的任何问题。
成功动态创建控件的两个绝对关键是
1) 在页面生命周期的正确时间创建它们
2) 在回发时重新创建完全相同的控制层次结构(包括 ID)
Apologies... this is not a complete answer, but a debugging suggestion that is too long for a comment:
In your browser save an HTML copy of your page for initial load, postback load, and second postback. Then compare the files using your favorite comparison tool. Eliminate obvious differences like search results, etc. This can help you pinpoint any issues with control IDs, missing controls, etc.
The two absolute keys to successful dynamically created controls are
1) Creating them at the correct time during the page lifecycle
2) Re-creating the EXACT SAME control hierarchy (including IDs) on postback
要获得正确的控件树,请覆盖 Controls 属性并调用 EnsureChildControls,并调用 EnsureChildControls 而不是 PagerLinkCommand 内的 CreateChildControls。
To get the proper control tree override the Controls property and call the EnsureChildControls, and also call the EnsureChildControls and not the CreateChildControls inside the PagerLinkCommand.
造成此行为的原因并非服务器控件本身,而是与 Sitecore 相关。为了使 Sitecore 不干扰服务器控制回发,需要在 web.config 文件的
typesThatShouldNotBeExpanded
部分下添加一个条目,如下所示。The reason for this behaviour was not down to the server control itself, but was Sitecore-related. In order for Sitecore to not interfere with server control postbacks, it is necessary to add an entry under the
typesThatShouldNotBeExpanded
section in the web.config file as shown below.