Вложенные бритвой макеты с каскадными секциями - PullRequest
77 голосов
/ 03 апреля 2011

У меня есть сайт MVC3, использующий Razor в качестве движка просмотра.Я хочу, чтобы мой сайт был скиновым.Большинство возможных скинов настолько похожи, что они могут быть получены из общего макета мастера.

Поэтому я рассматриваю этот дизайн:

Planned view diagram

Однако яхотел бы иметь возможность вызвать RenderSection в нижнем слое, _Common.cshtml, и сделать так, чтобы он отображал секцию, определенную в верхнем слое, Detail.cshtml.Это не работает: RenderSection, по-видимому, отображает только те разделы, которые определены на следующем слое.

Конечно, я могу определить каждый раздел в каждом скине.Например, если _Common необходимо вызвать RenderSection("hd") для раздела, определенного в Detail, я просто помещаю это в каждый _Skin, и это работает:

@section hd {
    @RenderSection("hd")
}

Это приводит к некоторому дублированиюкод (так как каждый скин должен иметь этот же раздел) и, как правило, выглядит грязно.Я все еще новичок в Razor, и, похоже, я упускаю что-то очевидное.

При отладке я вижу полный список определенных разделов в WebViewPage.SectionWritersStack.Если бы я мог просто попросить RenderSection просмотреть весь список, прежде чем сдаться, он нашел бы нужный мне раздел.Увы, SectionWritersStack не является общедоступным.

Кроме того, если бы я мог получить доступ к иерархии страниц макета и попытаться выполнить RenderSection в каждом отдельном контексте, я мог бы найти нужный мне раздел.Возможно, я что-то упускаю, но я не вижу способа сделать это.

Есть ли какой-нибудь способ достичь этой цели, кроме метода, который я уже обрисовал в общих чертах?

Ответы [ 4 ]

35 голосов
/ 03 апреля 2011

Сегодня это на самом деле невозможно при использовании общедоступного API (кроме использования подхода переопределения разделов). Возможно, вам повезет с личным размышлением, но это, конечно, хрупкий подход. Мы рассмотрим упрощение этого сценария в следующей версии Razor.

А пока вот несколько постов в блоге, которые я написал на эту тему:

17 голосов
/ 16 октября 2011
@helper ForwardSection( string section )
{
   if (IsSectionDefined(section))
   {
       DefineSection(section, () => Write(RenderSection(section)));
   }
}

Будет ли это делать работу?

4 голосов
/ 29 декабря 2013

Я не уверен, возможно ли это в MVC 3, но в MVC 5 я могу успешно сделать это, используя следующий трюк:

В ~/Views/Shared/_Common.cshtml введите свой общий HTML-код, например:

<!DOCTYPE html>
<html lang="fa">
<head>
    <title>Skinnable - @ViewBag.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>

В ~/Views/_ViewStart.cshtml:

@{
    Layout = "~/Views/Shared/_Common.cshtml";
}

Теперь все, что вам нужно сделать, это использовать _Common.cshtml в качестве Layout для всех скинов. Например, в ~/Views/Shared/Skin1.cshtml:

@{
    Layout = "~/Views/Shared/_Common.cshtml";
}

<p>Something specific to Skin1</p>

@RenderBody()

Теперь вы можете установить скин в качестве макета в контроллере или представлении в соответствии с вашими критериями. Например:

    public ActionResult Index()
    {
        //....
        if (user.SelectedSkin == Skins.Skin1)
            return View("ViewName", "Skin1", model);
    }

Если вы запустите код выше, вы должны получить HTML-страницу с содержимым Skin1.cshtml и _Common.cshtml

Короче говоря, вы установите макет страницы макета (обложки).

1 голос
/ 09 декабря 2014

Не уверен, поможет ли это вам, но я написал несколько методов расширения, которые помогут «всплыть» разделам из партиалов, которые также должны работать для вложенных макетов.

Вставка содержимого в определенные разделы из частичного представления ASP.NET MVC 3 с Razor View Engine

Объявление в дочернем макете / просмотре / частичном

@using (Html.Delayed()) {
    <b>show me multiple times, @Model.Whatever</b>
}

Визуализация в любом из родителей

@Html.RenderDelayed();

См. Ссылку ответа для большего количества вариантов использования, таких как рендеринг только одного блока с задержкой, даже если он объявлен в повторяющемся виде, рендеринг определенных блоков с задержкой и т. Д.

...