2015-02-27 6 views
0

Я использую ASP.NET MVC5 вместе с knockout.js. У меня есть несколько шаблонов knockout.js, orginized на частичные виды. Когда у меня есть компонент в представлении или частичном представлении, для которого нужен один или несколько конкретных шаблонов, я включаю соответствующие шаблоны с Html.Partial. Однако есть проблема, которую мне нужно решить: таким образом, если сам компонент находится в частичном, и у меня есть два или более компонентов, включенных в представление, шаблоны будут включаться два или более раз, что нежелательно.Как включить Частичный, но только если он еще не включен?

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

Есть ли какие-либо проблемы с выпуском или сторонними решениями этой проблемы?

+0

Попробуйте использовать погрузчики AMD, такие как JS. –

+1

Невозможно достичь этого с помощью Razor. Razor не поддерживает текущие результаты просмотра. Если вы включите частичное, оно будет слепо отображать его, будь то в первый раз или сотый. –

+0

Спасибо, да, к сожалению, это тоже было моей догадкой. Тем временем я работаю над вспомогательным методом расширения, чтобы это стало возможным. Мой план состоит в том, чтобы отслеживать обработанные частичные запросы для текущего запроса, поэтому я могу знать, должен ли я отменять базовый частичный метод. Если мне удастся собрать это вместе, я отвечу на мой вопрос. –

ответ

1

У меня была аналогичная проблема. Вот как я это решил. Я не люблю это решение, но оно работает. Если есть лучший способ, я бы с удовольствием это услышал.

public static class PartialExtension 
    { 
     public static void AddPartial(this HtmlHelper html, string partialLocation) 
     { 
      //Get a name for the template. This is used to identify the template and 
      //to ensure that a blank location has not been sent it. 
      var partialName = Path.GetFileNameWithoutExtension(partialLocation); 
      if (partialName == null) 
       throw new Exception("The partial location can not be null"); 

      //Get the extension and directory. If the location doesn't specify 
      //a directory, like the location is in the current directory, then 
      //we need to remove the extension. Not sure why, but html.Partial() 
      //throws an exception if you don't. 
      var extension = Path.GetExtension(partialLocation); 
      var dir = Path.GetDirectoryName(partialLocation); 
      if (string.IsNullOrWhiteSpace(dir) && string.IsNullOrWhiteSpace(extension) == false) 
       partialLocation = partialLocation.Replace(extension, ""); 

      var tmpBag = html.ViewBag; 
      tmpBag.TbdTemplates = tmpBag.TbdTemplates as Dictionary<string, MvcHtmlString> ?? new Dictionary<string, MvcHtmlString>(); 

      //Only add this template once. 
      if (((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates).ContainsKey(partialName)) return; 

      //FYI: because html.Partial can call this recursively, we want to set the item in the dictionary 
      //as soon as possible. Then we call Partial(). The final call to that method will be what is 
      //set as the value in the dictionary. 
      ((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates)[partialName] = MvcHtmlString.Create(""); 

      var tmpHtml = html.Partial(partialLocation, html.ViewData); 
      ((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates)[partialName] = tmpHtml; 
     } 

     public static MvcHtmlString WritePartials(this HtmlHelper html) 
     { 
      var tmpBag = html.ViewBag; 
      tmpBag.TbdTemplates = tmpBag.TbdTemplates as Dictionary<string, MvcHtmlString> ?? new Dictionary<string, MvcHtmlString>(); 

      if (tmpBag.TbdTemplates == null) return MvcHtmlString.Create(""); 

      var builder = new StringBuilder(); 
      foreach (var value in tmpBag.TbdTemplates.Values) 
      { 
       builder.Append(value); 
      } 

      return MvcHtmlString.Create(builder.ToString()); 
     } 
    } 

Затем в моем _Layout.cshtml. (К дну)

<div id="Partials" style="display: none;"> 
     @Html.WritePartials() 
    </div> 
+1

Это выглядит хорошо, и я думаю, что ваше решение ближе к моему вопросу. Я думаю, что это «симпатично». Я имею в виду, что MVC в основном похож на скелет, мы должны постоянно его настраивать (по крайней мере, в моем прошлом опыте), особенно если один из них (как и сейчас) использует его скорее для Web API, чем для бэкэнд, чем для классического MVC. Проект должен быть нереалистично простым, чтобы не требовать каких-либо настроек. Спасибо, я постараюсь использовать ваше решение. –

0

Решения проблемы с Razor/partial, о которых я знаю, не существует.

Вы должны взглянуть на Knockout Components (представленный в версии 3.2), предназначенный для решения этой проблемы.

Нокаутные компоненты могут отображать шаблон и viewModel различными способами. Модель и модель просмотра определяются только один раз и повторно используются столько раз, сколько требуется.

Если вы используете загрузчик модуля типа requireJS (Knockout позволяет использовать любой загрузчик), он также может динамически загружать шаблоны и сценарии по требованию. Компоненты также могут быть вложенными и повторно использоваться. Это должно отвечать вашим требованиям.

+0

Спасибо, я знаю о компонентах KO, но я сильно полагаюсь на Razor при рендеринге даже шаблонов KO. У меня много помощников для сокращения кодирования. –

+0

@ ZoltánTamási. Если бы вы создали контроллер, который вместо этого отобразил частичные виды, вы могли бы иметь лучшее из обоих миров.Я никогда не пробовал, но если вы вернете PartialView() вместо View(), который позволит вам использовать код бритвы и компоненты KO вместе. (Или Require.js) – Jeff

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