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

3
我正在尝试做一些谷歌无法回答的事情。我正在尝试创建一个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,而我想避免使用它。是否有人对此有提示,我是否可以通过其他方式实现我的目标?谢谢。

最终目标是什么?这个解决方案可能对你的需求来说太复杂了。 - Scott Cowan
2个回答

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,因此将其移到我想要的占位符中。
我希望这会帮助某些人。
以下是我用来实现目标的一些来源: 注册UpdatePanel

0
在用户控件的代码后台文件中添加一个公共属性。如果需要设计时支持,则需要更多工作,但对于像您概述的简单场景,这应该足够了。
然后只需在父页面中访问它以设置值,并在用户控件中读取它并使用该值来呈现所需内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接