调用EditorForModel时未使用的集合属性的EditorTemplate(自定义对象模板)

时间:2012-08-10 12:20:37

标签: asp.net-mvc asp.net-mvc-3 mvc-editor-templates

我知道在使用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并将一些内容添加到ModelMetadata的AdditionalValues集合以及设置TemplateHint。我可以从对象模板中读取这些数据,但不能从我的自定义模板中读取。

1 个答案:

答案 0 :(得分:2)

@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)
    }
}

但请注意,如果您不依赖已建立的约定来解析复杂集合类型的模板(a.k.a ~/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>
}

结果:

enter image description here

因此,您可以看到我们添加的其他元数据显示在模板中。