2008-11-30 12 views
10

अद्यतन के साथ ASP.NET विषय-वस्तु में स्टाइल शीट का नियंत्रण लेने के लिए: यह एक ब्लॉग पोस्ट में बदल गया, अपडेट किए गए लिंक और कोड के साथ, मेरे ब्लॉग पर खत्म हो गया: https://egilhansen.com/2008/12/01/how-to-take-control-of-style-sheets-in-asp-net-themes-with-the-styleplaceholder-and-style-control/StylePlaceHolder और शैली नियंत्रण


समस्या बहुत सरल है। ASP.NET थीम्स का उपयोग करते समय आपके पास बहुत कुछ नहीं है कि पेज पर आपकी स्टाइल शीट कैसे प्रदान की जाती हैं।

रेंडर इंजन < लिंक href = "..." नोटेशन का उपयोग करके, वर्णमाला क्रम में आपके थीम फ़ोल्डर में मौजूद सभी स्टाइल शीट जोड़ता है।

हम सभी जानते हैं कि स्टाइल शीट का क्रम महत्वपूर्ण है, सौभाग्य से asp.nets कमियों को 01, 02, ..., 99 के साथ स्टाइल शीट को उपसर्ग करके अवरुद्ध किया जा सकता है और इस प्रकार आप जिस ऑर्डर को चाहते हैं उसे मजबूर कर सकते हैं (देखें जंगली अधिक जानकारी के लिए तकनीक पर स्वैन blog post)।

यह विशेष रूप से महत्वपूर्ण है यदि आप रीसेट स्टाइल शीट का उपयोग करते हैं, जिसे मैं अत्यधिक अनुशंसा करता हूं; यह ब्राउज़रों में एक सतत रूप में साइट को स्टाइल करना अधिक आसान बनाता है (Reset Reloaded from Eric Meyer पर एक नज़र डालें)।

आप मीडिया प्रकार (जैसे स्क्रीन, प्रिंट, प्रोजेक्शन, ब्रेल, भाषण) निर्दिष्ट करने की संभावना से भी चूक जाते हैं। और यदि आप @import विधि का उपयोग करके स्टाइल शीट्स को शामिल करना पसंद करते हैं, तो आपको ठंड में भी छोड़ दिया जाता है।

एक अन्य गायब विकल्प सशर्त टिप्पणी है, जो विशेष रूप से उपयोगी है यदि आप "यानी-fix.css" स्टाइल शीट का उपयोग करते हैं।

इससे पहले कि मैं समझाऊं कि स्टाइलप्लेसधारक और स्टाइल कंट्रोल उपरोक्त मुद्दों को कैसे हल करता है, क्रेडिट जहां देय है, मेरा समाधान इस विषय पर Per Zimmerman’s blog post से प्रेरित है।

स्टाइलप्लेसहोल्डर नियंत्रण आपके मास्टर पेज या पेज के हेडर सेक्शन में रखा गया है। यह एक या अधिक स्टाइल नियंत्रण होस्ट कर सकता है, और डिफ़ॉल्ट रूप से रेंडर इंजन द्वारा जोड़े गए शैलियों को हटा देगा, और अपना स्वयं का जोड़ देगा (यह केवल वर्तमान सक्रिय थीम से जोड़े गए शैलियों को हटा देगा)।

स्टाइल कंट्रोल दोनों इनलाइन खोलने और समापन टैग के बीच इनलाइन शैलियों को होस्ट कर सकता है और इसकी सीएसएसयूआरएल संपत्ति के माध्यम से बाहरी स्टाइल शीट फ़ाइल का संदर्भ दे सकता है। अन्य गुणों के साथ आप इस बात को नियंत्रित करते हैं कि यह पृष्ठ पर स्टाइल शीट कैसे प्रस्तुत करता है।

मुझे एक उदाहरण दिखाएं। एक मास्टर पेज के साथ एक साधारण वेब साइट प्रोजेक्ट पर विचार करें और तीन स्टाइल शीट्स वाली थीम - 01reset.css, 02style.css, 99iefix.cs। नोट: मैंने उन्हें पहले वर्णित उपसर्ग तकनीक का उपयोग करके नाम दिया है, क्योंकि यह एक बेहतर डिजाइन समय अनुभव के लिए बनाता है। साथ ही, कस्टम नियंत्रण का टैग उपसर्ग "गधा:" है।

मास्टर पृष्ठ के हेडर अनुभाग में, जोड़ें:

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

अपने विषय निर्देशिका में, एक त्वचा फ़ाइल जोड़ने (जैसे Styles.skin) और निम्न सामग्री जोड़ने:

<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> 

है मूल रूप से यह। स्टाइल कंट्रोल पर अधिक गुण हैं जिनका उपयोग प्रतिपादन को नियंत्रित करने के लिए किया जा सकता है, लेकिन यह मूल सेटअप है। उस जगह के साथ, आप आसानी से एक और विषय जोड़ सकते हैं और सभी शैलियों को प्रतिस्थापित कर सकते हैं, क्योंकि आपको केवल एक अलग त्वचा फ़ाइल शामिल करने की आवश्यकता है।

अब कोड के लिए यह सब कुछ होता है। मुझे यह स्वीकार करना होगा कि डिजाइन समय के अनुभव में कुछ quirks है।यह शायद इस तथ्य के कारण है कि मैं कस्टम नियंत्रण लिखने में बहुत कुशल नहीं हूं (वास्तव में, ये दोनों मेरे पहले प्रयास हैं), इसलिए मुझे निम्नलिखित पर इनपुट पसंद आएगा। वर्तमान डब्ल्यूसीएबी/डब्ल्यूसीएसएफ आधारित परियोजना में मैं विकास कर रहा हूं, मुझे विजुअल स्टूडियो डिज़ाइन व्यू में इस तरह की त्रुटियां दिखाई दे रही हैं, और मुझे नहीं पता कि क्यों। साइट संकलित और सब कुछ ऑनलाइन काम करता है। शैली नियंत्रण के लिए

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); 
     } 

    } 
} 

और कोड:

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 
    } 
} 

तो क्या तुम लोग सोचते हो

Example of design time error in Visual Studio http://www.egil.dk/wp-content/styleplaceholder-error.jpg

निम्नलिखित StylePlaceHolder नियंत्रण के लिए कोड है? क्या यह एएसपीनेट थीम समस्या का एक अच्छा समाधान है? और कोड के बारे में क्या? मुझे वास्तव में डिजाइन समय के अनुभव के संबंध में कुछ इनपुट पसंद आएगा।

मैंने zipped version of the Visual Studio solution अपलोड किया है जिसमें कोई भी रुचि रखने पर परियोजना शामिल है।

सर्वश्रेष्ठ संबंध, Egil।

उत्तर

2

मेरे अपने प्रश्न का उत्तर मिला।

डिज़ाइन मोड में मुझे रेंडरिंग त्रुटियों के कारण का कारण, विजुअल स्टूडियो एसपी 1, which Microsoft has yet to fix में एक स्पष्ट बग है।

तो उपर्युक्त कोड डिज़ाइन मोड में भी अपेक्षित काम करता है, जब तक कि आप पहले से संकलित असेंबली में कस्टम नियंत्रण शामिल नहीं करते हैं, और उसी समाधान में किसी अन्य प्रोजेक्ट के माध्यम से नहीं।

ऊपर और ऊपर के लिंक के बारे में अधिक विस्तृत स्पष्टीकरण के लिए ऊपर दिए गए लिंक को देखें।

0

बहुत आसानी से काम करता है।

मेरे जैसे उन लोगों के लिए जो कभी भी <% टैग के सिंटैक्स को याद नहीं रखते हैं, आपको मास्टर पेज परिभाषा के शीर्ष पर जोड़ने और नामस्थान को पंजीकृत करने के लिए त्वचा फ़ाइल को जोड़ने की आवश्यकता है।

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

मुझे यकीन नहीं है कि मैं अपने कोड पर इतना 'गधा' चाहता हूं, लेकिन अन्यथा मुझे यह पसंद है।

ओह और यदि यह वास्तव में आपका पहला कस्टम नियंत्रण महान काम है। मुझे पता है कि यह किसी और के कोड से प्रेरित था लेकिन कम से कम सभी सही गुण और इंटरफेस रखने के लिए दिखाई देता है।

+0

साइमन के प्रकार के लिए धन्यवाद। यह वास्तव में मेरा पहला कस्टम नियंत्रण है, हालांकि इसे अब तक कुछ बार दोबारा प्रतिक्रिया दी गई है, इसलिए पहले कस्टम नियंत्रण, पहले प्रयास नहीं :) :) –

+0

@egil मजाकिया बात यह है कि मैं अगले दिन एमवीसी में स्विच कर रहा हूं - आंशिक रूप से क्योंकि मैं थक गया था सरल समस्याओं के लिए आपके जैसे चतुर समाधान की तलाश करना है। सौभाग्य से मैं एक नई साइट विकसित कर रहा हूं इसलिए मुझे विलासिता को एमवीसी के साथ खेलने की इजाजत मिली और मैं वास्तव में इसका आनंद ले रहा हूं –

0

पुन: विशिष्ट मीडिया सीएसएस फ़ाइल का उपयोग करके, आप @media सीएसएस कथन का उपयोग कर सकते हैं, ठीक काम करता है।

संबंधित मुद्दे