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

标签 c# ienumerable html-helper

我想创建一个可用于 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()如果指定特定模板,则不会进行枚举。

我知道我可以手动枚举,但我宁愿使用这种方法,除非更有知识的人提出其他建议。

最佳答案

你的助手需要

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()将为 T 生成正确 html 的方法和 IEnemerable<T>

假设您有一个 Person.cs类,在 /Views/Shared/DisplayTemplates/Person.cshtml 中创建局部 View (注意文件的名称必须与类的名称匹配)并且在 View 中只需使用

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

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

最后,如果您确实需要 2 个不同的 Person 模板在同一个 Controller 中,您可以使用 View 模型,例如 class PersonVMclass AssociatedPersonVM并创建一个 EditorTemplate对于每个

关于c# - 我可以专门为 IEnumerable 属性创建一个 HtmlHelper 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35282314/

相关文章:

C# 代表真实世界的使用

c# - 如何检查 IEnumerable<DataRow> 返回 null 或有任何行?

c# - 表单已经关闭时调用时出错

c# - 如何使用 IEnumerable 实现进度?

c# - IEnumerable<T> 如何在后台工作

asp.net-mvc - MVC - Ajax.BeginForm 不起作用

c# - List<T>.AsReadOnly() 与 IReadOnlyCollection<T>

c# - 无法使用集合初始值设定项初始化类型,因为它未实现 ienumerable

asp.net - 使用 ASP.NET MVC 3 Helpers 渲染带有标题属性的 span 标签

html - 没有 href 属性的 CakePHP 链接