I am using a contentplaceholder control in a master page to allow the content editor to specify the URL of an image used as a background to a div.
<div id="content-left-column"
style="background-image: url('<wc:UrlContentPlaceHolder runat='server' ID='leftCo开发者_开发技巧ntentBackgroundUrl'></wc:UrlContentPlaceHolder>');">
The placeholder is referenced on the content page like:
<asp:Content ID="Content1" ContentPlaceHolderID="leftContentBackgroundUrl" runat="server">/img/left-content.jpg</asp:Content>
The page renders just fine using this approach. However, when I look at the content page in source view, the ContentPlaceHolderId attribute value is underlined and there is a warning "Could not find 'leftContentBackgroundUrl' in the current master page or pages."
Design view will not render the content page due to this error.
Is there a way to use ContentPlaceHolder for attribute values such that no errors are reported in the Visual Studio editor and design surface?
*Note. I am aware of the issues with this approach. If the content editor puts in spaces, carriage returns or performs a document format in visual studio, the rendered attribute value is broken. I have created a subclass of ContentPlaceHolder that trims its values and uses ResolveClientUrl to address these issues. For the sake of discussion I have described the issue which affects a normal ContentPlaceHolder control.
The following stack overflow question addresses the fact that ContentPlaceHolder can be used with attribute values but does not address the design surface issues. Why can't I use a ContentPlaceholder inside HTML attributes in ASP.NET?
I don't believe that's how ContentPlaceHolders where meant to be used. I would strongly advise you to use inline code for this.
Main.master:
<div id="content-left-column"
style="background-image: url(<%: LeftContentBackgroundURL %>);">
Main.master.cs:
public string LeftContentBackgroundURL { get; set; }
In the ContentPage you then just use the @MasterType directive and set the Property in Codebehind.
Content.aspx:
<%@ MasterType VirtualPath="~/Main.master" %>
Content.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
this.Master.LeftContentBackgroundURL = "/img/left-content.jpg";
}
This solution was inspired by @atticae's response.
On the master page, I included a normal ContentPlaceholder control with visible="false". Where I was previously using that ContentPlaceholder as an attribute value, I instead reference a property of the MasterPage, LeftBackgroundImageUrl.
<asp:ContentPlaceHolder runat='server' ID='leftContentBackgroundUrl' Visible="false"/>
<div id="content-left-column" style="background-image: url('<%: LeftBackgroundImageUrl%>');">
Using a subclass of ContentPlaceholder causes errors in the design surface of content pages which is why I went back to using a normal ContentPlaceholder.
The LeftBackgroundImageUrl property code looks like:
ReadOnly Property LeftBackgroundImageUrl As String
Get
Return RenderResolvedUrl(leftContentBackgroundUrl)
End Get
End Property
Private Function RenderedResolvedUrl(control As Control) As String
Dim visible As Boolean = control.Visible
control.Visible = True
Dim result As String = Nothing
Using writer As New System.IO.StringWriter()
Using htmlWriter As New System.Web.UI.HtmlTextWriter(writer)
control.RenderControl(htmlWriter)
htmlWriter.Flush()
End Using
result = Page.ResolveClientUrl(writer.ToString.Trim).Trim
End Using
control.Visible = visible
Return result
End Function
This solution allows the image url to be specified declaratively, and without the user having to add a MasterType directive. This is not perfect in the sense that it does not, at edit/design time, validate that the content the editor provides is just a URL or application relative URL. But, it does keep the user from having to write code.
精彩评论