簡體   English   中英

Asp.NET自定義服務器控件事件處理程序不會在第二次回發時觸發

[英]Asp.NET custom server control event handler not firing on second postback

我正在開發一個繼承CompositeControl類的Asp.NET(.NET 3.5)中的自定義服務器控件。 在我的控制范圍內,我重寫了CreateChildControls()方法,以生成html和Asp.NET服務器控件的混合。 添加的一些Asp.NET控件是LinkButton (每個LinkButton都將其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>

根據我的經驗,這種問題通常是由於沒有為動態生成的控件分配ID。

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

道歉......這不是一個完整的答案,而是一個對評論來說太長的調試建議:

在瀏覽器中保存頁面的HTML副本,以進行初始加載,回發加載和第二次回發。 然后使用您最喜歡的比較工具比較文件。 消除顯而易見的差異,如搜索結果等。這可以幫助您查明控件ID,缺少控件等的任何問題。

成功動態創建控件的兩個絕對鍵是
1)在頁面生命周期中的正確時間創建它們
2)在回發時重新創建EXACT SAME控制層次結構(包括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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM