теперь мы можем вызвать другой шаблон с той же моделью

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

Мой вид:

@model Mvc3VanillaApplication.Models.ContactModel

@using (Html.BeginForm())
{
    @Html.EditorForModel("Fieldset")
}

Использует шаблон набора полей (Views / Shared / EditorTemplates / Fieldset.cshtml):

<fieldset>
    <legend>@ViewData.ModelMetadata.DisplayName</legend>
    @Html.EditorForModel()
</fieldset>

Который, в свою очередь, использует базовый шаблон для всех объектов (Views / Shared / EditorTemplates / Object.cshtml):

@foreach (var prop in ViewData.ModelMetadata.Properties.Where(x => 
    x.ShowForEdit && !x.IsComplexType && !ViewData.TemplateInfo.Visited(x)))
{
    @Html.Label(prop.PropertyName, prop.DisplayName)
    @Html.Editor(prop.PropertyName)
}

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

Если я изменю представление, чтобы не указывать шаблон «Fieldset», тогда свойства моей модели будут отображаться с использованием шаблона объекта, поэтому мой шаблон объекта не будет найден.

Можно ли пропустить одну и ту же модель через несколько шаблонов?

Для чего это стоит, модель представления выглядит так:

namespace Mvc3VanillaApplication.Models
{
    [System.ComponentModel.DisplayName("Contact Info")]
    public class ContactModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}
 Eric Bock01 июн. 2011 г., 17:07
@ThangChung Ну, я переопределяю шаблон редактора объектов, потому что он тяжелый (оборачивает все в div), и я хочу расширить его, чтобы воспользоваться некоторыми другими соглашениями. Кроме того, я использую шаблон набора полей, чтобы каждая модель отображалась в наборе полей, который становится страницей в мастере с помощью javascript.
 thangchung01 июн. 2011 г., 16:54
Так что усложняй. Можете ли вы разместить свой код View Model? Таким образом, мы можем прояснить ваш вопрос. Как я знал, вы пытаетесь создать общие компоненты для всех редакторов, не так ли?

Ответы на вопрос(2)

чистить список VisitedObjects).

var templateInfo = ViewData.TemplateInfo;
ViewData.TemplateInfo = new TemplateInfo
{
    HtmlFieldPrefix = templateInfo.HtmlFieldPrefix,
    FormattedModelValue = templateInfo.FormattedModelValue
};

теперь мы можем вызвать другой шаблон с той же моделью

@Html.DisplayForModel("SecondTemplate")
Решение Вопроса

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

Я открылMVC3 исходный код, искалEditorForModel и нашел правильную функцию.

public static MvcHtmlString EditorForModel(this HtmlHelper html) {
    return MvcHtmlString.Create(TemplateHelpers.TemplateHelper(html, html.ViewData.ModelMetadata, String.Empty, null /* templateName */, DataBoundControlMode.Edit, null /* additionalViewData */));
}

Очевидно, это было не так, поэтому я нажалF12 наTemplateHelpers.TemplateHelperи как только я снова нажалF12 на однолинейном вызове, который приводит вас к сути функции. Здесь я нашел этот короткий фрагмент кода, начинающийся со строки 214TemplateHelpers.cs:

// Normally this shouldn't happen, unless someone writes their own custom Object templates which
// don't check to make sure that the object hasn't already been displayed
object visitedObjectsKey = metadata.Model ?? metadata.RealModelType;
if (html.ViewDataContainer.ViewData.TemplateInfo.VisitedObjects.Contains(visitedObjectsKey)) {    // DDB #224750
    return String.Empty;
}

Эти комментарии на самом деле в коде, и здесь у нас есть ответ на ваш вопрос:Можно ли пропустить одну модель через несколько шаблонов редактора?, ответнет *.

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

@{
    Func<dynamic, object> fieldset = @<fieldset><legend>@ViewData.ModelMetadata.DisplayName</legend>@Html.EditorForModel()</fieldset>;
}

@using (Html.BeginForm())
{
    //@Html.EditorForModel("Fieldset")
    //@Html.EditorForModel()
    @fieldset(Model)
}

И альт! Это сработало! Я оставлю это на ваше усмотрение, чтобы реализовать это как расширение (и гораздо более многократно используемый) метод. Вот небольшой пост в блоге ошаблонные делегаты бритвы.

* Технически вы можете переписать эту функцию и скомпилировать свою собственную версию MVC3, но это, вероятно, больше проблем, чем стоит. Мы пытались сделать это накарьера проект, когда мы узнали, чтоHtml.ActionLink Функция работает довольно медленно, если у вас определено несколько сотен маршрутов. Существует проблема подписи с остальными библиотеками, которые, как мы решили, не стоили нашего времени, чтобы проработать сейчас и поддерживать будущие выпуски MVC.

 Nick Larsen♦02 июн. 2011 г., 16:13
@EricBock: другой альтернативой может быть завертывание модели вFieldsetViewModel который имеет только 1 свойство, объект. Это кажется немного громоздким, хотя.
 Eric Bock02 июн. 2011 г., 15:04
Спасибо за подробный ответ; метод расширения кажется подходящим. Я посмотрел на источник и заметил (TemplateInfo.cs: 33), что был добавлен VisitedObjects HashSet для предотвращения бесконечной рекурсии. Кажется, что было бы лучше, если бы команда MVC использовала комбинацию модели и шаблона в наборе вместо исключительно модели. Таким образом, это все равно предотвратит рекурсию, но позволит применять несколько шаблонов. Однако я буду держаться подальше от своей собственной версии MVC.

Ваш ответ на вопрос