Question

Est-il possible d'ajouter des références CSS à une page d'une vue partielle, et de les rendre dans <head> de la page (comme l'exige la HTML 4.01 spec )?

Était-ce utile?

La solution 4

Vous pouvez utiliser un HttpModule pour manipuler le code HTML de réponse et déplacer les références CSS / script aux endroits appropriés. Ce n'est pas idéal, et je ne suis pas sûr des conséquences sur les performances, mais il semble que la seule façon de résoudre le problème sans (a) une solution javascript, ou (b) par rapport aux principes de travail MVC.

Autres conseils

Si vous utilisez MVC3 & rasoir, la meilleure façon d'ajouter des éléments par page à votre section est de: 1) Appelez RenderSection () à partir de votre page de mise en page 2) Déclarer une section correspondante dans les pages de votre enfant:

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

La page HTML résultante comprend alors une section qui ressemble à ceci:

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

Vous pouvez également utiliser les commandes open source Telerik pour MVC et faire quelque chose comme:

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

dans la section de tête et

<%= Html.Telerik().ScriptRegistrar()
                  .DefaultGroup(group => group
                     .Add("script.js"));

dans la section de script à la botttom de votre page.

Et vous pouvez continuer à ajouter des scripts sur une vue ou vue partielle et ils devraient travailler.

Si vous ne souhaitez pas utiliser le composant que vous pouvez toujours vous inspirer à partir de là et faire quelque chose de plus personnalisé.

Oh, avec Telerik vous avez également des options de combinaison et la compression des scripts.

Vous pourriez avoir la charge vue partielle dans un bloc javascript qui tombe dans le style à la tête, mais ce serait stupide étant donné que vous voulez sans doute le bloc javascript dans la section de tête pour la même raison.

J'ai récemment découvert quelque chose assez cool cependant. Vous pouvez sérialiser une vue partielle en une chaîne et l'envoyer au client dans le cadre d'un objet JSON. Cela vous permet de passer d'autres paramètres aussi bien, ainsi que la vue.

De retour une vue dans le cadre d'un objet JSON

Vous pouvez saisir un objet JSON avec JQuery et ajax et l'ont chargé avec la vue partielle, puis une autre propriété JSON pourrait être votre bloc de style. JQuery pourrait vérifier si vous êtes retourné un bloc de style, le cas échéant, puis déposez-le dans la section de la tête.

Quelque chose comme:

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

Une autre approche, qui va à l'encontre des principes de MVC est d'utiliser un ViewModel et répondre à l'événement Init de votre page pour définir le css / javascript désiré (c.-à-myViewModel.Css.Add ( «css ») et dans votre la tête rendre le contenu du css-collection sur votre viewmodel.

Pour ce faire, vous créez une classe viewmodel de base que tous vos autres modèles hérités de, ala

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

Dans votre page maître vous définissez à utiliser cette viewmodel

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

et votre section de tête, vous pouvez écrire la valeur de la propriété 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>

Dans votre vue partielle vous devez avoir ce code, qui est un peu laid dans MVC

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

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

Ce qui suit ne peut fonctionner que si javascript ont été activés. il est un peu aide que j'utilise exactement le scénario que vous mentionnez:

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

utilisation:

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

fonctionne pour moi, quoique comme indiqué, que si javascript est activé, ce qui limite son utilité un peu.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top