レイアウトページの見出し:
<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ファイルリンクAnotherViewとAnotherPartialからレイアウトヘッドへのリンク?
AnotherPageには複数のPartialを含めることができるため、RenderSectionはお勧めできません。すべてのCSSをheadに追加しても、動的に変化するため(Anotherpagesに依存します)、役に立ちません。
レイアウト:
<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)
}
このようにして、直接の子供だけでなく、すべてのビューがheadセクションを実装できます。ただし、これは部分的にしか機能しません。特に、複数の部分音で問題が発生します(あなたの質問で述べたように)。
だからあなたの問題に対する唯一の本当の解決策は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スタイルはカスケードされるので、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メソッドを再定義してください。
私はこの問題を解決しようとしました。
私の答えはここにあります。
"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>
...
私は同様の問題を抱えていて、Kalmanの優れた答えを以下のコードで適用しました(それほどきれいではありませんが、おそらくもっと拡張可能です)。
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"));
}
}
次に、BundleConfigクラスをGlobal.asaxファイルに登録しました。
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")
簡単なラッパーを作成しました。これを使用すると、すべての部分ビューでスタイルやスクリプトを動的にheadタグに登録できます。
これはjsakamotoが提唱したDynamicHeaderに基づいていますが、いくつかのパフォーマンスの改善と調整が行われています。
それは非常に使いやすく、そして多用途です。
使い方
@{
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");
}
あなたは完全なコード、説明と例を中に見つけることができます: スタイルとスクリプトを動的にヘッドタグに追加する