80

我有一个使用 Razor 作为其视图引擎的 MVC3 站点。我希望我的网站可以换肤。大多数可能的皮肤都非常相似,它们可以从共享的主布局中派生出来。

因此,我正在考虑这种设计:

计划视图图

但是,我希望能够RenderSection在底层调用_Common.cshtml,并让它呈现在顶层定义的部分,Detail.cshtml。这不起作用:RenderSection显然只渲染下一层定义的部分。

当然,我可以定义每个皮肤中的每个部分。例如,如果_Common需要调用RenderSection("hd")中定义的部分Detail,我只需将其放在每个部分中即可_Skin

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

这会导致一些代码重复(因为现在每个皮肤都必须有相同的部分)并且通常感觉混乱。我还是 Razor 的新手,似乎我可能遗漏了一些明显的东西。

调试时,我可以在 WebViewPage.SectionWritersStack 中看到已定义部分的完整列表。如果我可以告诉 RenderSection 在放弃之前查看整个列表,它会找到我需要的部分。唉,SectionWritersStack 是非公开的。

或者,如果我可以访问布局页面的层次结构并尝试在每个不同的上下文中执行 RenderSection,我可以找到我需要的部分。我可能遗漏了一些东西,但我没有看到任何方法可以做到这一点。

除了我已经概述的方法之外,还有其他方法可以实现这一目标吗?

4

4 回答 4

36

这实际上在今天使用公共 API 是不可能的(除了使用部分重新定义方法)。使用私有反射可能会有一些运气,但这当然是一种脆弱的方法。我们将研究在 Razor 的下一个版本中使这种情况更容易。

与此同时,这里有几篇我写的关于这个主题的博客文章:

于 2011-04-03T04:48:30.583 回答
17
@helper ForwardSection( string section )
{
   if (IsSectionDefined(section))
   {
       DefineSection(section, () => Write(RenderSection(section)));
   }
}

这会做这项工作吗?

于 2011-10-15T21:37:44.377 回答
4

我不确定这在 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

简而言之,您将为(皮肤)布局页面设置布局。

于 2013-12-29T15:13:42.610 回答
1

不确定这是否会对您有所帮助,但我编写了一些扩展方法来帮助从局部中“冒泡”部分,这也适用于嵌套布局。

使用 Razor 视图引擎将内容从局部视图 ASP.NET MVC 3 注入特定部分

在子布局/视图/部分中声明

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

在任何父级中渲染

@Html.RenderDelayed();

有关更多用例,请参阅答案链接,例如即使在重复视图中声明也仅渲染一个延迟块,渲染特定延迟块等。

于 2014-12-09T20:46:04.707 回答