2017-08-11 31 views
0

編輯:可悲的是,似乎沒有人知道。也許這將有助於澄清我的困境:我試圖實現我自己的DataList類型的控件,支持從ItemTemplate切換到EditItemTemplate。單擊EditItemTemplate內的按鈕時會出現問題 - 除非再次單擊,否則不會觸發處理程序!重新綁定ASP.NET 4.0中的事件處理程序「模板控制」?

對不起,這篇冗長的文章。代碼完整,但希望沒有任何分心。

我試圖創建我自己的用戶控件接受多個模板。我部分遵循Manning的「ASP.NET 4.0 in Practice」中的技巧39和40。它似乎工作,除了模板內的按鈕沒有綁定到處理程序,直到第二次點擊(一個額外的回發後)。

涉及到四個文件。 Default.aspx的:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 

    <%@ Register Src="~/TheTemplate.ascx" TagPrefix="TT" TagName="TheTemplate" %> 

    <!DOCTYPE html> 

    <html xmlns="http://www.w3.org/1999/xhtml"> 
    <head runat="server"> 
      <title></title> 
    </head> 
    <body> 
      <form id="form1" runat="server"> 
        <div> 
          <TT:TheTemplate ID="tt" runat="server"> 
            <ATemplate> 
              <p>This is template A</p> 
              <asp:Button ID="TemplateAButton" OnClick="TemplateAButton_Click" runat="server" Text="Template A Button" /> 
            </ATemplate> 
            <BTemplate> 
              <p>This is template B</p> 
              <asp:Button ID="TemplateBButton" OnClick="TemplateBButton_Click" runat="server" Text="Template B Button" /> 
            </BTemplate> 
          </TT:TheTemplate> 
          <br /> 
          <asp:Button ID="ToggleTemplate" Text="Toggle Template" OnClick="ToggleTemplate_Click" runat="server" /> 
        </div> 
      </form> 
    </body> 
    </html> 

Default.aspx.cs:

using System; 

    public partial class _Default : System.Web.UI.Page 
    { 
      protected void Page_Load(object sender, EventArgs e) 
      { 
        Trace.IsEnabled = true; 
        tt.DataBind(); 
      } 


      protected void ToggleTemplate_Click(object sender, EventArgs e) 
      { 
        tt.TemplateName = (tt.TemplateName == "A") ? "B" : "A"; 
        tt.DataBind(); 
      } 


      public void TemplateAButton_Click(object sender, EventArgs e) 
      { 
        Trace.Write("TemplateAButton_Click"); 
      } 


      public void TemplateBButton_Click(object sender, EventArgs e) 
      { 
        Trace.Write("TemplateBButton_Click"); 
      } 
    } 

而且用戶控制,TheTemplate.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TheTemplate.ascx.cs" Inherits="TheTemplate" %> 

    <p>Using template <asp:Literal Text="<%# TemplateName %>" ID="Literal1" runat="server"></asp:Literal></p> 
    <asp:Placeholder runat="server" ID="PlaceHolder1" /> 

最後,TheTemplate.ascx.cs:

using System; 
    using System.Web.UI; 

    [ParseChildren(true)] 
    public class TheTemplateContainer : Control, INamingContainer 
    { 
      private TheTemplate parent; 
      public TheTemplateContainer(TheTemplate parent) 
      { 
        this.parent = parent; 
      } 
    } 


    public partial class TheTemplate : System.Web.UI.UserControl, INamingContainer 
    { 
      public string TemplateName 
      { 
        get { return (string)(ViewState["TemplateName"] ?? "A"); } 
        set { ViewState["TemplateName"] = value; } 
      } 


      [TemplateContainer(typeof(TheTemplateContainer))] 
      [PersistenceMode(PersistenceMode.InnerProperty)] 
      public ITemplate ATemplate { get; set; } 


      [TemplateContainer(typeof(TheTemplateContainer))] 
      [PersistenceMode(PersistenceMode.InnerProperty)] 
      public ITemplate BTemplate { get; set; } 


      protected override void OnDataBinding(EventArgs e) 
      { 
        TheTemplateContainer container = new TheTemplateContainer(this); 
        if (TemplateName == "A") 
          ATemplate.InstantiateIn(container); 
        else if (TemplateName == "B") 
          BTemplate.InstantiateIn(container); 

        PlaceHolder1.Controls.Clear(); 
        PlaceHolder1.Controls.Add(container); 

        EnsureChildControls(); 
        base.OnDataBinding(e); 
      } 
    } 

當你第一次運行它時,你會看到ATempla TE使用:

enter image description here

如果你點擊切換模板按鈕,所有的文字被正確地呈現:

enter image description here

但點擊或者「模板按鈕」或「模板B鍵」不會觸發第一次嘗試的onclick處理程序:

enter image description here

它會在第二次點擊工作:

enter image description here

該問題是否已做.DataBind()被調用在哪裏?

回答

0

我不太確定我是否理解,但問題與新增控件如何通過「追趕」事件有關。刪除PlaceHolder1並以編程方式添加它解決了這個問題。 TheTemplate.ascx變爲:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TheTemplate.ascx.cs" Inherits="TheTemplate" %> 

    <p>Using template 
      <asp:Literal Text="<%# TemplateName %>" ID="Literal1" runat="server"></asp:Literal></p> 

...在TheTemplate.ascx.cs,這樣的替換OnDataBinding:

protected override void OnDataBinding(EventArgs e) 
{ 
    TheTemplateContainer container = new TheTemplateContainer(this); 
    if (TemplateName == "A") 
     ATemplate.InstantiateIn(container); 
    else if (TemplateName == "B") 
     BTemplate.InstantiateIn(container); 

    System.Web.UI.WebControls.PlaceHolder PlaceHolder1 = new System.Web.UI.WebControls.PlaceHolder(); 
    //PlaceHolder1.Controls.Clear(); 
    PlaceHolder1.Controls.Add(container); 
    this.Controls.Clear(); 
    this.Controls.Add(PlaceHolder1); 

    EnsureChildControls(); 
    base.OnDataBinding(e); 
} 

在未來,如果我覺得我需要動態地添加控件,我也將動態創建一個PlaceHolder並將其用作根。當填充PlaceHolder時,我會將它添加到頁面中。

相關問題