我可以专门为IEnumerable属性创建一个HtmlHelper吗?

本文关键字:一个 HtmlHelper IEnumerable 创建 属性 我可以 | 更新日期: 2023-09-27 18:33:41

我想创建一个可用于IEnumerable属性的HtmlHelper。

目的是像这样使用它:

@Html.DisplayForEnumerable(m => m.EnumerableItemsProperty, "ViewTemplateName");

如果可能的话,我想使用 m => m.Items lambda 语法(而不是通过 Model.Items (。

这是我迄今为止最大的努力。但我不确定如何从表达式参数中获取items变量。

怀疑我可能不得不使用 IEnumerable<TValue> 之类的东西作为表达式的返回类型,但我对泛型很陌生,我不知道如何实现这一点。

public static MvcHtmlString DisplayForEnumerable<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable>> expression, string templateName, object additonalViewData = null)
{
    var sb = new StringBuilder();
    // how to get items variable?
    foreach (var item in items)
    {
        var item1 = item;
        sb.Append(html.DisplayFor(m => item1, templateName, additonalViewData));
    }
    return MvcHtmlString.Create(sb.ToString());
}

更新

澄清一下 - 我之所以采用这种方法,是因为我希望能够为同一模型指定不同的模板。 如果指定特定模板,则不会发生正常的DisplayFor()枚举。

我知道我可以手动枚举,但我宁愿使用这种方法,除非有知识渊博的人另有建议。

我可以专门为IEnumerable属性创建一个HtmlHelper吗?

你的助手需要

public static MvcHtmlString DisplayForEnumerable<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string templateName, object additionalViewData = null)
{
    ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
    IEnumerable collection = metaData.Model as IEnumerable;
    if (collection == null)
    {
        return helper.DisplayFor(expression, templateName, additionalViewData );
    }
    StringBuilder html = new StringBuilder();
    foreach (var item in collection)
    {
        html.Append(helper.DisplayFor(m => item, templateName, additionalViewData).ToString());
    }
    return MvcHtmlString.Create(html.ToString());
}

请注意,代码允许您传递单个TIEnumerable<T>(尽管方法名称现在没有实际意义(。如果你想把它限制为只有IEnumerable<T>你可以抛出一个InvalidCastException,如果collection == null

请注意,如果要为集合(例如 EditorForEnumerable() 方法(生成表单控件,则此方法不起作用,因为所需的集合索引器不会添加到生成name属性中。更好的方法是使用内置的DisplayFor()EditorFor()方法,这些方法将为TIEnemerable<T>生成正确的html

假设您有一个Person.cs类,请在 /Views/Shared/DisplayTemplates/Person.cshtml 中创建分部视图(请注意,文件名必须与类的名称匹配(,并在视图中简单地使用

@Html.DisplayFor(m => m.yourCollectionProperty)

您还可以为每个控制器创建特定的显示和编辑器模板,例如 /Views/yourControllerName/DisplayTemplates/Person.cshtml 。这允许您在/Persons/Index中使用一个模板,在/Organisation/Details/1中使用另一个模板,这可能会显示与Organisation关联的Person列表

最后,如果您确实需要 2 个不同的模板用于同一控制器中的Person,则可以使用视图模型,例如 class PersonVMclass AssociatedPersonVM,并为每个模型创建一个EditorTemplate