在部分视图中修改MVC 3 ViewBag不会保留到_Layout.cshtml
我正在使用MVC 3与Razor视图引擎。 我想在部分视图中的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"; }
这工作正常。 关于视图呈现时,页面标题是“关于我们”。 所以,现在我想在我的关于视图中呈现一个部分视图,我想修改我的部分视图中的ViewBag.Title。 ( “/Views/Shared/SomePartial.cshtml”)
@Html.Partial("SomePartial")
在这个部分视图中,我有这样的代码:
@{ ViewBag.Title = "About Us From The Partial View"; }
当我debugging这段代码,我看到ViewBag.Title设置为“关于我们”,然后在部分视图,我看到它重置为“关于我们从部分视图”,但是当代码命中_Layout.cshtml它去回到“关于我们”。
这是否意味着如果在部分视图中修改了ViewBag的内容,那么在主视图(About.cshtml)或_Layout.cshtml中不会显示(可访问)这些更改?
提前致谢!
我也有这个问题,找不到任何简洁明了的解决办法。
我想出的解决scheme是实现一个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; } }
它find当前请求的顶级控制器,并且每次在相同的HTTP请求中调用该方法时返回相同的PageData对象。 它会在第一次在新的HTTP请求中调用它时创build一个新的PageData对象。
如果您将ViewBag传递到partial的viewdatadictionary中,然后将其拉出(并投射),则可以执行任何您想要的操作并保留该引用。 很酷的部分是,因为它是dynamic的,你甚至可以添加属性,然后他们会显示在父页面的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"
局部视图获取自己的ViewBag
。
您可以从((WebViewPage) WebPageContext.Current.Page).ViewBag
获取页面的ViewBag ((WebViewPage) WebPageContext.Current.Page).ViewBag
你可以在你的局部视图中使用这个技巧来覆盖_Layout.cshtml中的标题:
@{ ViewBag.Title = "About Us From The Partial View"; } ...... <script type="text/javascript"> document.title = "@ViewBag.Title"; </script>
正如其他人指出布局 , 视图和部分获得自己的ViewBag 。 但是,我能够得到它与以下工作:在视图或部分。
@{ Html.ViewContext.ViewBag.Title = "Reusable Global Variable"; }
然后在_Layout
@ Html.ViewContext.ViewBag.Title
通过显式使用ViewContext ,视图'重新使用'相同的ViewBag。
我已经尝试了以下,它的工作原理:
在(父)视图中…
@Html.Partial("SomePartial", ViewData, null)
注意: ViewData
作为model
parameter passing,但是您必须为viewData
参数指定null
以使用正确的重载。 您不能使用ViewBag
因为Html.Partial
不喜欢dynamic。
然后,在局部视图中…
@model ViewDataDictionary @{ Model["Title"] = "About us from the partial view"; }
当然,如果您需要将model
参数用于真实模型,则必须具有更高的创造性。
尝试使用@SLaks代码
(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
如果有人仍然在寻找解决scheme,看起来你可以用TempData做到这一点:
TempData["x"] = x;
TempData被保存直到它被读取,所以你可以在_Layout中读取它。 你只需要小心,你读了一切,以便下一个请求被清除。
我使用mvc3的时候遇到了同样的问题,我发现
this.ViewBag.ViewBag.PropertyName
在您的自定义控件中工作。
我这是什么页面数据的devise。 把它放到你的视图中。
@Page.somePropertyName = "Whatever you want";
然后在布局视图中访问它。 一定要检查它不是第一个。
@{ if(Page.somePropertyName != null) { //Do stuff } }