Jonathan Wood
Jonathan Wood

Reputation: 67193

Single Reference to CSS File from ASCX Control

I'm writing an ASCX control that needs to reference both a JavaScript file and a CSS file.

Obviously, I only want the host page to reference these files once. So I'm using Page.ClientScript.RegisterClientScriptInclude() to reference the JavaScript file. The CSS file, however, is a bit more complicated.

I thought maybe I could do the following:

if (!Page.ClientScript.IsClientScriptIncludeRegistered(ScriptManagerJsKey))
{
    Page.ClientScript.RegisterClientScriptInclude(this.GetType(), ScriptManagerJsKey, ResolveClientUrl("~/javascript/PaymentSchedule.js"));

    HtmlLink cssLink = new HtmlLink();
    cssLink.Href = "~/css/PaymentSchedule.css";
    cssLink.Attributes["rel"] = "stylesheet";
    cssLink.Attributes["type"] = "text/css";
    Page.Header.Controls.Add(cssLink);
}

The idea here was to add an HtmlLink to reference the CSS file in the page header, but only once. Since I believe this code will only add the JavaScript reference once, I thought this would do the trick.

However, this actually adds the reference to the CSS file twice in the head section of the file.

Has anyone found a trick to referencing a CSS file only once from an ASCX control?

Upvotes: 0

Views: 431

Answers (3)

Jonathan Wood
Jonathan Wood

Reputation: 67193

I'm not sure why my original code shouldn't work. It seems like IsClientScriptIncludeRegistered() should prevent the code within my if statement from running more than once.

At any rate, here's how I worked around it:

private static readonly string ScriptManagerJsKey = "PaymentScheduleControls.ascx.js";
private static readonly string CssLinkId = "PaymentScheduleControlCssLink";

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.ClientScript.IsClientScriptIncludeRegistered(ScriptManagerJsKey))
    {
        Page.ClientScript.RegisterClientScriptInclude(this.GetType(), ScriptManagerJsKey, ResolveClientUrl("~/javascript/PaymentSchedule.js"));
        if (Page.Header.FindControl(CssLinkId) == null)
        {
            HtmlLink cssLink = new HtmlLink();
            cssLink.ID = CssLinkId;
            cssLink.Href = "~/css/PaymentSchedule.css";
            cssLink.Attributes["rel"] = "stylesheet";
            cssLink.Attributes["type"] = "text/css";
            Page.Header.Controls.Add(cssLink);
        }
    }
}

This code simply sets an explicit ID for the CSS link control. It then takes steps to only add the link if it isn't already added. Seems to work okay.

Upvotes: 0

cmd.prompt
cmd.prompt

Reputation: 954

You can use HttpContext.Current.Items for this kind of stuff.

private void UserControl_Init(object sender, EventArgs e)
{
    this.addStyleSheet("~/css/PaymentSchedule.css");
}

private void addStyleSheet(String href)
{
    if (String.IsNullOrWhiteSpace(Convert.ToString(HttpContext.Current.Items[href])))
    {
        HttpContext.Current.Items[href] = href;
        HtmlLink sheet = new HtmlLink() {
            Href = href
        };
        sheet.Attributes["rel"] = "stylesheet";
        sheet.Attributes["type"] = "text/css";
        this.Page.Header.Controls.Add(sheet);
    }
}

Upvotes: 1

Sean
Sean

Reputation: 46

Have you tried adding the attributes like this?

HtmlLink cssLink = new HtmlLink();
cssLink.Href = "~/css/PaymentSchedule.css";
cssLink.Attributes.Add("rel", "stylesheet");
cssLink.Attributes.Add("type", "text/css")
Page.Header.Controls.Add(cssLink);

Upvotes: 0

Related Questions