在局部视图中修改MVC 3 ViewBag不会持久保存到_Layout.cshtml

时间:2011-02-11 21:03:51

标签: view asp.net-mvc-3 razor partial viewbag

我正在使用带有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设置为“关于我们”,然后在Partial视图中我看到它重置为“关于我们从部分视图”,但是当代码命中_Layout时。 cshtml它可以追溯到“关于我们”。

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

提前致谢!

10 个答案:

答案 0 :(得分:31)

如果您将ViewBag传递给partial的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"

答案 1 :(得分:12)

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

我提出的解决方案是实现一个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对象。

答案 2 :(得分:8)

部分视图有自己的ViewBag

您可以从((WebViewPage) WebPageContext.Current.Page).ViewBag

获取该页面的ViewBag

答案 3 :(得分:8)

您可以在局部视图中执行此操作以覆盖_Layout.cshtml中的标题:

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

......

<script type="text/javascript">
    document.title = "@ViewBag.Title";
</script>

答案 4 :(得分:4)

正如其他人指出布局观看次数部分获取他们自己的 ViewBag 。但是,我能够使用以下内容: 在视图或部分中。

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

然后在_Layout

  

@ Html.ViewContext.ViewBag.Title

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

答案 5 :(得分:1)

使用

尝试@SLaks代码
(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName

答案 6 :(得分:1)

我尝试了以下内容并且有效:

在(父)视图中......

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

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

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

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

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

答案 7 :(得分:0)

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

TempData["x"] = x;

TempData会一直存在,直到被读取为止,您只需在_Layout中读取即可。你必须要小心,你要读取所有内容,以便为下一个请求清除它。

答案 8 :(得分:-1)

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

this.ViewBag.ViewBag.PropertyName 

适用于您的自定义控件。

答案 9 :(得分:-1)

我这是设计用于页面数据的内容。把它放到你的视野中。

@Page.somePropertyName = "Whatever you want";

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

@{
    if(Page.somePropertyName != null)
    {
       //Do stuff
    }
}