2013-05-21 3 views
2

У меня есть сайт ASP.NET MVC 4, организованный во множество областей. Каждая область имеет вид Views/Shared/_Layout.cshtml, который ссылается на общий общий макет. В общем макете у меня есть боковая панель, содержащая список элементов. Я хотел бы иметь возможность иметь общий список элементов, доступ к которым можно получить во всех представлениях _Layout.cshtml, чтобы агрегировать набор ссылок.Добавить данные в общий _Layout.cshtml из области MVC _Layout.cshtml

Area1/Просмотров/Shared/_Layout.cshtml:

@{ 
    SidebarItems.Add("Area1 Item"); 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 

Просмотров/Shared/_Layout.cshtml:

@{ 
    SidebarItems.Add("Common Item"); 
} 
<ul> 
@foreach (var item in SidebarItems) 
{ 
    <li>@item</li> @* List should contain two items: "Area1 Item", and "Common Item" *@ 
} 
</ul> 

я попытался два подхода:

  1. Создать обычай WebViewPage<T> для каждой области, которая наследуется от общего класса WebViewPage<T> и делает коллекцию SidebarItems собственностью общего базового класса. Это не работает, поскольку кажется, что Razor выделяет новый WebPageView при перемещении между макетами.

  2. Создайте статический класс со статической коллекцией, в которой каждый _Layout призывает добавлять элементы. Это успешно накапливает элементы списка, но, поскольку это статический класс, его время жизни привязано к домену приложений, что означает, что боковая панель накапливает элементы из каждой области, которая посещается несколькими запросами, а не является списком для каждого запроса.

Я рассматриваю, используя HttpRequest.Items собственности, но, похоже, это было бы слишком недолгим - список элементов не изменяется между запросами и полностью определяется видом района, который отображается.

Другой альтернативой является толкать рендеринг списка в section, который отображается в каждом поле _Layout. Это меньше, чем идеально, поскольку я хотел бы иметь одну точку в коде, который отображает список, но выполним.

Предложения?

ответ

3

Вы можете попробовать использовать ViewBag для этого.

Я сделал быстрый тест, добавив свойство с именем Items в ViewBag. Это будет заполнено из каждой области (путем добавления собственных элементов) и из основного макета, добавив общие элементы. Затем он будет использоваться для отображения списка элементов из основного макета.

Area1 \ Views \ Shared_Layout.cshtml

@{ 
    ViewBag.Title = "_Layout"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 

    if (ViewBag.Items == null){ViewBag.Items = new List<String>();} 
    ViewBag.Items.Add("Area1 item"); 
} 

<h2>Area1 Layout</h2> 

@RenderBody() 

Просмотров \ Shared_Layout.cshtml (часть)

@{ 
    if (ViewBag.Items == null){ViewBag.Items = new List<String>();} 
    ViewBag.Items.Add("Common Item"); 
} 
<ul> 
@foreach (var item in ViewBag.Items) 
{ 
    <li>@item</li> @* List should contain two items: "Area1 Item", and "Common Item" *@ 
} 
</ul> 

Я не люблю много, как это выглядит код, поскольку он довольно много повторяет и расширяет использование элементов ViewBag.Items. Это может быть более чистым с помощью помощников Html для добавления элементов в список и отображения списка.Например, можно создать следующие 2 Html помощников:

public static class HtmlHelpers 
{ 
    public static void AddCommonListItems(this HtmlHelper helper, params string[] values) 
    { 
     if(helper.ViewContext.ViewBag.Items == null) helper.ViewContext.ViewBag.Items=new List<String>(); 
     helper.ViewContext.ViewBag.Items.AddRange(values); 
    } 

    public static MvcHtmlString CommonList(this HtmlHelper helper) 
    { 
     if (helper.ViewContext.ViewBag.Items == null) 
      return new MvcHtmlString(new TagBuilder("ul").ToString()); 

     var itemsList = new TagBuilder("ul"); 
     foreach (var item in helper.ViewContext.ViewBag.Items) 
     { 
      var listItem = new TagBuilder("li"); 
      listItem.SetInnerText(item); 
      itemsList.InnerHtml += listItem.ToString(); 
     } 
     return new MvcHtmlString(itemsList.ToString()); 

    } 
} 

И тогда ваши мнения будут выглядеть чище, так как они будут использовать только те помощники и избежать повторения кода:

Area1 \ Views \ Shared_Layout .cshtml (с использованием новых помощников HTML)

@{ 
    ViewBag.Title = "_Layout"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 

    Html.AddCommonListItems("Area1 item", "Area1 item 2"); 
} 

<h2>Area1 Layout</h2> 

@RenderBody() 

Views \ Shared_Layout.cshtml (часть его, используя новые хелперов HTML)

@{Html.AddCommonListItems("Common Item");} 
@Html.CommonList() 
+0

Кажется хорошо работать. Не могу поверить, что я забыл о «ViewBag». Принять завтра не возникнет никаких других проблем. – Lucas

+0

Отлично! (Не слишком гордясь именами помощников, вы, вероятно, могли бы разработать лучшие, которые имеют смысл для ваших бизнес-требований ...) –

Смежные вопросы