Asp.NET 自定义服务器控件事件处理程序在第二次回发时未触发



我正在 Asp.NET(.NET 3.5)中开发一个自定义服务器控件,它继承了CompositeControl类。 在我的控件中,我重写了 CreateChildControls() 方法以生成 html 和 Asp.NET 服务器控件的混合。 添加的一些 Asp.NET 控件是 LinkButton s(每个控件都将其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 站点中使用,而我忘记使用 <typesThatShouldNotBeExpanded> 条目在 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>

根据我的经验,此类问题通常是由于没有为动态生成的控件分配 ID。

LinkButton prevLink = new LinkButton();
prevLink.ID = "prevLink";

道歉...这不是一个完整的答案,而是一个调试建议,太长了,无法发表评论:

在浏览器中保存页面的 HTML 副本,用于初始加载、回发加载和第二次回发。 然后使用您喜欢的比较工具比较文件。 消除明显的差异,如搜索结果等。 这可以帮助您查明控件 ID 、缺少控件等的任何问题。

成功动态创建的控件的两个绝对关键是
1) 在页面生命周期
中的正确时间创建它们2) 在回发时重新创建完全相同的控件层次结构(包括 ID)

若要获取正确的控件树,请覆盖 Controls 属性并调用 EnsureChildControls,同时调用 EnsureChildControls,而不是 PagerLinkCommand 中的 CreateChildControls。

    /// <summary>
    /// Gets controls.
    /// </summary>
    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return base.Controls;
        }
    }
    /// <summary>
    /// Create child controls.
    /// </summary>
    protected override void CreateChildControls()
    {
        this.Controls.Clear();
        //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());
      EnsureChildControls();
    }        

这种行为的原因不是服务器控件本身,而是与 Sitecore 相关。 为了使 Sitecore 不干扰服务器控制回发,有必要在 web.config 文件的typesThatShouldNotBeExpanded部分下添加一个条目,如下所示。

<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>

最新更新