EditorTemplate для свойства коллекции, не используемого при вызове EditorForModel (шаблон пользовательского объекта)

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

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

Мой шаблон объекта в основном таков:

@foreach (var property in ViewData.ModelMetadata.Properties.Where(x => x.ShowForEdit))
{
  @Html.Editor(property.PropertyName)
}

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

Является ли это ошибкой / есть ли обходные пути?

Еще немного информации:

Итак, моя модель представления содержит следующее:

[ACustomAttribute("Something")]
public IEnumerable<int> SelectedOptions { get; set; }

Атрибут реализует IMetadataAware и добавляет некоторые данные в коллекцию AdditionalValues ​​для ModelMetadata, а также устанавливает TemplateHint. Я могу прочитать эти данные из шаблона объекта, но не из моего пользовательского шаблона.


person Paul Hiles    schedule 10.08.2012    source источник


Ответы (1)


@foreach (var property in ViewData.ModelMetadata.Properties.Where(x => x.ShowForEdit))
{
    if (!string.IsNullOrEmpty(property.TemplateHint))
    {
        @Html.Editor(property.PropertyName, property.TemplateHint)
    }
    else
    {
        @Html.Editor(property.PropertyName)
    }
}

Но обратите внимание, что если вы не полагаетесь на установленные соглашения для разрешения шаблонов для сложных типов коллекций (также известных как ~/Views/Shared/EditorTemplates/NameOfTheTypeOfCollectionElements.cshtml) и использовали UIHint в своем свойстве коллекции:

[UIHint("FooBar")]
public IEnumerable<FooViewModel> Foos { get; set; }

тогда шаблон редактора ~/Views/Shared/EditorTemplates/FooBar.cshtml должен быть строго типизирован до IEnumerable<FooViewModel>, а не FooViewModel. Так что будьте осторожны, если это ваш случай, вам решать зацикливаться внутри этого пользовательского шаблона, если вы хотите получить доступ к отдельным элементам коллекции. Это больше не будет ASP.NET MVC, который будет автоматически зацикливаться и вызывать шаблон редактора для каждого элемента.


ОБНОВИТЬ:

Все еще не могу воспроизвести вашу проблему.

Пользовательский атрибут:

public class ACustomAttribute : Attribute, IMetadataAware
{
    private readonly string _templateHint;
    public ACustomAttribute(string templateHint)
    {
        _templateHint = templateHint;
    }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["foo"] = "bar";
        metadata.TemplateHint = _templateHint;
    }
}

Модель:

public class MyViewModel
{
    [ACustom("Something")]
    public IEnumerable<int> Foos { get; set; }
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel
        {
            Foos = Enumerable.Range(1, 5)
        };
        return View(model);
    }
}

Вид (~/Views/Home/Index.cshtml):

@model MyViewModel

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

Шаблон редактора для типа объекта (~/Views/Shared/EditorTemplates/Object.cshtml):

@foreach (var property in ViewData.ModelMetadata.Properties.Where(x => x.ShowForEdit))
{
    if (!string.IsNullOrEmpty(property.TemplateHint))
    {
        @Html.Editor(property.PropertyName, property.TemplateHint)
    }
    else
    {
        @Html.Editor(property.PropertyName)
    }
}

Шаблон пользовательского редактора (~/Views/Shared/EditorTemplates/Something.cshtml):

@model IEnumerable<int>

<h3>
    @ViewData.ModelMetadata.AdditionalValues["foo"]
</h3>

@foreach (var item in Model)
{
    <div>
        @item
    </div>
}

Результат:

введите здесь описание изображения

Как видите, дополнительные метаданные, которые мы добавили, отображаются в шаблоне.

person Darin Dimitrov    schedule 10.08.2012
comment
Спасибо. Однако, как я уже упоминал, если я передам имя шаблона, то, хотя он использует правильный шаблон, метаданные модели не будут правильно созданы. У меня есть элементы в коллекции AdditionalValues ​​для свойства, которое я вижу из шаблона объекта, но они не передаются. Любые идеи? - person Paul Hiles; 10.08.2012
comment
Я не понимаю, для какого свойства у вас есть дополнительные метаданные. Не могли бы вы показать код? - person Darin Dimitrov; 10.08.2012
comment
Метаданные находятся в свойстве коллекции. Это часть сложного механизма шаблонов, столь сложного с кодом, но, надеюсь, то, что я добавил к вопросу, поможет. - person Paul Hiles; 10.08.2012
comment
Достаточно ли обновленного вопроса, чтобы продолжить, или вам нужен еще код? Спасибо - person Paul Hiles; 14.08.2012
comment
@TheFlowerGuy, я все еще не могу воспроизвести вашу проблему. Я обновил свой ответ. - person Darin Dimitrov; 14.08.2012
comment
Спасибо. Был ли я идиотом. Играл и добавил элемент в ViewData с тем же именем, что и свойство в моей строго типизированной модели представления. При выполнении Html.Editor кажется, что свойство ViewData имеет приоритет. Удалил это и теперь работает нормально. Все еще не понимаю, почему мне нужно явно указывать, чтобы использовать TemplateHint для коллекций. Ожидал бы, что это будет автоматически, если бы я применил его к самому свойству коллекции. - person Paul Hiles; 14.08.2012
comment
Кстати, я целую вечность ждал такого эксперта по MVC, как вы :-) -helper" title="захват обернутого содержимого в одноразовом HTML-помощнике в стиле beginform"> stackoverflow.com/questions/10013095/ - person Paul Hiles; 14.08.2012