Ich habe eine MVC3-Site, die Razor als Ansichtsmodul verwendet. Ich möchte, dass meine Website skinnbar ist. Die meisten möglichen Skins sind so ähnlich, dass sie von einem gemeinsam genutzten Master-Layout abgeleitet werden können.
Daher denke ich über dieses Design nach:
Ich möchte jedoch RenderSection
in der Lage sein, die unterste Ebene aufzurufen _Common.cshtml
und einen Abschnitt rendern zu lassen, der in der obersten Ebene definiert ist Detail.cshtml
. Dies funktioniert nicht: RenderSection
Anscheinend werden nur Abschnitte gerendert, die in der nächsten Ebene definiert sind.
Natürlich kann ich jeden Abschnitt in jeder Skin definieren. Wenn zum Beispiel ein in definierter Abschnitt _Common
aufgerufen werden muss , platziere ich diesen einfach in jedem und es funktioniert:RenderSection("hd")
Detail
_Skin
@section hd {
@RenderSection("hd")
}
Dies führt zu einer gewissen Duplizierung des Codes (da jeder Skin jetzt denselben Abschnitt haben muss) und fühlt sich im Allgemeinen unordentlich an. Ich bin noch neu bei Razor und es scheint, als würde mir etwas Offensichtliches fehlen.
Beim Debuggen wird die vollständige Liste der definierten Abschnitte in WebViewPage.SectionWritersStack angezeigt. Wenn ich RenderSection nur anweisen könnte, die gesamte Liste durchzusehen, bevor ich aufgebe, würde es den Abschnitt finden, den ich brauche. Leider ist SectionWritersStack nicht öffentlich.
Wenn ich alternativ auf die Hierarchie der Layoutseiten zugreifen und versuchen könnte, RenderSection in jedem unterschiedlichen Kontext auszuführen, könnte ich den gewünschten Abschnitt finden. Ich vermisse wahrscheinlich etwas, aber ich sehe keine Möglichkeit, dies zu tun.
Gibt es eine andere Möglichkeit, dieses Ziel zu erreichen, als die bereits beschriebene Methode?
quelle
@helper ForwardSection( string section ) { if (IsSectionDefined(section)) { DefineSection(section, () => Write(RenderSection(section))); } }
Würde das den Job machen?
quelle
Ich bin nicht sicher, ob dies in MVC 3 möglich ist, aber in MVC 5 kann ich dies mit dem folgenden Trick erfolgreich durchführen:
In
~/Views/Shared/_Common.cshtml
Schreiben Sie Ihre gemeinsamen HTML - Code wie:<!DOCTYPE html> <html lang="fa"> <head> <title>Skinnable - @ViewBag.Title</title> </head> <body> @RenderBody() </body> </html>
In
~/Views/_ViewStart.cshtml
:@{ Layout = "~/Views/Shared/_Common.cshtml"; }
Jetzt müssen Sie nur noch das
_Common.cshtml
als dasLayout
für alle Skins verwenden. Zum Beispiel in~/Views/Shared/Skin1.cshtml
:@{ Layout = "~/Views/Shared/_Common.cshtml"; } <p>Something specific to Skin1</p> @RenderBody()
Jetzt können Sie den Skin als Layout im Controller oder in der Ansicht basierend auf Ihren Kriterien festlegen. Zum Beispiel:
public ActionResult Index() { //.... if (user.SelectedSkin == Skins.Skin1) return View("ViewName", "Skin1", model); }
Wenn Sie den obigen Code ausführen, sollten Sie eine HTML-Seite mit dem Inhalt von
Skin1.cshtml
und erhalten_Common.cshtml
Kurz gesagt, Sie legen das Layout für die (Skin-) Layoutseite fest.
quelle
Ich bin mir nicht sicher, ob dies Ihnen helfen wird, aber ich habe einige Erweiterungsmethoden geschrieben, um Abschnitte aus Teilbereichen heraus "aufzublasen", die auch für verschachtelte Layouts funktionieren sollten.
Injizieren von Inhalten in bestimmte Abschnitte aus einer Teilansicht ASP.NET MVC 3 mit Razor View Engine
In untergeordnetem Layout / Ansicht / Teil deklarieren
In jedem Elternteil rendern
Weitere Anwendungsfälle finden Sie unter dem Antwortlink. Sie können beispielsweise nur einen verzögerten Block rendern, auch wenn er in einer sich wiederholenden Ansicht deklariert ist, bestimmte verzögerte Blöcke rendern usw.
quelle