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

时间:2011-05-13 15:08:21

标签: c# asp.net postback sitecore custom-server-controls

我正在开发一个继承CompositeControl类的Asp.NET(.NET 3.5)中的自定义服务器控件。在我的控制范围内,我正在覆盖CreateChildControls()方法,以生成混合的html和Asp.NET服务器控件。添加的一些Asp.NET控件是LinkButton s(每个控件都将Command事件处理程序设置为我控件中的方法)。我发现的是,第一次点击其中一个LinkBut​​ton时,会触发回发并正确触发事件处理程序方法。在此事件处理程序方法内部,显式调用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文件中使用<typesThatShouldNotBeExpanded>条目注册控件类型。此条目用于防止服务器控件使其事件被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>

4 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

道歉......这不是一个完整的答案,而是一个对评论来说太长的调试建议:

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

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

答案 2 :(得分:0)

要获取正确的控制树,请覆盖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();
    }        

答案 3 :(得分:0)

此行为的原因不是服务器控件本身,而是与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>