我遇到了一个稍微复杂的问题,我发现很难解开。
我有一个班级:
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);
}
}
}
我希望输出看起来像这样:
<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函数,因为我们只需要叶级节点计数。
答案 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];
}
}