Dodaj pliki CSS lub JavaScript do głowicy układu z widoków lub widoków częściowych


176

Układ nagłówków stron:

<head>
    <link href="@Url.Content("~/Content/themes/base/Site.css")"
          rel="stylesheet" type="text/css" />
</head>

Widok (AnotherView) z aplikacji wymaga:

<link href="@Url.Content("~/Content/themes/base/AnotherPage.css")"
      rel="stylesheet" type="text/css" />

a AnotherView ma częściowy widok (AnotherPartial), który wymaga:

<link href="@Url.Content("~/Content/themes/base/AnotherPartial.css")"
      rel="stylesheet" type="text/css" />

Pytanie: Jak możemy dodać te linki do plików CSS, linki AnotherView i AnotherPartial do nagłówka Layout ?

RenderSection nie jest dobrym pomysłem, ponieważ AnotherPage może mieć więcej niż jedną Partials. Dodanie całego CSS do nagłówka nie jest przydatne, ponieważ będzie się dynamicznie zmieniać (zależy to od Anotherpages).


@NuriYILMAZ to ogromna różnica między „z wyświetleń” a „lub częściowymi widokami”, jak mówi twój tytuł. Zresztą, jakieś nowe pomysły w tej sprawie?
Shimmy Weitzhandler

Odpowiedzi:


196

Układ:

<html>
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title</title>
        <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
        <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/modernizr-2.0.6-development-only.js")" type="text/javascript"></script>
        @if (IsSectionDefined("AddToHead"))
        {
            @RenderSection("AddToHead", required: false)
        }

        @RenderSection("AddToHeadAnotherWay", required: false)
    </head>

Widok:

@model ProjectsExt.Models.DirectoryObject

@section AddToHead{
    <link href="@Url.Content("~/Content/Upload.css")" rel="stylesheet" type="text/css" />
}

5
Myślę, że to najprostsze rozwiązanie.
iamichi

Niezłe rozwiązanie po wyjęciu z pudełka!
jerrylroberts

14
To nie zadziała, jeśli AddToHeadsekcja jest w częściowym widoku osadzonym w View.
Shimmy Weitzhandler

57
Pytanie wyraźnie dotyczyło częściowego poglądu, a ta najwyżej oceniona odpowiedź nie rozwiązuje problemu! Może to być doskonałe rozwiązanie w przypadku innego zapytania, ale nie tego.
Vulcan Raven

1
Byłoby eleganckim rozwiązaniem, gdyby działało z częściowymi widokami.
Jonny

75

Aktualizacja : podstawowy przykład dostępny pod adresem https://github.com/speier/mvcassetshelper

Używamy następującej implementacji, aby dodać pliki JS i CSS do strony układu.

View lub PartialView:

@{
    Html.Assets().Styles.Add("/Dashboard/Content/Dashboard.css");
    Html.Assets().Scripts.Add("/Dashboard/Scripts/Dashboard.js");
}

Strona układu:

<head>
    @Html.Assets().Styles.Render()
</head>

<body>
    ...
    @Html.Assets().Scripts.Render()
</body>

Rozszerzenie HtmlHelper:

public static class HtmlHelperExtensions
{
    public static AssetsHelper Assets(this HtmlHelper htmlHelper)
    {
        return AssetsHelper.GetInstance(htmlHelper);
    }    
}

public class AssetsHelper 
{
    public static AssetsHelper GetInstance(HtmlHelper htmlHelper)
    {
        var instanceKey = "AssetsHelperInstance";

        var context = htmlHelper.ViewContext.HttpContext;
        if (context == null) return null;

        var assetsHelper = (AssetsHelper)context.Items[instanceKey];

        if (assetsHelper == null)
            context.Items.Add(instanceKey, assetsHelper = new AssetsHelper());

        return assetsHelper;
    }

    public ItemRegistrar Styles { get; private set; }
    public ItemRegistrar Scripts { get; private set; }

    public AssetsHelper()
    {
        Styles = new ItemRegistrar(ItemRegistrarFormatters.StyleFormat);
        Scripts = new ItemRegistrar(ItemRegistrarFormatters.ScriptFormat);
    }
}

public class ItemRegistrar
{
    private readonly string _format;
    private readonly IList<string> _items;

    public ItemRegistrar(string format)
    {
        _format = format;
        _items = new List<string>();
    }

    public ItemRegistrar Add(string url)
    {
        if (!_items.Contains(url))
            _items.Add(url);

        return this;
    }

    public IHtmlString Render()
    {
        var sb = new StringBuilder();

        foreach (var item in _items)
        {
            var fmt = string.Format(_format, item);
            sb.AppendLine(fmt);
        }

        return new HtmlString(sb.ToString());
    }
}

public class ItemRegistrarFormatters
{
    public const string StyleFormat = "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />";
    public const string ScriptFormat = "<script src=\"{0}\" type=\"text/javascript\"></script>";
}

2
@JBeckton: Przyjrzyj się kodowi i zamień Insertmetody na Addmetody
Valamas

9
@Kalman - bezpieczeństwo wątków zostało zakwestionowane (moim zdaniem całkiem słusznie): stackoverflow.com/questions/6609586/…
Marc Gravell

2
To jest bardzo złe; powinien być [ThreadStatic], a najlepiej przechowywany w formacie HttpContext.Items.
SLaks

6
Czy coś mi brakuje? Jeśli Styles.Render () jest wywoływana w <head>, to wszelkie pliki css dodane po <head> (tj. Pliki dodane w widokach częściowych) nie będą renderowane. (MVC renderuje się od góry do dołu.)
ken

3
@FernandoCorreia Myślę, że wszystko źle zrozumiałeś. Nazwane sekcje nie działają w widokach częściowych, które są podstawą całego tego wątku.
Shimmy Weitzhandler

11

Niestety, domyślnie nie można tego użyć sectionzgodnie z sugestią innego użytkownika, ponieważ sectionjest on dostępny tylko dla bezpośredniego childpliku View.

Jednak działa to zaimplementowanie i przedefiniowanie sectionw każdym widoku , co oznacza:

section Head
{
    @RenderSection("Head", false)
}

W ten sposób każdy widok może implementować sekcję główną, a nie tylko bezpośrednie elementy potomne. Działa to jednak tylko częściowo, zwłaszcza w przypadku wielu częściowych problemów zaczynają się kłopoty (jak wspomniałeś w swoim pytaniu).

Więc jedynym prawdziwym rozwiązaniem twojego problemu jest użycie ViewBag. Najlepszą prawdopodobnie byłaby osobna kolekcja (lista) dla CSS i skryptów. Aby to zadziałało, musisz upewnić się, że Listużywany jest zainicjowany przed wykonaniem któregokolwiek z widoków. Następnie możesz zrobić takie rzeczy u góry każdego widoku / częściowej (bez zwracania uwagi na to, Scriptsczy Styleswartość lub jest pusta:

ViewBag.Scripts.Add("myscript.js");
ViewBag.Styles.Add("mystyle.css");

W układzie możesz następnie przeglądać kolekcje i dodawać style na podstawie wartości w pliku List.

@foreach (var script in ViewBag.Scripts)
{
    <script type="text/javascript" src="@script"></script>
}
@foreach (var style in ViewBag.Styles)
{
    <link href="@style" rel="stylesheet" type="text/css" />
}

Myślę, że jest brzydki, ale to jedyna rzecz, która działa.

****** UPDATE **** Ponieważ zaczyna najpierw wykonywać wewnętrzne widoki i przechodzić do układu, a style CSS są kaskadowe, prawdopodobnie miałoby sens odwrócenie listy stylów za pomocą ViewBag.Styles.Reverse().

W ten sposób najbardziej zewnętrzny styl jest dodawany jako pierwszy, który i tak jest zgodny z tym, jak działają arkusze stylów CSS.


1
Dzięki ntziolis. Wygląda to ładnie, ale głowice układu brzytwy działają najpierw przed innymi widokami, a dynamika .scripts i .styles była pusta przed kolejnymi widokami. Znalazłem fajny blog na ten temat i podzieliłem się tym pytaniem.
Nuri YILMAZ

To zadziała dla każdego widoku pochodnego, ale nie dla częściowych. W przypadku częściowych rzeczywiście kolejność wykonania jest nieprawidłowa. w zasadzie dla podszablonów nie ma możliwości umieszczenia ich w nagłówku. Sugerowałbym, zamiast dodawać go do nagłówka, po prostu dodaj go na początku tagu body. Nie byłby to mój pierwszy wybór, ale w ten sposób masz zwięzły sposób zarządzania wszystkimi stylami / js w jednym miejscu, a raczej ich rozproszenie.
ntziolis

Zgadzam się z tobą. Ponieważ znalazłem kilka rozwiązań, które wymieniłem w odpowiedzi, ale są to dokładnie rozwiązania js. Naprawdę zastanawiam się, dlaczego nie mogliśmy użyć strony układu jako klasycznej strony asp.net. Oznacza to, że mogę sięgnąć do strony podrzędnej.
Nuri YILMAZ

11

Możesz zdefiniować sekcję metodą RenderSection w układzie.

Układ

<head>
  <link href="@Url.Content("~/Content/themes/base/Site.css")"
    rel="stylesheet" type="text/css" />
  @RenderSection("heads", required: false)
</head>

Następnie możesz umieścić swoje pliki css w obszarze sekcji w widoku z wyjątkiem widoku częściowego .

Przekrój działa w widoku, ale nie działa w widoku częściowym zgodnie z projektem .

<!--your code -->
@section heads
{
  <link href="@Url.Content("~/Content/themes/base/AnotherPage.css")"
  rel="stylesheet" type="text/css" />
}

Jeśli naprawdę chcesz używać obszaru przekroju w widoku częściowym, możesz postępować zgodnie z artykułem, aby przedefiniować metodę RenderSection.

Razor, zagnieżdżone układy i przedefiniowane sekcje - Marcin on ASP.NET


6

Miałem podobny problem i ostatecznie zastosowałem doskonałą odpowiedź Kalmana z poniższym kodem (nie całkiem zgrabny, ale prawdopodobnie bardziej rozszerzalny):

namespace MvcHtmlHelpers
{
    //http://stackoverflow.com/questions/5110028/add-css-or-js-files-to-layout-head-from-views-or-partial-views#5148224
    public static partial class HtmlExtensions
    {
        public static AssetsHelper Assets(this HtmlHelper htmlHelper)
        {
            return AssetsHelper.GetInstance(htmlHelper);
        }
    }
    public enum BrowserType { Ie6=1,Ie7=2,Ie8=4,IeLegacy=7,W3cCompliant=8,All=15}
    public class AssetsHelper
    {
        public static AssetsHelper GetInstance(HtmlHelper htmlHelper)
        {
            var instanceKey = "AssetsHelperInstance";
            var context = htmlHelper.ViewContext.HttpContext;
            if (context == null) {return null;}
            var assetsHelper = (AssetsHelper)context.Items[instanceKey];
            if (assetsHelper == null){context.Items.Add(instanceKey, assetsHelper = new AssetsHelper(htmlHelper));}
            return assetsHelper;
        }
        private readonly List<string> _styleRefs = new List<string>();
        public AssetsHelper AddStyle(string stylesheet)
        {
            _styleRefs.Add(stylesheet);
            return this;
        }
        private readonly List<string> _scriptRefs = new List<string>();
        public AssetsHelper AddScript(string scriptfile)
        {
            _scriptRefs.Add(scriptfile);
            return this;
        }
        public IHtmlString RenderStyles()
        {
            ItemRegistrar styles = new ItemRegistrar(ItemRegistrarFormatters.StyleFormat,_urlHelper);
            styles.Add(Libraries.UsedStyles());
            styles.Add(_styleRefs);
            return styles.Render();
        }
        public IHtmlString RenderScripts()
        {
            ItemRegistrar scripts = new ItemRegistrar(ItemRegistrarFormatters.ScriptFormat, _urlHelper);
            scripts.Add(Libraries.UsedScripts());
            scripts.Add(_scriptRefs);
            return scripts.Render();
        }
        public LibraryRegistrar Libraries { get; private set; }
        private UrlHelper _urlHelper;
        public AssetsHelper(HtmlHelper htmlHelper)
        {
            _urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
            Libraries = new LibraryRegistrar();
        }
    }
    public class LibraryRegistrar
    {
        public class Component
        {
            internal class HtmlReference
            {
                internal string Url { get; set; }
                internal BrowserType ServeTo { get; set; }
            }
            internal List<HtmlReference> Styles { get; private set; }
            internal List<HtmlReference> Scripts { get; private set; }
            internal List<string> RequiredLibraries { get; private set; }

            public Component()
            {
                Styles = new List<HtmlReference>();
                Scripts = new List<HtmlReference>();
                RequiredLibraries = new List<string>();
            }
            public Component Requires(params string[] libraryNames)
            {
                foreach (var lib in libraryNames)
                {
                    if (!RequiredLibraries.Contains(lib))
                        { RequiredLibraries.Add(lib); }
                }
                return this;
            }
            public Component AddStyle(string url, BrowserType serveTo = BrowserType.All)
            {
                Styles.Add(new HtmlReference { Url = url, ServeTo=serveTo });
                return this;
            }
            public Component AddScript(string url, BrowserType serveTo = BrowserType.All)
            {
                Scripts.Add(new HtmlReference { Url = url, ServeTo = serveTo });
                return this;
            }
        }
        private readonly Dictionary<string, Component> _allLibraries = new Dictionary<string, Component>();
        private List<string> _usedLibraries = new List<string>();
        internal IEnumerable<string> UsedScripts()
        {
            SetOrder();
            var returnVal = new List<string>();
            foreach (var key in _usedLibraries)
            {
                returnVal.AddRange(from s in _allLibraries[key].Scripts
                                   where IncludesCurrentBrowser(s.ServeTo)
                                   select s.Url);
            }
            return returnVal;
        }
        internal IEnumerable<string> UsedStyles()
        {
            SetOrder();
            var returnVal = new List<string>();
            foreach (var key in _usedLibraries)
            {
                returnVal.AddRange(from s in _allLibraries[key].Styles
                                   where IncludesCurrentBrowser(s.ServeTo)
                                   select s.Url);
            }
            return returnVal;
        }
        public void Uses(params string[] libraryNames)
        {
            foreach (var name in libraryNames)
            {
                if (!_usedLibraries.Contains(name)){_usedLibraries.Add(name);}
            }
        }
        public bool IsUsing(string libraryName)
        {
            SetOrder();
            return _usedLibraries.Contains(libraryName);
        }
        private List<string> WalkLibraryTree(List<string> libraryNames)
        {
            var returnList = new List<string>(libraryNames);
            int counter = 0;
            foreach (string libraryName in libraryNames)
            {
                WalkLibraryTree(libraryName, ref returnList, ref counter);
            }
            return returnList;
        }
        private void WalkLibraryTree(string libraryName, ref List<string> libBuild, ref int counter)
        {
            if (counter++ > 1000) { throw new System.Exception("Dependancy library appears to be in infinate loop - please check for circular reference"); }
            Component library;
            if (!_allLibraries.TryGetValue(libraryName, out library))
                { throw new KeyNotFoundException("Cannot find a definition for the required style/script library named: " + libraryName); }
            foreach (var childLibraryName in library.RequiredLibraries)
            {
                int childIndex = libBuild.IndexOf(childLibraryName);
                if (childIndex!=-1)
                {
                    //child already exists, so move parent to position before child if it isn't before already
                    int parentIndex = libBuild.LastIndexOf(libraryName);
                    if (parentIndex>childIndex)
                    {
                        libBuild.RemoveAt(parentIndex);
                        libBuild.Insert(childIndex, libraryName);
                    }
                }
                else
                {
                    libBuild.Add(childLibraryName);
                    WalkLibraryTree(childLibraryName, ref libBuild, ref counter);
                }
            }
            return;
        }
        private bool _dependenciesExpanded;
        private void SetOrder()
        {
            if (_dependenciesExpanded){return;}
            _usedLibraries = WalkLibraryTree(_usedLibraries);
            _usedLibraries.Reverse();
            _dependenciesExpanded = true;
        }
        public Component this[string index]
        {
            get
            {
                if (_allLibraries.ContainsKey(index))
                    { return _allLibraries[index]; }
                var newComponent = new Component();
                _allLibraries.Add(index, newComponent);
                return newComponent;
            }
        }
        private BrowserType _requestingBrowser;
        private BrowserType RequestingBrowser
        {
            get
            {
                if (_requestingBrowser == 0)
                {
                    var browser = HttpContext.Current.Request.Browser.Type;
                    if (browser.Length > 2 && browser.Substring(0, 2) == "IE")
                    {
                        switch (browser[2])
                        {
                            case '6':
                                _requestingBrowser = BrowserType.Ie6;
                                break;
                            case '7':
                                _requestingBrowser = BrowserType.Ie7;
                                break;
                            case '8':
                                _requestingBrowser = BrowserType.Ie8;
                                break;
                            default:
                                _requestingBrowser = BrowserType.W3cCompliant;
                                break;
                        }
                    }
                    else
                    {
                        _requestingBrowser = BrowserType.W3cCompliant;
                    }
                }
                return _requestingBrowser;
            }
        }
        private bool IncludesCurrentBrowser(BrowserType browserType)
        {
            if (browserType == BrowserType.All) { return true; }
            return (browserType & RequestingBrowser) != 0;
        }
    }
    public class ItemRegistrar
    {
        private readonly string _format;
        private readonly List<string> _items;
        private readonly UrlHelper _urlHelper;

        public ItemRegistrar(string format, UrlHelper urlHelper)
        {
            _format = format;
            _items = new List<string>();
            _urlHelper = urlHelper;
        }
        internal void Add(IEnumerable<string> urls)
        {
            foreach (string url in urls)
            {
                Add(url);
            }
        }
        public ItemRegistrar Add(string url)
        {
            url = _urlHelper.Content(url);
            if (!_items.Contains(url))
                { _items.Add( url); }
            return this;
        }
        public IHtmlString Render()
        {
            var sb = new StringBuilder();
            foreach (var item in _items)
            {
                var fmt = string.Format(_format, item);
                sb.AppendLine(fmt);
            }
            return new HtmlString(sb.ToString());
        }
    }
    public class ItemRegistrarFormatters
    {
        public const string StyleFormat = "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />";
        public const string ScriptFormat = "<script src=\"{0}\" type=\"text/javascript\"></script>";
    }
}

Projekt zawiera statyczną metodę AssignAllResources:

assets.Libraries["jQuery"]
        .AddScript("~/Scripts/jquery-1.10.0.min.js", BrowserType.IeLegacy)
        .AddScript("~/Scripts//jquery-2.0.1.min.js",BrowserType.W3cCompliant);
        /* NOT HOSTED YET - CHECK SOON 
        .AddScript("//ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js",BrowserType.W3cCompliant);
        */
    assets.Libraries["jQueryUI"].Requires("jQuery")
        .AddScript("//ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js",BrowserType.Ie6)
        .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.ui/1.9.2/themes/eggplant/jquery-ui.css",BrowserType.Ie6)
        .AddScript("//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js", ~BrowserType.Ie6)
        .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.3/themes/eggplant/jquery-ui.css", ~BrowserType.Ie6);
    assets.Libraries["TimePicker"].Requires("jQueryUI")
        .AddScript("~/Scripts/jquery-ui-sliderAccess.min.js")
        .AddScript("~/Scripts/jquery-ui-timepicker-addon-1.3.min.js")
        .AddStyle("~/Content/jQueryUI/jquery-ui-timepicker-addon.css");
    assets.Libraries["Validation"].Requires("jQuery")
        .AddScript("//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js")
        .AddScript("~/Scripts/jquery.validate.unobtrusive.min.js")
        .AddScript("~/Scripts/mvcfoolproof.unobtrusive.min.js")
        .AddScript("~/Scripts/CustomClientValidation-1.0.0.min.js");
    assets.Libraries["MyUtilityScripts"].Requires("jQuery")
        .AddScript("~/Scripts/GeneralOnLoad-1.0.0.min.js");
    assets.Libraries["FormTools"].Requires("Validation", "MyUtilityScripts");
    assets.Libraries["AjaxFormTools"].Requires("FormTools", "jQueryUI")
        .AddScript("~/Scripts/jquery.unobtrusive-ajax.min.js");
    assets.Libraries["DataTables"].Requires("MyUtilityScripts")
        .AddScript("//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js")
        .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css")
        .AddStyle("//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css");
    assets.Libraries["MvcDataTables"].Requires("DataTables", "jQueryUI")
        .AddScript("~/Scripts/jquery.dataTables.columnFilter.min.js");
    assets.Libraries["DummyData"].Requires("MyUtilityScripts")
        .AddScript("~/Scripts/DummyData.js")
        .AddStyle("~/Content/DummyData.css");     

na stronie _layout

@{
    var assets = Html.Assets();
    CurrentResources.AssignAllResources(assets);
    Html.Assets().RenderStyles()
}
</head>
...
    @Html.Assets().RenderScripts()
</body>

oraz w części (ach) i widokach

Html.Assets().Libraries.Uses("DataTables");
Html.Assets().AddScript("~/Scripts/emailGridUtilities.js");

Ciekawy. Wydaje się, że to przesada, ale widzę, że jest to używane częściej w witrynach, które nie mają innego wyjścia, jak tylko do radzenia sobie z użytkownikami używającymi starszych wersji, tj. ... jak w środowiskach korporacyjnych, w których niektóre kraje nie zostały zaktualizowane, a chcesz się zastrzelić. lol. +1 za to
pqsk

5

Próbowałem rozwiązać ten problem.

Moja odpowiedź jest tutaj.

„DynamicHeader” - http://dynamicheader.codeplex.com/ , https://nuget.org/packages/DynamicHeader

Na przykład _Layout.cshtml to:

<head>
@Html.DynamicHeader()
</head>
...

Możesz też zarejestrować pliki .js i .css w „DynamicHeader” w dowolnym miejscu .

Na przykład blok kodu w AnotherPartial.cshtm to:

@{
  DynamicHeader.AddSyleSheet("~/Content/themes/base/AnotherPartial.css");
  DynamicHeader.AddScript("~/some/myscript.js");
}

Ostatecznie wyjściowy kod HTML to:

<html>
  <link href="/myapp/Content/themes/base/AnotherPartial.css" .../>
  <script src="/myapp/some/myscript.js" ...></script>
</html>
...

4

Wypróbuj gotowe rozwiązanie (ASP.NET MVC 4 lub nowszy):

@{
    var bundle = BundleTable.Bundles.GetRegisteredBundles().First(b => b.Path == "~/js");

    bundle.Include("~/Scripts/myFile.js");
}

Otrzymuję błąd:CS0103: The name 'BundleTable' does not exist in the current context
Kunal

nvm: rozwiązałem to. Musiał dołączyć System.Web.Optimizationnp.System.Web.Optimization.BundleTable.Bundles.GetRegisteredBundles().First(b => b.Path == "~/bundles/css");
Kunal

1
Czy to nie zmienia pakietu na całym świecie? Jeśli zrobisz to na stronie A, a później otworzysz stronę B, strona B będzie również zawierała plik myFile.js, który, jak sądzę, nie był pożądany przez OP
mile82

4

Dla tych z nas, którzy używają ASP.NET MVC 4 - może to być pomocne.

Najpierw dodałem klasę BundleConfig w folderze App_Start.

Oto mój kod, którego użyłem do jego utworzenia:

using System.Web.Optimization;

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/SiteMaster.css"));
    }
}

Po drugie, zarejestrowałem klasę BundleConfig w pliku Global.asax:

protected void Application_Start()
{
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

Po trzecie, dodałem pomocników stylu do mojego pliku CSS:

/* Styles for validation helpers */
.field-validation-error {
    color: red;
    font-weight: bold;
}

.field-validation-valid {
    display: none;
}

input.input-validation-error {
    border: 1px solid #e80c4d;
}

input[type="checkbox"].input-validation-error {
    border: 0 none;
}

.validation-summary-errors {
    color: #e80c4d;
    font-weight: bold;
    font-size: 1.1em;
}

.validation-summary-valid {
    display: none;
}

Wreszcie użyłem tej składni w dowolnym widoku:

@Styles.Render("~/Content/css")

3

Oto wtyczka NuGet o nazwie Cassette , która między innymi zapewnia możliwość odwoływania się do skryptów i stylów w częściach.

Chociaż istnieje wiele konfiguracji dostępnych dla tej wtyczki, co czyni ją bardzo elastyczną. Oto najprostszy sposób odwoływania się do plików skryptów lub arkuszy stylów:

Bundles.Reference("scripts/app");

Zgodnie z dokumentacją :

Wzywa do Reference mogą pojawić się w dowolnym miejscu strony, układu lub częściowego widoku.

Argument ścieżki może być jednym z następujących:

  • Ścieżka pakietu
  • Ścieżka zasobu - odwołuje się do całego pakietu zawierającego ten zasób
  • URL

2

Napisałem łatwe opakowanie, które pozwala na dynamiczne rejestrowanie stylów i skrawków w każdym częściowym widoku w tagu head.

Opiera się na utworzonym przez DynamicHeader jsakamoto, ale ma pewne ulepszenia wydajności i poprawki.

Jest bardzo łatwy w użyciu i wszechstronny.

Użycie:

@{
    DynamicHeader.AddStyleSheet("/Content/Css/footer.css", ResourceType.Layout);    
    DynamicHeader.AddStyleSheet("/Content/Css/controls.css", ResourceType.Infrastructure);
    DynamicHeader.AddScript("/Content/Js/Controls.js", ResourceType.Infrastructure);
    DynamicHeader.AddStyleSheet("/Content/Css/homepage.css");    
}

Możesz znaleźć pełny kod, wyjaśnienia i przykłady w: Dodaj style i skrypty dynamicznie do tagu nagłówka

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.