2

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

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,那将是小菜一碟。

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


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

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

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

与上述相同,但将 WmlCard 的属性InnerText类型从更改StringList(Of Object)
'System.Collections.IList' 中不允许文字内容('Any text.')。

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

如果我将 WmlCard 更改为继承System.Web.UI.WebControls.PlaceHolder而不是System.Web.UI.UserControl
此处不允许使用“...UserControl.WmlCard”,因为它不扩展类“System.Web.UI.UserControl”。

4

4 回答 4

3

找到了一个有效的方法:

1) 什么都不放在我的控制范围内 (WmlCard.ascx)。

2) 将属性添加<ParseChildren(False)>到 WmlCard。

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

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

于 2011-03-03T16:56:44.960 回答
0

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

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

于 2011-03-03T16:39:43.753 回答
0

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

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

 [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。我很难看到你的实际问题。

于 2011-03-03T16:43:29.033 回答
0

得到这个工作足够简单。

[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 内容的所有内容。

于 2019-10-18T17:39:54.447 回答