2017-08-11 26 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时,我会将它添加到页面中。

相关问题