Wie mit der Styleplaceholder und Style-Steuerung Steuerung von Stylesheets in ASP.NET Themen nehmen

StackOverflow https://stackoverflow.com/questions/328763

Frage

Update: Dieser verwandelte sich in eine Blog-Post, mit aktualisierten Links und Code, über auf meinem Blog: https://egilhansen.com/2008 / 12/01 / how-to-take-control-of-style-sheets-in-asp-net-Themen-mit-dem-Styleplaceholder-and-style-control /


Das Problem ist ziemlich einfach. Wenn ASP.NET Themes verwenden, haben Sie nicht viel sagen, wie Sie Ihre Stylesheets auf die Seite gerendert werden.

Die Render-Engine fügt alle Stylesheets Sie in Ihren Themen haben Ordner in alphabetischer Reihenfolge, die

Wir alle, die Reihenfolge der Stylesheets wissen wichtig sind, asp.nets zum Glück können Mängel mit 01 durch das Vorsetzen der Stylesheets umgangen werden, 02, ..., 99, und so zwingt die Reihenfolge Sie (siehe Rusty Swayne wollen Blogeintrag auf die Technik für weitere Informationen).

Dies ist besonders wichtig, wenn Sie einen Reset-Stylesheet verwenden, die ich sehr empfehlen; es macht es viel einfacher in allen Browsern eine Website in einer einheitlichen Form, Stil (einen Blick auf Reset Reloaded von Eric Meyer ).

Sie verpassen auch aus der Möglichkeit, einen Medientyp angeben (zum Beispiel Bildschirm, Druck, Projektion, Braille-Schrift, Sprache). Und wenn Sie es vorziehen, Stylesheets gehören die @import Methode verwenden, werden Sie auch in der Kälte aus.

Eine weitere fehlende Option ist Conditional Comment, was besonders nützlich ist, wenn Sie einen „ie-fix.css“ Stylesheet verwenden.

Bevor ich erklären, wie die Styleplaceholder und Style-Steuerung die oben genannten Probleme zu lösen, Kredit, in dem Kredit passend ist, ist meine Lösung von Per Zimmerman Blog-Post zu diesem Thema.

Die Styleplaceholder Steuerung im Kopfbereich der Masterseite oder Seite platziert. Es kann einen oder mehr Style-Steuerelemente ausgeführt, und Stile von der Render-Engine standardmäßig hinzugefügt entfernen, und fügt ihre eigenen (es wird nur Stile entfernen aus dem aktuellen aktiven Thema hinzugefügt).

Die Style-Steuerung können beide Host-Inline-Styles in-between es öffnen und Tags und einen Verweis auf eine externe Stylesheet-Datei durch seine CssUrl Eigenschaft zu schließen. Mit anderen Eigenschaften steuern Sie, wie das Stylesheet es auf der Seite macht.

Lassen Sie mich ein Beispiel zeigen. Betrachten wir ein einfaches Website-Projekt mit einer Masterseite und ein Thema mit drei Stylesheets - 01reset.css, 02style.css, 99iefix.cs. Hinweis: ich genannt habe sie mit prefixing Technik bereits beschrieben, wie es für ein besseres Design-Zeit Erlebnis macht. Auch ist die Tagpräfix der Custom Controls „ass“.

In der Header-Bereich Master-Seite hinzu:

<ass:StylePlaceHolder ID="StylePlaceHolder1" runat="server" SkinID="ThemeStyles" />

In Ihrem Themenverzeichnis, fügen Sie eine Skin-Datei (zum Beispiel Styles.skin) und fügen Sie den folgenden Inhalt:

<ass:StylePlaceHolder1runat="server" SkinId="ThemeStyles">
    <ass:Style CssUrl="~/App_Themes/Default/01reset.css" />
    <ass:Style CssUrl="~/App_Themes/Default/02style.css" />
    <ass:Style CssUrl="~/App_Themes/Default/99iefix.css" ConditionCommentExpression="[if IE]" />
</ass:StylePlaceHolder1>

Das ist im Grunde es. Es gibt mehr Eigenschaften auf dem Style-Steuerelement, das verwendet werden kann, die Wiedergabe zu steuern, aber das ist die Grundeinstellung. Mit dem im Ort, können Sie einfach ein anderes Thema hinzufügen und alle Stile ersetzen, da Sie nur eine andere Skin-Datei enthalten müssen.

Nun zu dem Code, der das alles möglich macht. Ich muss zugeben, dass die Design-Zeit Erfahrung einige Macken haben. Es ist wahrscheinlich aufgrund der Tatsache, dass ich in Schreiben von benutzerdefinierten Kontrollen nicht sehr bewandert bin (in der Tat, diese beide sind meine erste Versuche), so würde ich sehr gerne Eingang am nächsten. In einem aktuellen Projekt WCAB / WCSF basierend Ich entwickle, ich Fehler wie dies in Visual Studios Entwurfsansicht sehe, und ich habe keine Ahnung, warum. Die Website erstellt und allesfunktioniert online.

Beispiel für Design Zeitfehler in Visual Studio http: //www.egil .dk / wp-content / Styleplaceholder-error.jpg

Im Folgenden ist der Code für die Steuerung Styleplaceholder:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;

[assembly: TagPrefix("Assimilated.Extensions.Web.Controls", "ass")]
namespace Assimilated.WebControls.Stylesheet
{
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [DefaultProperty("SkinID")]
    [ToolboxData("<{0}:StylePlaceHolder runat=\"server\" SkinID=\"ThemeStyles\"></{0}:StylePlaceHolder>")]
    [ParseChildren(true, "Styles")]
    [Themeable(true)]
    [PersistChildren(false)]
    public class StylePlaceHolder : Control
    {
        private List<Style> _styles;

        [Browsable(true)]
        [Category("Behavior")]
        [DefaultValue("ThemeStyles")]
        public override string SkinID { get; set; }

        [Browsable(false)]
        public List<Style> Styles
        {
            get
            {
                if (_styles == null)
                    _styles = new List<Style>();
                return _styles;
            }
        }

        protected override void CreateChildControls()
        {
            if (_styles == null)
                return;

            // add child controls
            Styles.ForEach(Controls.Add);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            // get notified when page has finished its load stage
            Page.LoadComplete += Page_LoadComplete;
        }

        void Page_LoadComplete(object sender, EventArgs e)
        {
            // only remove if the page is actually using themes
            if (!string.IsNullOrEmpty(Page.StyleSheetTheme) || !string.IsNullOrEmpty(Page.Theme))
            {
                // Make sure only to remove style sheets from the added by
                // the runtime form the current theme.
                var themePath = string.Format("~/App_Themes/{0}",
                                              !string.IsNullOrEmpty(Page.StyleSheetTheme)
                                                  ? Page.StyleSheetTheme
                                                  : Page.Theme);

                // find all existing stylesheets in header
                var removeCandidate = Page.Header.Controls.OfType<HtmlLink>()
                    .Where(link => link.Href.StartsWith(themePath)).ToList();

                // remove the automatically added style sheets
                removeCandidate.ForEach(Page.Header.Controls.Remove);
            }
        }

        protected override void AddParsedSubObject(object obj)
        {
            // only add Style controls
            if (obj is Style)
                base.AddParsedSubObject(obj);
        }

    }
}

Und der Code für die Style-Steuerung:

using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;

[assembly: TagPrefix("Assimilated.Extensions.Web.Controls", "ass")]
namespace Assimilated.WebControls.Stylesheet
{
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [DefaultProperty("CssUrl")]
    [ParseChildren(true, "InlineStyle")]
    [PersistChildren(false)]
    [ToolboxData("<{0}:Style runat=\"server\"></{0}:Style>")]
    [Themeable(true)]
    public class Style : Control
    {
        public Style()
        {
            // set default value... for some reason the DefaultValue attribute do
            // not set this as I would have expected.
            TargetMedia = "All";
        }

        #region Properties

        [Browsable(true)]
        [Category("Style sheet")]
        [DefaultValue("")]
        [Description("The url to the style sheet.")]
        [UrlProperty("*.css")]
        public string CssUrl
        {
            get; set;
        }

        [Browsable(true)]
        [Category("Style sheet")]
        [DefaultValue("All")]
        [Description("The target media(s) of the style sheet. See http://www.w3.org/TR/REC-CSS2/media.html for more information.")]
        public string TargetMedia
        {
            get; set;
        }

        [Browsable(true)]
        [Category("Style sheet")]
        [DefaultValue(EmbedType.Link)]
        [Description("Specify how to embed the style sheet on the page.")]
        public EmbedType Type
        {
            get; set;
        }

        [Browsable(false)]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public string InlineStyle
        {
            get; set;
        }

        [Browsable(true)]
        [Category("Conditional comment")]
        [DefaultValue("")]
        [Description("Specifies a conditional comment expression to wrap the style sheet in. See http://msdn.microsoft.com/en-us/library/ms537512.aspx")]
        public string ConditionalCommentExpression
        {
            get; set;
        }

        [Browsable(true)]
        [Category("Conditional comment")]
        [DefaultValue(CommentType.DownlevelHidden)]
        [Description("Whether to reveal the conditional comment expression to downlevel browsers. Default is to hide. See http://msdn.microsoft.com/en-us/library/ms537512.aspx")]
        public CommentType ConditionalCommentType
        {
            get; set;
        }

        [Browsable(true)]
        [Category("Behavior")]
        public override string SkinID { get; set; }

        #endregion

        protected override void Render(HtmlTextWriter writer)
        {            
            // add empty line to make output pretty
            writer.WriteLine();

            // prints out begin condition comment tag
            if (!string.IsNullOrEmpty(ConditionalCommentExpression))
                writer.WriteLine(ConditionalCommentType == CommentType.DownlevelRevealed ? "<!{0}>" : "<!--{0}>",
                                 ConditionalCommentExpression);

            if (!string.IsNullOrEmpty(CssUrl))
            {               
                // add shared attribute
                writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/css");

                // render either import or link tag
                if (Type == EmbedType.Link)
                {
                    // <link href=\"{0}\" type=\"text/css\" rel=\"stylesheet\" media=\"{1}\" />
                    writer.AddAttribute(HtmlTextWriterAttribute.Href, ResolveUrl(CssUrl));
                    writer.AddAttribute(HtmlTextWriterAttribute.Rel, "stylesheet");
                    writer.AddAttribute("media", TargetMedia);
                    writer.RenderBeginTag(HtmlTextWriterTag.Link);
                    writer.RenderEndTag();
                }
                else
                {
                    // <style type="text/css">@import "modern.css" screen;</style>
                    writer.RenderBeginTag(HtmlTextWriterTag.Style);
                    writer.Write("@import \"{0}\" {1};", ResolveUrl(CssUrl), TargetMedia);
                    writer.RenderEndTag();
                }
            }

            if(!string.IsNullOrEmpty(InlineStyle))
            {
                // <style type="text/css">... inline style ... </style>
                writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/css");
                writer.RenderBeginTag(HtmlTextWriterTag.Style);
                writer.Write(InlineStyle);
                writer.RenderEndTag();
            }

            // prints out end condition comment tag
            if (!string.IsNullOrEmpty(ConditionalCommentExpression))
            {
                // add empty line to make output pretty
                writer.WriteLine();
                writer.WriteLine(ConditionalCommentType == CommentType.DownlevelRevealed ? "<![endif]>" : "<![endif]-->");
            }
        }
    }

    public enum EmbedType
    {        
        Link = 0,
        Import = 1,
    }

    public enum CommentType
    {
        DownlevelHidden = 0,
        DownlevelRevealed = 1
    }
}

Also, was denkt ihr? Ist dies eine gute Lösung für das asp.net Thema Problem? Und was ist mit dem Code? Ich würde wirklich eine Eingabe an mag es, vor allem in Bezug auf die Design-Zeit Erfahrung.

Ich lud hoch gezippte Version der Visual Studio-Lösung das enthält das Projekt, falls es jemanden interessiert.

Mit freundlichen Grüßen, Egil.

War es hilfreich?

Lösung

Können Sie die Antwort auf meine eigene Frage.

Der Grund für die Rendering-Fehler, die ich im Entwurfsmodus bin immer, ist ein offensichtlicher Fehler in Visual Studio SP1, , die Microsoft noch beheben .

So ist der obige Code funktioniert wie erwartet, auch im Design-Modus, solange Sie nur die benutzerdefinierte Steuerelemente in einem vorher kompilierten Assembly enthalten, und nicht durch ein anderes Projekt in der gleichen Lösung.

Siehe den Link oben für eine ausführlichere Erklärung, wie und warum.

Andere Tipps

Funktioniert sehr glatt.

Für mich diejenigen, die wie die nie hier Syntax von <% Tags erinnern, was Sie brauchen, um die Spitze der Masterseite Definition und die Skin-Datei hinzufügen, um den Namensraum zu registrieren.

<%@ Register TagPrefix="ass" Namespace="Assimilated.WebControls.Stylesheet" %>

Ich bin mir nicht sicher, ob ich möchte, dass viel ‚Arsch‘ über meinen Code, sonst aber ich mag es.

Oh, und wenn dies wirklich Ihre erste eigene Kontrolle gute Arbeit geleistet. Ich weiß, dass es von jemandem anderen Code inspiriert wurde, aber es zumindest erscheint hat alle die richtigen Attribute und Schnittstellen.

Re:. Mit spezifischen Medien CSS-Datei, die Sie @media CSS-Anweisung verwenden können, funktioniert

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top