뷰 또는 부분 뷰에서 레이아웃 헤드에 CSS 또는 JavaScript 파일 추가
레이아웃 페이지 헤드 :
<head>
<link href="@Url.Content("~/Content/themes/base/Site.css")"
rel="stylesheet" type="text/css" />
</head>
응용 프로그램의보기 (AnotherView)에는 다음이 필요합니다.
<link href="@Url.Content("~/Content/themes/base/AnotherPage.css")"
rel="stylesheet" type="text/css" />
AnotherView에는 다음과 같은 부분보기 (AnotherPartial)가 있습니다.
<link href="@Url.Content("~/Content/themes/base/AnotherPartial.css")"
rel="stylesheet" type="text/css" />
질문 : 이 CSS 파일을 어떻게 추가 하여 다른 뷰와 다른 부분 링크를 레이아웃 헤드에 링크 할 수 있습니까?
AnotherPage는 둘 이상의 부분을 가질 수 있으므로 RenderSection은 좋은 생각이 아닙니다. head에 모든 CSS를 추가하면 동적으로 변경되므로 (다른 페이지에 따라 다름) 유용하지 않습니다.
나열한 것:
<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>
전망:
@model ProjectsExt.Models.DirectoryObject
@section AddToHead{
<link href="@Url.Content("~/Content/Upload.css")" rel="stylesheet" type="text/css" />
}
업데이트 : https://github.com/speier/mvcassetshelper 에서 제공되는 기본 예제
다음 구현을 사용하여 JS 및 CSS 파일을 레이아웃 페이지에 추가합니다.
보기 또는 PartialView :
@{
Html.Assets().Styles.Add("/Dashboard/Content/Dashboard.css");
Html.Assets().Scripts.Add("/Dashboard/Scripts/Dashboard.js");
}
레이아웃 페이지 :
<head>
@Html.Assets().Styles.Render()
</head>
<body>
...
@Html.Assets().Scripts.Render()
</body>
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>";
}
기본 사용에 의해 슬프게도,이 수 없습니다 section다른 사용자가 제안으로 이후, section즉각적인 만 사용할 수 있습니다 child의 View.
그러나 작동 하는 section것은 모든 관점에서를 구현하고 재정의하는 것 입니다 .
section Head
{
@RenderSection("Head", false)
}
이런 식으로 모든 뷰는 직계 자식뿐만 아니라 헤드 섹션을 구현할 수 있습니다. 이것은 부분적으로 만 작동하며, 특히 여러 부분으로 인해 문제가 시작됩니다 (질문에서 언급했듯이).
따라서 문제에 대한 유일한 실제 해결책은을 사용하는 것 ViewBag입니다. CSS와 스크립트에 대한 별도의 컬렉션 (목록)이 가장 적합 할 것입니다. 이렇게 List하려면 뷰를 실행하기 전에 사용 된 것이 초기화 되었는지 확인해야합니다 . 그런 다음 모든보기 / 부분 상단에서 이와 같은 작업을 수행 할 수 있습니다 ( Scripts또는 Styles값이 null 인 경우 신경 쓰지 않고) .
ViewBag.Scripts.Add("myscript.js");
ViewBag.Styles.Add("mystyle.css");
레이아웃에서 컬렉션을 반복하고의 값을 기반으로 스타일을 추가 할 수 있습니다 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" />
}
나는 그것이 추악하다고 생각하지만 그것이 작동하는 유일한 것입니다.
****** UPDATE **** 내부 뷰를 먼저 실행하고 레이아웃으로 나가는 작업을 시작하고 CSS 스타일이 계단식이므로 CSS를 통해 스타일 목록을 뒤집는 것이 ViewBag.Styles.Reverse()좋습니다.
이렇게하면 가장 외부 스타일이 먼저 추가되며 CSS 스타일 시트가 작동하는 방식과 일치합니다.
레이아웃에서 RenderSection 메서드로 섹션을 정의 할 수 있습니다 .
나열한 것
<head>
<link href="@Url.Content("~/Content/themes/base/Site.css")"
rel="stylesheet" type="text/css" />
@RenderSection("heads", required: false)
</head>
그런 다음 부분보기를 제외한 보기의 섹션 영역에 CSS 파일을 포함시킬 수 있습니다 .
이 섹션은보기에서 작동하지만 디자인에 의해 부분보기에서는 작동하지 않습니다 .
<!--your code -->
@section heads
{
<link href="@Url.Content("~/Content/themes/base/AnotherPage.css")"
rel="stylesheet" type="text/css" />
}
부분보기에서 섹션 영역을 실제로 사용하려면 기사를 따라 RenderSection 메서드를 재정의 할 수 있습니다.
면도기, 중첩 레이아웃 및 재정의 섹션 – Marcin On ASP.NET
이 문제를 해결하려고했습니다.
내 대답은 여기에 있습니다.
"DynamicHeader"- http://dynamicheader.codeplex.com/ , https://nuget.org/packages/DynamicHeader
예를 들어, _Layout.cshtml은 다음과 같습니다.
<head>
@Html.DynamicHeader()
</head>
...
또한 .js 및 .css 파일을 원하는 곳의 "DynamicHeader"에 등록 할 수 있습니다 .
예를 들어 AnotherPartial.cshtm의 코드 블록은 다음과 같습니다.
@{
DynamicHeader.AddSyleSheet("~/Content/themes/base/AnotherPartial.css");
DynamicHeader.AddScript("~/some/myscript.js");
}
그런 다음 최종 출력 HTML은 다음과 같습니다.
<html>
<link href="/myapp/Content/themes/base/AnotherPartial.css" .../>
<script src="/myapp/some/myscript.js" ...></script>
</html>
...
비슷한 문제가 있었고 아래 코드와 함께 칼만의 훌륭한 답변을 적용했습니다 (정확하지는 않지만 확장 가능합니다).
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>";
}
}
이 프로젝트에는 정적 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");
_layout 페이지에서
@{
var assets = Html.Assets();
CurrentResources.AssignAllResources(assets);
Html.Assets().RenderStyles()
}
</head>
...
@Html.Assets().RenderScripts()
</body>
그리고 부분 및 전망에서
Html.Assets().Libraries.Uses("DataTables");
Html.Assets().AddScript("~/Scripts/emailGridUtilities.js");
기본 제공 솔루션 (ASP.NET MVC 4 이상)을 사용해보십시오.
@{
var bundle = BundleTable.Bundles.GetRegisteredBundles().First(b => b.Path == "~/js");
bundle.Include("~/Scripts/myFile.js");
}
ASP.NET MVC 4를 사용하는 사람들에게는 도움이 될 것입니다.
먼저 App_Start 폴더에 BundleConfig 클래스를 추가했습니다.
다음은 코드를 만드는 데 사용한 코드입니다.
using System.Web.Optimization;
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/SiteMaster.css"));
}
}
둘째, Global.asax 파일에 BundleConfig 클래스를 등록했습니다.
protected void Application_Start()
{
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
셋째, 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;
}
마지막 으로이 구문을 모든보기에서 사용했습니다.
@Styles.Render("~/Content/css")
다음은 Cassette 라는 NuGet 플러그인으로 , 스크립트와 스타일을 부분적으로 참조 할 수있는 기능을 제공합니다.
이 플러그인에 사용할 수있는 구성 이 많이 있지만 유연성이 뛰어납니다. 다음은 스크립트 또는 스타일 시트 파일을 참조하는 가장 간단한 방법입니다.
Bundles.Reference("scripts/app");
설명서 에 따르면 :
호출
Reference은 페이지, 레이아웃 또는 부분보기의 어느 곳에 나 나타날 수 있습니다.경로 인수는 다음 중 하나 일 수 있습니다.
- 번들 경로
- 자산 경로-이 자산을 포함하는 전체 번들이 참조됩니다
- URL
모든 부분보기에서 스타일과 스크립을 헤드 태그에 동적으로 등록 할 수있는 쉬운 래퍼를 작성했습니다.
DynamicHeader jsakamoto를 기반으로하지만 성능이 약간 향상되었습니다.
사용하기 매우 쉽고 다양합니다.
사용법 :
@{
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");
}
전체 코드, 설명 및 예제는 다음에서 찾을 수 있습니다. 헤드 태그에 동적으로 스타일 및 스크립트 추가
'Programming' 카테고리의 다른 글
| 정수 범위를 지정하여 최적화 프로그램에 힌트를 줄 수 있습니까? (0) | 2020.05.24 |
|---|---|
| 요소의 id를 얻다 (0) | 2020.05.24 |
| IList 사용시기 및 List 사용시기 (0) | 2020.05.24 |
| 찾기 및 바꾸기-캐리지 리턴 또는 줄 바꾸기 추가 (0) | 2020.05.24 |
| HTML5 캔버스에서 단일 픽셀을 설정하는 가장 좋은 방법은 무엇입니까? (0) | 2020.05.24 |