【问题标题】:Asp.net user control with inner controls带有内部控件的 Asp.net 用户控件
【发布时间】:2011-03-03 16:36:31
【问题描述】:

我需要开发一个类似模板的用户控件,它可以接受任意内容,包括其他控件。

WmlCard.ascx

<asp:PlaceHolder ID="phContent" runat="server">
<card id="<%= Me.CardId %>" title="<%= Me.Title %>"> 
<p>
    <%= Me.InnerText %>
</p>
</card>
</asp:PlaceHolder>

会这样使用:
ListaTelefonica.aspx

<%@ Register TagPrefix="sic" TagName="Card" Src="~/path/to/WmlCard.ascx"%>    
<sic:Card ID="BuscaCard" runat="server" CardId="busca" title="Lista Telefônica" Visible="false">
   <asp:Literal ID="SomeLiteral" runat="server" Visible="false">Some text<br /></asp:Literal>
   <asp:Literal ID="RuntimeFilledLiteral" runat="server" Visible="false" /><br /></asp:Literal>
   Any text.
</sic:Card>

不幸的是 Ascx 用户控件必须继承 System.Web.UI.UserControl。例如,如果我可以继承System.Web.UI.WebControls.WebControl,那将是小菜一碟。

我的问题与to this one 类似,但控件应该接受其中的任何其他控件,而不仅仅是文本。


我尝试了&lt;ParseChildren(False)&gt; 并在WmlCard 中覆盖AddParsedSubObject(Object),但这不是解决方案,因为html 是在页面加载之前呈现的,因此在页面的Page_Load 中更改RuntimeFilledLiteral.Text 的值毫无意义,例如。

我遇到的第一个错误:
解析器错误消息:类型“ASP.sic_sicphone_usercontrol_wmlcard_ascx”没有名为“Literal”的公共属性。

添加&lt;PersistenceMode(PersistenceMode.InnerDefaultProperty), ParseChildren(True, "InnerText")&gt;后:
“sic:Card”的“InnerText”属性不允许子对象。

与上述相同,但将 WmlCard 的属性 InnerText 类型从 String 更改为 List(Of Object)
在“System.Collections.IList”中不允许使用文字内容(“任何文本。”) .

添加&lt;ParseChildren(False)&gt; 并覆盖AddParsedSubObject 后:
没有错误消息,但在我有机会更改其内部控件运行时属性之前,WmlCard 的内容已呈现为 html。

如果我将 WmlCard 更改为继承 System.Web.UI.WebControls.PlaceHolder 而不是 System.Web.UI.UserControl:
'...UserControl.WmlCard' 在这里是不允许的,因为它没有扩展类 'System.Web.UI.UserControl '。

【问题讨论】:

    标签: asp.net web-user-controls


    【解决方案1】:

    找到了一个有效的方法:

    1) 在我的控制范围内不要放任何东西 (WmlCard.ascx)。

    2) 为 WmlCard 添加属性&lt;ParseChildren(False)&gt;

    3) 为 WmlCard 上的事件 PreRender 添加了一个处理程序:

    Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
      Dim litBefore As New Literal()
      litBefore.Text = String.Format("<card id=""{0}"" title=""{1}""><p>", Me.CardId, Me.Title)
    
      Dim litAfter As New Literal()
      litAfter.Text = "</p></card>"
    
      Me.Controls.AddAt(0, litBefore)
      Me.Controls.Add(litAfter)
    End Sub
    

    就是这样。一切正常。感谢您的帮助!

    【讨论】:

    • 我注意到我的 sic:Card 控件 (WmlCard) 不能直接包含 &lt;%# %&gt; 或 ` 标记。一个简单的解决方法是将这些内容包含在 Asp:Placeholder(或任何其他控件)中。
    【解决方案2】:

    您需要的是一个模板化的用户控件。

    查看这篇文章了解详细的操作方法:http://msdn.microsoft.com/en-us/library/36574bf6.aspx

    【讨论】:

      【解决方案3】:

      其实你可以创建一个自定义用户控件,继承自占位符,你的问题应该解决了吗?

      您可以按照建议采用模板化控制方式,但我看不出您想要这样做的原因。

       [SupportsEventValidation, DefaultEvent("YourEventName")]
          [ParseChildren(true)]
          [PersistChildren(false)]
          [ToolboxBitmap(typeof(System.Web.UI.WebControls.Panel))]
          public class MyCustomControl : System.Web.UI.WebControls.PlaceHolder, INamingContainer, IPostBackDataHandler, IPostBackEventHandler
      

      您可以重写 Render 方法来控制呈现的 HTML。我很难看到你的实际问题。

      【讨论】:

        【解决方案4】:

        让这个工作很简单。

        [ParseChildren(false)]
        public class CssControl : System.Web.UI.UserControl
        {
            protected override void Render(HtmlTextWriter writer)
            {
                string html = null;
                using(var innerWriter = new System.IO.StringWriter())
                using(var htmlWriter = new HtmlTextWriter(innerWriter))
                {
                    base.Render(htmlWriter);
                    html = innerWriter.GetStringBuilder().ToString();               
                }
        
                var min = ScriptAndCssParser.MinifyCssFromHtml(html);
                writer.Write(min);
            }
        }
        

        就我而言,我的目标是允许母版页级控件具有子 HTML 和服务器控件,例如 asp:content 块。这样,Viewpages 可以将样式表沿链向上传递到母版页。

        然后我想截取所有生成的 HTML,并缩小 CSS 文件。缩小部分超出了这个问题的范围,但上面的ParseChildren(false) 可以防止.aspx 中出现“元素不能包含...”错误,然后在内部编写器上调用base.Render() 可以让您使用现有的 Web 窗体管道为您完成服务器控件和纯 HTML 内容的所有呈现。

        【讨论】:

          猜你喜欢
          • 2010-12-27
          • 1970-01-01
          • 1970-01-01
          • 2016-05-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-15
          相关资源
          最近更新 更多