使用Razor模板创建一个包含n列的表

时间:2015-10-26 17:37:49

标签: c# css asp.net-mvc razor

我需要创建一个数据表,我知道将要出现的行数,但列数会有所不同。该表将存在于剃刀模板中。

理想情况下,我会使用单个foreach循环迭代集合并在循环内部,我会为每个对象添加一列。

这是我现在使用它的方式,但这需要每行一个循环。有30行,这不是一个理想的解决方案。

<table>
  <tr>
    @foreach(var o in oCollection)
    {
      <td>@o.Name</td>
    }
  </tr>
  <tr>
    @foreach(var o in oCollection)
    {
      <td>@o.Id</td>
    }
  </tr>
  <tr>
    @foreach(var o in oCollection)
    {
      <td>@o.Address</td>
    }
  </tr>
</table>

注意:我在我的示例中使用HTML表,但这不是必需的。只有数据显示在输出等表格中。

编辑:这是2个对象输出的小提琴示例。 http://jsfiddle.net/rked00dr/。这是3个对象的示例。 http://jsfiddle.net/rked00dr/2/

3 个答案:

答案 0 :(得分:6)

您正在寻找的是调用数据透视。而是试图在Razor视图中生成它,您可以在Controller中处理它并使用透视数据来避免您已经提到的复杂性。

假设您的数据如下:

            var list = new List<Entity>();
            list.Add(1, "Thing1", "WithAddress_1");
            list.Add(2, "Thing2", "WithAddress_2");
            list.Add(3, "Thing3", "WithAddress_3");
            list.Add(4, "Thing4", "WithAddress_4");
            list.Add(5, "Thing5", "WithAddress_5");
            list.Add(6, "Thing6", "WithAddress_6");

注意:不要担心这个初始化我使用列表扩展来完成这项工作。

使用类似下面的函数虽然它不是Pivot数据的最佳方法,但它可以做到这一点。 创建如下所示的扩展方法。确保将List<Entity>替换为您键入的内容。

Public static class ListExtensions
 {
    Public static IEnumerable<dynamic> ToPivot(this List<Entity> oCollection)
    {
        List<dynamic> parent = new List<dynamic>();
        List<dynamic> extended = null;

        foreach (Entity entity in oCollection)
        {
            extended = new List<dynamic>();
            foreach (var prop in entity.GetType().GetProperties())
            {
                extended.Add(new { Property = prop.Name, Value = prop.GetValue(entity) });
            }

            parent.AddRange(extended);
        }

        // Grouping of value by property names, so each property
        // represents list of all values w.r.t to that property in given list.
        var grps = from d in parent
                   group d by d.Property
                       into grp
                       select new
                       {
                           Property = grp.Key,
                           Values = grp.Select(d2 => d2.Value).ToArray()
                       };
        return grps;
    }
}

现在您只需将此功能调用到您的收藏中即可。

  <table>
    foreach (var item in oCollection.ToPivot())
    {
       <tr>
        <td>
           @item.Property;
        <td>
        foreach (var value in item.Values)
        {
            <td>
                @value;
           </td>
        }
       <tr>
    }
  </table>

输出:

+---------+---------------+---------------+-----+
| Id      | 1             | 2             | ... |
| Name    | Thing1        | Thing2        | ... |
| Address | WithAddress_1 | WithAddress_2 | ... |
+---------+---------------+---------------+-----+

我建议的通用版本(根据以下评论 - &gt; jim):

public static IEnumerable<dynamic> ToPivot<T>(this IList<T> oCollection)
{
    var parent = new List<dynamic>();

    try
    {
        foreach (T entity in oCollection)
        {
            var extended = new List<dynamic>();
            foreach (var prop in entity.GetType().GetProperties())
            {
                extended.Add(new { Property = prop.Name, Value = prop.GetValue(entity) });
            }

            parent.AddRange(extended);
        }

        // Grouping of value by property names, so each property
        // represents list of all values w.r.t that property in given list.
        var grps = parent.GroupBy(d => d.Property).Select(grp => new
        {
            Property = grp.Key,
            Values = grp.Select(d2 => d2.Value).ToArray()
        });
        return grps;
    }
    catch
    {
        // log the reason perhaps
        return default(dynamic);
    }
}

答案 1 :(得分:1)

这将允许您只需迭代集合一次即可构建列。

@{
    string row1;
    string row2;
    string row3;
    foreach (var o in oCollection)
    {
        row1 += string.Format("<td>{0}</td>", o.Name);
        row2 += string.Format("<td>{0}</td>", o.Id);
        row3 += string.Format("<td>{0}</td>", o.Address);
    }
}
<table>
    <tr>
        @Html.Raw(row1);
    </tr>
    <tr>
        @Html.Raw(row2);
    </tr>
    <tr>
        @Html.Raw(row3);
    </tr>
</table>

答案 2 :(得分:1)

如果你想要功能,你可以做这样的事情。其中oCollectionItemoCollection

中的任何类型
@{
    List<Func<oCollectionItem, string>> funcs = new List<Func<oCollectionItem, string>>(){
        x => x.Name,
        x => x.Address,
        x => x.ID.ToString(), 
       //repeat for each thing to display
    };
}


<table>
    @foreach(var func in funcs)
    {
        <tr>
            @foreach(var item in oCollection)
            {
              <td>@func(item)</td>
            }
        </td>    
    }
</table>