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ビューがレンダリングされると、ページタイトルは「About Us」になります。だから、今、私はAboutビュー内でPartialビューをレンダリングし、Partialビュー内でViewBag.Titleを変更したいです。 ( "/Views/Shared/SomePartial.cshtml")
@Html.Partial("SomePartial")
この部分ビューには、次のコードがあります。
@{
ViewBag.Title = "About Us From The Partial View";
}
このコードをデバッグすると、ViewBag.Titleが "About Us"に設定され、Partialビューで "About Us From The Partial View"にリセットされますが、コードが_Layout.cshtmlに達すると、 「会社概要」に戻ります。
これは、ViewBagのコンテンツが部分ビューで変更された場合、それらの変更がメインビュー(About.cshtml)または_Layout.cshtmlに表示されないことを意味しますか?
前もって感謝します!
私もこの問題を抱えていて、きちんとした明確な解決策を見つけることができませんでした。
私が思いついた解決策は、必要なデータを含む、定義した「PageData」クラスを返すHtml拡張メソッドを実装することでした。
[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オブジェクトを作成します。
ViewBagをパーシャルのviewdatadictionaryに渡し、それを引き出し(そしてキャスト)すると、何でもできますし、参照は保持されます。クールな部分は、動的であるため、プロパティを追加して、親ページのビューバッグに表示することもできます。
ページ:
//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
を取得します。
ページの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を「再利用」します。
で@SLaksコードを試す
(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
私は次を試してみましたが、うまくいきます:
(親)ビューで...
@Html.Partial("SomePartial", ViewData, null)
注:ViewData
はmodel
引数として渡されますが、正しいオーバーロードを使用するには、null
引数にviewData
を指定する必要があります。 ViewBag
を使用できないのは、Html.Partial
はダイナミクスが好きではありません。
次に、部分ビューで...
@model ViewDataDictionary
@{
Model["Title"] = "About us from the partial view";
}
もちろん、実際のモデルにmodel
引数を使用する必要がある場合は、より創造的にする必要があります。
誰かがまだこれに対する解決策を探しているなら、TempDataでそれを行うことができるようです:
TempData["x"] = x;
TempDataは読み取られるまで保持されるため、_Layoutで読み取ることができます。次のリクエストでクリアされるように、すべてを読むように注意する必要があります。