从局部视图

从局部视图

问题描述:

添加到页面的CSS 引用是有办法的CSS引用从局部视图添加到页面,并让他们在渲染页面的<head>(所要求的HTML 4.01 spec)?从局部视图

+0

您的问题已经回答了几次已经,http://*.com/questions/912755/include-javascript- file-in-partial-views&http://*.com/questions/885990/linking-javascript-libraries-in-user-controls。我们在这种情况下讨论css还是js并不重要。 – 2010-11-18 02:48:20

+0

@BurningIce - 你说得对,资源的类型并不重要。您链接到的问题具有相同的接受答案,这对部分视图无效,因为他们无法使用asp:内容控件(解析器错误消息:内容控件必须是内容页面中的*控件或嵌套母版页引用母版页。)或者我错过了什么? – kristian 2010-11-18 03:24:34

+0

嗯有趣的一点。我想唯一真正的方法是将你的脚本/ css分成他们自己的部分视图。然后渲染部分在头部分的asp:Content中。这是我所能想到的。 – Chev 2010-11-18 07:48:04

您可以使用HttpModule来操作响应HTML并将任何CSS /脚本引用移动到适当的位置。这并不理想,我也不确定性能的影响,但它似乎是在没有(a)基于JavaScript的解决方案或(b)针对MVC原则的情况下解决问题的唯一方法。

您可以在JavaScript块中将部分视图加载到头部的样式中,但考虑到您可能希望头部的JavaScript块出于相同原因,这可能很愚蠢。

我最近发现了一些很酷的东西。您可以将部分视图序列化为一个字符串,并将其作为JSON对象的一部分发送回客户端。这使您可以传递其他参数以及视图。

Returning a view as part of a JSON object

你可以抓住用jQuery和Ajax JSON对象,并把它装载了局部视图,然后又是JSON财产可能是你的风格块。 JQuery可以检查你是否返回了一个样式块,如果是,则将其放入头部。

喜欢的东西:

$.ajax(
{ 
    url: "your/action/method", 
    data: { some: data }, 
    success: function(response) 
    { 
      $('#partialViewContainer).html(response.partialView); 
      if (response.styleBlock != null) 
       $('head').append(response.styleBlock); 
    } 
}); 
+0

良好的思维,这将工作,但它取决于用户启用了JavaScript(这是公平的,如果你正在加载脚本资源,但没有太多的CSS。) – kristian 2010-11-18 03:33:59

另一种方法,这违背了MVC的原则是使用视图模型,并到你的页面的Init事件来设置所需的CSS/JavaScript的(即myViewModel.Css回应。新增(“CSS”),并在你的脑袋上呈现您的视图模型的CSS-集合的内容。

要做到这一点,你创建你的所有车型,从继承的基础视图模型类,ALA

public class BaseViewModel 
{ 
    public string Css { get; set; } 
} 

在你的母版页设定要使用此视图模型

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseViewModel>" %> 

和你的头部分,你可以写出来的CSS属性的值现在

<head runat="server"> 
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title> 
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> 

    <%= Model.Css %> 
</head> 

,在您的局部视图你需要有这样的代码,这是MVC

<script runat="server"> 
    protected override void OnInit(EventArgs e) 
    { 
     Model.Css = "hej"; 

     base.OnInit(e); 
    } 
</script> 
+0

即使OP没有提及ajax请求的部分,这当然会起作用,只是作为标准页面请求的一部分。我想挑战是让它适用于局部视图,无论是作为单个请求的一部分调用,还是作为ajax刷新(我不知道它是如何工作的,除非它通过javascript注入头部) – 2010-11-18 13:23:52

+1

Yikes!我根本不喜欢这个。我宁愿违反保留头部部分样式的协议,也不愿意抛弃我的MVC应用程序中的问题。 – Chev 2010-11-18 21:16:27

您也可以使用Telerik的开源控件MVC和这样做有点难看:

<%= Html.Telerik().StyleSheetRegistrar() 
        .DefaultGroup(group => group 
        .Add("stylesheet.css")); 
head部分

<%= Html.Telerik().ScriptRegistrar() 
        .DefaultGroup(group => group 
        .Add("script.js")); 
在你的页面的botttom脚本部分

你可以在任何视图或局部视图上添加脚本,它们应该可以工作。

如果你不想使用该组件,你总是可以从那里激发你自己,做一些更自定义的事情。

哦,在Telerik中,您还可以选择合并和压缩脚本。

+0

+1,我喜欢这个解决方案。虽然我很想知道Telerik如何做它的业务。我可能会去看看它。 – Chev 2010-11-18 21:18:20

只有启用了JavaScript,以下才有效。这是我使用完全相同的场景中的小帮手你提到:

// standard method - renders as defined in as(cp)x file 
public static MvcHtmlString Css(this HtmlHelper html, string path) 
{ 
    return html.Css(path, false); 
} 
// override - to allow javascript to put css in head 
public static MvcHtmlString Css(this HtmlHelper html, 
           string path, 
           bool renderAsAjax) 
{ 
    var filePath = VirtualPathUtility.ToAbsolute(path); 

    HttpContextBase context = html.ViewContext.HttpContext; 
    // don't add the file if it's already there 
    if (context.Items.Contains(filePath)) 
     return null; 

    // otherwise, add it to the context and put on page 
    // this of course only works for items going in via the current 
    // request and by this method 
    context.Items.Add(filePath, filePath); 

    // js and css function strings 
    const string jsHead = "<script type='text/javascript'>"; 
    const string jsFoot = "</script>"; 
    const string jsFunctionStt = "$(function(){"; 
    const string jsFunctionEnd = "});"; 
    string linkText = string.Format("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\"></link>", filePath); 
    string jsBody = string.Format("$('head').prepend('{0}');", linkText); 

    var sb = new StringBuilder(); 

    if (renderAsAjax) 
    { 
     // join it all up now 
     sb.Append(jsHead); 
     sb.AppendFormat("\r\n\t"); 
     sb.Append(jsFunctionStt); 
     sb.AppendFormat("\r\n\t\t"); 
     sb.Append(jsBody); 
     sb.AppendFormat("\r\n\t"); 
     sb.Append(jsFunctionEnd); 
     sb.AppendFormat("\r\n"); 
     sb.Append(jsFoot); 
    } 
    else 
    { 
     sb.Append(linkText); 
    } 

    return MvcHtmlString.Create(sb.ToString()); 
} 

用法:

<%=Html.Css("~/content/site.css", true) %> 

作品对我来说,寿如上所述,只有当启用javascript,从而限制了其有效性一点。

如果您正在使用MVC3 &剃刀,给每个页面项目添加到您的部分最好的办法是: 1)从布局页 2)中调用RenderSection()声明你的孩子中的相应部分网页:

/Views/Shared/_Layout.cshtml:

<head> 
    <!-- ... Rest of your head section here ... -> 
    @RenderSection("HeadArea") 
</head> 

/Views/Entries/Index.cshtml:

@section HeadArea { 
    <link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" /> 
} 

得到的HTML页面,然后包括部分看起来像这样:

<head> 
    <!-- ... Rest of your head section here ... -> 
    <link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" /> 
<head> 
+0

您的解决方案帮助了我。谢谢! – 2011-05-07 09:13:36

+3

@Richard,你在这里描述的不是针对OP的问题,他是在谈论一个局部视图,而'_Layout.cshtml'是一个布局,而不是局部视图(包含在Index.cshtml中的实例',并且想要将脚本直接渲染到_layout.cshtml的'

'标签中。 – Shimmy 2012-11-13 06:55:31