递归列表到格式良好的表

时间:2018-05-17 13:06:02

标签: c# html asp.net asp.net-mvc

我遇到了一个稍微复杂的问题,我发现很难解开。

我有一个班级:

 public class Location
 {
    public string Name { get; set; }

    public List<Location> ChildLocations { get; set; }
 }

它再次引用了Child Location对象。所以这是一个递归List,我想在一个格式很好的HTML表格中输出这个列表。这是代码:

using System.Collections.Generic;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class Location
    {
        public string Name { get; set; }

        public List<Location> ChildLocations { get; set; }
    }

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            List<Location> locations = new List<Location>() {
                 new Location() {
                    Name = "Item 1",
                    ChildLocations = new List<Location>() {
                        new Location()
                        {
                            Name="Female",
                            ChildLocations = new List<Location>()
                            {
                                new Location() { Name = "Female 1" },
                                new Location() { Name = "Female 2" }
                            }

                        },
                        new Location()
                        {
                            Name="Male",
                            ChildLocations = new List<Location>()
                            {
                                new Location() { Name = "Male 1" },
                                new Location() { Name = "Male 2" }
                            }

                        }
                    }
                },
                 new Location() {
                    Name = "Item 2",
                    ChildLocations = new List<Location>() {
                        new Location()
                        {
                            Name="Female",
                            ChildLocations = new List<Location>()
                            {
                                new Location() { Name = "M1" },
                                new Location() { Name = "M2" },
                                new Location() { Name = "M3" }
                            }

                        },
                        new Location()
                        {
                            Name="Male",
                            ChildLocations = new List<Location>()                            

                        },
                        new Location()
                        {
                            Name="Unknown",
                            ChildLocations = new List<Location>()

                        }
                    }
                }
            };

            return View(locations);
        }
    }
}

我希望输出看起来像这样:

enter image description here

<table class="table table-border">
  <tr>
    <td rowspan="4">
      Item 1
    </td>
    <td rowspan="2">
      Female
    </td>   
    <td>
      Female 1
    </td>
  </tr> 
  <tr>
    <td>Female 2</td>
  </tr>
  <tr>
    <td rowspan="2">Male</td>
    <td>Male 1</td>
  </tr>
  <tr>
      <td>Male 2</td>    
  </tr>
  <tr>
    <td rowspan="5">
      Item 2      
    </td>
    <td rowspan="3">Female</td>
    <td>M1</td>
  </tr>
  <tr>
    <td>M2</td>
  </tr>
  <tr>
    <td>
      M3
    </td>
  </tr>
  <tr>
    <td>Male</td>
  </tr>
  <tr>
    <td>Unknown</td>
  </tr>
</table>

如果有人想查看HTML,我就有了jsfiddle:

https://jsfiddle.net/4pk0necp/

我想使用我在cshtml中以编程方式提供的数据来呈现这种类型的表:

@using WebApplication1.Controllers;
@model List<Location>
@{
    ViewBag.Title = "Home Page";
}

我知道需要一个计算行数的函数,所以我创建了一个正确返回深度的微小函数:

public static int GetDepth(this Location location)
    {
        int noOfchildren = 0;
        bool counted = false;
        foreach (Location item in location.ChildLocations)
        {
            if (item.ChildLocations.Count <= 0)
            {
                if (!counted)
                {
                    noOfchildren += location.ChildLocations.Where(i => i.ChildLocations.Count <= 0).Count();
                    counted = true;
                }
            }
            else
                noOfchildren += GetDepth(item);
        }

        return noOfchildren;
    }

Tree的给出列表只是一个示例,树中可以有很多级别的深度。任何帮助表示赞赏。

编辑:我调整了我的GetDepth函数,因为我们只需要叶级节点计数。

1 个答案:

答案 0 :(得分:2)

尝试使用以下课程。只是勉强测试:

public class TreeDrawer {

    private readonly Dictionary<Location, int> _depthMap;

    public TreeDrawer() {
        _depthMap = new Dictionary<Location, int>();
    }

    public string Draw(IEnumerable<Location> locations) {
        var sb = new StringBuilder("<table>");

        bool first = true;
        foreach (var l in locations) {
            Draw(l, sb, true, first);
            first = false;
        }

        sb.Append("</table>");

        return sb.ToString();
    }

    private void Draw(Location l, StringBuilder sb, bool fromRoot, bool first) {
        int depth = GetDepth(l);
        bool openedRow = false;
        if (fromRoot || !first) {
            sb.Append("<tr>");
            openedRow = true;
        }
        sb.Append("<td");
        if (depth > 1) {
            sb.Append(" rowspan=\"");
            sb.Append(depth);
            sb.Append("\"");
        }
        sb.Append(">");
        sb.Append(l.Name);
        sb.Append("</td>");

        bool isFirstChild = true;
        if (l.ChildLocations != null) {
            foreach (var child in l.ChildLocations) {
                Draw(child, sb, false, isFirstChild);
                isFirstChild = false;
            }
        }
        if (openedRow) {
            sb.Append("</tr>");
        }

    }

    private int GetDepth(Location l) {
        if (!_depthMap.ContainsKey(l)) {
            _depthMap.Add(l, Math.Max(1, l.ChildLocations?.Sum(GetDepth) ?? 0));
        }
        return _depthMap[l];
    }
}