7 Stimmen

Versuchen, JS und CSS zu Layout-Datei in MVC 3 Razor Website aus partiellen Ansichten hinzufügen

Ich verwende derzeit eine Methode, die wie der folgende Code aussieht, um Skript- und CSS-Dateien in den Kopf der Layout-Datei hinzuzufügen.

public static class HtmlHelperExtensions
{
    public static MyCompanyHtmlHelpers MyCompany(this HtmlHelper htmlHelper)
    {
        return MyCompanyHtmlHelpers.GetInstance(htmlHelper);
    }    
}

public class MyCompanyHtmlHelpers
{
    private static MyCompanyHtmlHelpers _instance;

    public static MyCompanyHtmlHelpers GetInstance(HtmlHelper htmlHelper)
    {
        if (_instance == null)
            _instance = new MyCompanyHtmlHelpers();

        _instance.SetHtmlHelper(htmlHelper);

        return _instance;
    }

    private HtmlHelper _htmlHelper;

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

    public MyCompanyHtmlHelpers()
    {
        Styles = new ItemRegistrar(ItemRegistrarFromatters.StyleFormat);
        Scripts = new ItemRegistrar(ItemRegistrarFromatters.ScriptFormat);
    }

    private void SetHtmlHelper(HtmlHelper htmlHelper)
    {
        _htmlHelper = htmlHelper;
    }
}

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

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

    public ItemRegistrar Add(string url)
    {
        if (!_items.Contains(url))
            _items.Insert(0, 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 ItemRegistrarFromatters
{
    public const string StyleFormat = "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />";
    public const string ScriptFormat = "<script src=\"{0}\" type=\"text/javascript\"></script>";
}

Verwendung von Html.MyCompany().Styles.Add("/Dashboard/Content/Dashboard.css"); um Dateien hinzuzufügen... Und @Html.MyCompany().Styles.Render() um sie in Layout_.cshtml zu rendern.

Mein Problem ist, dass dies eine statische Methode ist, d.h. die Liste der Stylesheets und Skriptdateien wird beibehalten.

Ich muss das Gleiche tun, wie das hier, aber ohne es dauerhaft zu halten.

Die Listen müssen bei jeder Anfrage neu erstellt werden, da sie sich von Seite zu Seite ändern, was auf der jeweiligen Seite zu sehen ist.

Ist es möglich, die Listen bei jeder Anfrage zu leeren, bevor die benötigten Skripte hinzugefügt werden, oder vielleicht, nachdem sie gerendert worden sind?

Aktualisierung: Der Grund dafür, dass keine Abschnitte, RenderPartial oder RenderaActions verwendet werden, ist, dass verhindert werden soll, dass dieselbe Stylesheet- oder Skriptdatei mehr als einmal zur Layoutdatei hinzugefügt wird.

Die Website, die ich aufbaue, hat ein Layout_.cshtml mit dem Grundlayout. Diese wird wiederum von einer Ansicht verwendet, die in einer Schleife eine Liste von Elementen durchläuft, und für jedes Element wird eine RenderAction aufgerufen, die die spezifische Teilansicht für dieses Element ausgibt. Diesen Teilansichten müssen manchmal Stylesheets und Skripte hinzugefügt werden.

Da es notwendig sein kann, viele verschiedene Skripte und Stylesheets aus verschiedenen Teilansichten hinzuzufügen, war eine globale Liste für Stile und Skripte der einzige Weg, den ich dachte, dass dies getan werden könnte, damit es einen globalen Ort gibt, um zu prüfen, ob ein Skript bereits zur Sammlung hinzugefügt wurde oder nicht, und sie dann alle auf einmal in der Reihenfolge zu rendern, in der sie hinzugefügt wurden.

Update 2: Die eigentliche Frage ist, wie man die gleiche Art von Funktion (eine globale Liste) ausführen kann, ohne eine statische Erweiterungsmethode zu verwenden.

9voto

Marc Gravell Punkte 970173

Ich würde dies mit Abschnitten tun, d.h.

@section head {
    ...add whatever you want here...
}

Und machen Sie den "Kopf"-Abschnitt aus dem Layout:

<head>
...other stuff here...
@RenderSection("head", required: false)
</head>

Wenn Sie nicht möchten, dass Abschnitte, und nicht wollen, um es zu übergeben, würde ich die HttpContext hier verwenden; speichern Sie einige Daten gegen HttpContext.Current.Items[someKey] . Ist sie null, wird eine neue erstellt und im Kontext gespeichert.

Zum Beispiel:

public static MyCompanyHtmlHelpers GetInstance(HtmlHelper htmlHelper)
{
    const string key = "MyCompanyHtmlHelpersInstance";
    IDictionary items = (htmlHelper == null || htmlHelper.ViewContext == null
        || htmlHelper.ViewContext.HttpContext == null)
        ? HttpContext.Current.Items : htmlHelper.ViewContext.HttpContext.Items;

    MyCompanyHtmlHelpers obj = (MyCompanyHtmlHelpers)items[key];
    if (obj == null)
    {
        items.Add(key, obj = new MyCompanyHtmlHelpers());
    }
    return obj;
}

0voto

Chev Punkte 56446

Sie müssen die Html-Hilfe ein wenig anders erweitern.

public static MvcHtmlString AddStyle(this HtmlHelper<TModel> html, string styleUrl)
{
    string styleTag = string.Format("<link rel='stylesheet' type='text/css' href='{0}' />", styleUrl);
    return MvcHtmlString.Create(styleTag);
}

Dann tun Sie es Ihrer Meinung nach einfach:

<head>
    @Html.AddStyle("/Dashboard/Content/Dashboard.css")
</head>

Wenn Sie relative Root-URLs benötigen, geben Sie einfach den Url-Content-Helper ein.

<head>
    @Html.AddStyle(Url.Content("~/Dashboard/Content/Dashboard.css"))
</head>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X