43

我正在使用带有 Razor 视图引擎的 MVC 3。我想在部分视图内的 ViewBag 中设置一些值,并希望在我的 _Layout.cshtml 中检索这些值。例如,当您设置默认的 ASP.NET MVC 3 项目时,您会在“/Views/Shared”文件夹中获得一个 _Layout.cshtml 文件。在那个 _Layout.cshtml 中,页面标题设置如下:

<title>@ViewBag.PageTitle</title>

然后在“/Views/Home/About.cshtml”视图中修改ViewBag的内容:

@{
    ViewBag.Title = "About Us";
}

这工作正常。呈现关于视图时,页面标题为“关于我们”。所以,现在我想在 About 视图中呈现 Partial 视图,并且我想在 Partial 视图中修改 ViewBag.Title。("/Views/Shared/SomePartial.cshtml")

@Html.Partial("SomePartial")

在此部分视图中,我有以下代码:

@{
    ViewBag.Title = "About Us From The Partial View";
}

当我调试这段代码时,我看到 ViewBag.Title 被设置为“关于我们”,然后在部分视图中我看到它被重置为“从部分视图中关于我们”,但是当代码点击 _Layout.cshtml 时回到“关于我们”。

这是否意味着如果在 Partial 视图中修改了 ViewBag 的内容,这些更改将不会出现(可访问)在主视图(About.cshtml)或 _Layout.cshtml 中?

提前致谢!

4

10 回答 10

33

如果您将 ViewBag 传递到部分的 viewdatadictionary,然后将其拉出(并投射),您可以做任何您想做的事情并保留参考。很酷的部分是,由于它是动态的,您甚至可以添加属性,然后它们将显示在父页面的 Viewbag 上。

页:

//set the viewbag into the partial's view data
@{Html.RenderPartial("Elaborate", Model, new ViewDataDictionary { {"vb", ViewBag}});}

部分的:

@{
   var vb = ((dynamic)ViewData["vb"]);
   vb.TheTitle = "New values";
 }

@ViewBag.TheTitle = "New value"
于 2011-03-02T15:55:55.987 回答
13

我也遇到了这个问题,找不到任何简洁明了的解决方案。

我想出的解决方案是实现一个 Html 扩展方法,该方法返回您定义的“PageData”类,包含您需要的任何数据:

    [ThreadStatic]
    private static ControllerBase pageDataController;
    [ThreadStatic]
    private static PageData pageData;

    public static PageData GetPageData(this HtmlHelper html) {
        ControllerBase controller = html.ViewContext.Controller;
        while (controller.ControllerContext.IsChildAction) {
            controller = controller.ControllerContext.ParentActionViewContext.Controller;
        }
        if (pageDataController == controller) {
            return pageData;
        } else {
            pageDataController = controller;
            pageData = new PageData();
            return pageData;
        }
    }

它找到当前请求的顶级控制器,并且每次在同一个 HTTP 请求中调用该方法时都返回同一个 PageData 对象。第一次在新的 HTTP 请求中调用它时,它会创建一个新的 PageData 对象。

于 2011-02-12T21:46:30.197 回答
8

局部视图拥有自己的ViewBag.

您可以从中获取页面的 ViewBag((WebViewPage) WebPageContext.Current.Page).ViewBag

于 2011-02-11T21:17:13.520 回答
7

您可以在局部视图中使用此技巧来覆盖 _Layout.cshtml 中的标题:

@{
    ViewBag.Title = "About Us From The Partial View";
}

......

<script type="text/javascript">
    document.title = "@ViewBag.Title";
</script>
于 2012-11-14T19:40:32.273 回答
4

正如其他人指出的LayoutViewsPartials有自己的ViewBag。但是,我能够让它与以下内容一起使用:在视图或部分中。

@{ Html.ViewContext.ViewBag.Title = "Reusable Global Variable"; }

然后在_Layout

@Html.ViewContext.ViewBag.Title

通过显式使用ViewContext,视图“重用”相同的 ViewBag。

于 2012-06-12T00:30:29.033 回答
3

如果有人仍在寻找解决方案,看来您可以使用 TempData 来解决:

TempData["x"] = x;

TempData 会一直保存到被读取,因此您可以在 _Layout 中读取它。您只需要小心阅读所有内容,以便为下一个请求清除它。

于 2017-05-09T11:51:03.010 回答
1

尝试使用@SLaks 代码

(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
于 2011-06-07T03:13:11.487 回答
1

我已经尝试了以下方法并且它有效:

在(父)视图中...

@Html.Partial("SomePartial", ViewData, null)

注意: ViewData作为参数传递model,但您必须指定null参数viewData以使用正确的重载。你不能使用ViewBag,因为Html.Partial不喜欢动态。

然后,在局部视图中...

@model ViewDataDictionary
@{
    Model["Title"] = "About us from the partial view";
}

当然,如果您需要将model参数用于真实模型,则必须更具创造性。

于 2013-01-14T14:56:57.867 回答
-1

我在使用mvc3时遇到了同样的问题,我发现

this.ViewBag.ViewBag.PropertyName 

在您的自定义控件中工作。

于 2011-10-27T01:00:52.670 回答
-1

我这就是页面数据的设计目的。将此弹出到您的视图中。

@Page.somePropertyName = "Whatever you want";

然后在您的布局视图中访问它。请务必先检查它是否不为空。

@{
    if(Page.somePropertyName != null)
    {
       //Do stuff
    }
}
于 2013-06-20T15:33:01.533 回答