代码之家  ›  专栏  ›  技术社区  ›  baptiste

ASP.NET:是否可以创建包含在标记内容中的用户控件?

  •  3
  • baptiste  · 技术社区  · 16 年前

    我正在努力实现谷歌无法给出答案的目标。我正在尝试创建一个ASP.NET用户控件,当我将内容放入它的“打开-关闭”标记时,它将包含它,以便我仍然能够通过父级的ID访问它的内容。下面是我想要实现的一个例子。

    Usercontrol:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="ctrlGENE_CollapsiblePanel.ascx.cs"
        Inherits="Controls_GenericsControls_ctrlGENE_CollapsiblePanel" %>
    <asp:Panel ID="pnlHeader" CssClass="SnapPanelHeader" runat="server">
        <h3>
            <asp:Literal ID="litTitle" Text='<%# Text %>' runat="server" />
        </h3>
        <div class="SnapPanelHeader-img">
            <img id="imgOpenClose" src="/images/application/close.jpg" alt="" />
        </div>
    </asp:Panel>
    <asp:PlaceHolder runat="server" ID="pnlContent">
    // **HERE I WANT TO INCLUDE THE INSIDE MARKUP**
    </asp:PlaceHolder>
    <act:CollapsiblePanelExtender runat="server" TargetControlID="pnlContent" ImageControlID="imgOpenClose"
        ExpandControlID="imgOpenClose" CollapseControlID="imgOpenClose" CollapsedImage="/images/application/open.jpg"
        ExpandedImage="/images/application/close.jpg" CollapsedSize="0" TextLabelID="litTitle">
    </act:CollapsiblePanelExtender>
    

    包含控件的父页:

    <uc:MyUserControl ID="clpTest" runat="server">
         <asp:Literal ID="litText" runat="server" />
    </uc:MyUserControl>
    

    这样,我就可以在parent.cs文件中执行以下操作:

    litText.Text = "Anything";
    

    我知道我们可以实现类似于itemplate接口的功能,如下所示: http://msdn.microsoft.com/en-us/library/36574bf6.aspx

    就像这样:

    <uc:MyUserControl ID="clpTest" runat="server">
         <ItemTemplate>
              <asp:Literal ID="litText" runat="server" />
         </ItemTemplate>
    </uc:MyUserControl>
    

    但是如果我这样做的话,我就无法访问Littlext的属性,我唯一能访问它的方法就是使用findcontrol,我想避免这种情况。

    如果我能以这样或那样的方式达到我的目标,有人对此有什么提示吗?

    谢谢你

    2 回复  |  直到 16 年前
        1
  •  3
  •   baptiste    16 年前

    好的,我修正了它,这里是我使用的解决方案:

    在myuserconstrol.ascx文件中,我放置了一个占位符,希望innerhtml显示:

    <asp:PlaceHolder runat="server" ID="plhContent" />
    

    然后在myusercontrol.ascx.cs文件中,我将这些属性添加到类中:

    [ParseChildren(false)]
    [PersistChildren(true)]
    

    我在文件中添加了:

    public void RegisterUpdatePanel(UpdatePanel panel)
    {
        MethodInfo m =
            (from methods in typeof (ScriptManager).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
             where methods.Name.Equals("System.Web.UI.IScriptManagerInternal.RegisterUpdatePanel")
             select methods).First();
    
        m.Invoke(ScriptManager.GetCurrent(Page), new object[] {panel});
    }
    
    protected override void CreateChildControls()
    {
        for (int i = 0; i < Controls.Count; i++)
            if (Controls[i] is MyLastControl)
                while (i + 2 < Controls.Count)
                {
                    // In cas there is an updatepanel in the control we are moving
                    // We are registering an event to register the updatepanel
                    // to the scriptmanager again
                    SearchUpdatePanel(Controls[i + 2]);
                    plhContent.Controls.Add(Controls[i + 2]);
                }
        base.CreateChildControls();
    }
    
    private void SearchUpdatePanel(Control control)
    {
        if (control is UpdatePanel)
            control.Unload += updPnl_Unload;
    
        foreach (Control childcontrol in control.Controls)
            SearchUpdatePanel(childcontrol);
    }
    
    protected void updPnl_Unload(object sender, EventArgs e)
    {
        RegisterUpdatePanel((UpdatePanel) sender);
    }
    

    请注意,我在ascx文件my last control中命名了最后一个控件,以了解innerhtml注入之前的控件是什么,因为我不知道收到了什么。这个过程基本上是在用户控件中的控件中循环,当您到达用户控件的末尾时,后面的所有内容都是从父级开始的innerhtml,所以将它们移到我想要的位置。

    我希望这能帮助别人。

    以下是我用来实现目标的一些来源: Registering UpdatePanel

        2
  •  0
  •   Pawel Krakowiak    16 年前

    在用户控件的代码隐藏文件中添加公共属性。如果您需要设计时支持,那么需要做更多的工作,但是对于像您概述的那样的简单场景,这就足够了。

    然后,只需在父页中访问它来设置值并在用户控件中读取它,然后使用该值来呈现需要的内容。