ASP.NET:可以创建包含内部标记内容的UserControl吗?

时间:2008-12-17 16:17:33

标签: c# asp.net user-controls

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

用户控件:

<%@ 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>

但是,如果我这样做,我将无法访问litText的属性,我能够达到它的唯一方法是使用FindControl,我想避免。

如果我能以这种或那种方式达到我的目标,任何人都会对此有所暗示吗?

谢谢

2 个答案:

答案 0 :(得分:3)

好的我在这里修复了我使用的解决方案:

在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文件myLastContol中命名了我的最后一个控件,以便知道在innerHTML注入之前控件是什么,因为我不知道我收到了什么。该过程基本上是在UserControl的控件中循环,当你到达UserControl的末尾时,之后的所有内容都是来自父对象的innerHTML,所以把它们移动到我想要的占位符。

我希望这会对某人有所帮助。

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

答案 1 :(得分:0)

在用户控件的代码隐藏文件中添加公共属性。如果您需要设计时间支持,则涉及更多工作,但对于您所概述的简单方案,它应该足够了。

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