2012-07-20 40 views
3

我有我的数据库中有两个2表MVC 3剃须刀显示父/子表作为一个表

Table: Foo     Table: Bar 
-----------------   --------------------- 
|FooID  | Int|   |BarID  | Int | 
|Number | Int|   |FooID  | Int | 
-----------------   |Name  | String | 
          |Value  | Int | 
          --------------------- 

With data     with data 
|FooID | Number |   |BarID |FoodID |Name |Value | 
|1  | 1  |   |1  |1  |apple |100 | 
|2  | 2  |   |2  |1  |orange |110 | 
          |3  |2  |apple |200 | 
          |4  |2  |orange |40 | 

以上是相关车型

class Foo 
{ 
    public int FooID { get; set; } 
    public int Number { get; set;} 

    public virtual ICollection<Bar> Bars { get; set; } 
} 

class Bar 
{ 
    public int BarID { get; set; } 
    public int FooID { get; set; } 
    public string Name { get; set;} 
    public int Value { get; set;} 
} 

我可以伊斯利在这样一个表中显示此通过在其输出

视图

<table> 
    @foreach(var f in Model) 
    { 
     <tr> 
      foreach(var b in f.Bar) 
      { 
       <td>@f.Number</td> 
       <td>@b.Name</td> 
       <td>@b.Value</td> 
      } 
     </tr> 
    } 
</table> 

做follwing格式

------------------- 
|1 |apple |100| 
------------------- 
|1 |orange |110| 
------------------- 
|2 |apple |200| 
------------------- 
|2 |orange | 40| 
------------------- 

我真的会看到输出结果如下。

------------------------- 
|   | 1  | 2 | 
------------------------- 
|apple |100  |200 | 
------------------------- 
|orange |200  | 40 | 
------------------------- 

有人能指点我在正确的方向?

+0

你肯定Foo.Number将始终从1开始,sequencialy增长? – Mohayemin 2012-07-20 23:14:10

+0

感谢您的回复。是的,我确信它将从1开始并逐步增长......但是这很重要吗?如果Foo.Number是一个字符串而不是Int?任何建议帮助。再次感谢! – 2012-07-20 23:36:20

+0

噢,我想我知道你可能在...... Foo.Number将重置为1并在我的应用程序中再次备份。我试图通过删除多余的字段来简化我的问题。 – 2012-07-20 23:39:20

回答

4

也许有更优雅的解决方案存在,但这里是我会怎么做。

您需要一个循环来生成Foo.Number中的标题行,然后您需要第二个循环,您可以在其中选择所有Bar s并按它们的Name对它们进行分组。从这些组中可以生成数据行。

现在,您只需要一个通过Bar.Value s构建表格行的第三个循环。

所以上述的“算法”中的代码:

<table> 
    <tr> 
     <td> 
      &nbsp; 
     </td> 
     @foreach (var f in Model.OrderBy(f => f.FooID)) 
     { 
      <td>@f.Number 
      </td> 
     } 
    </tr> 
    @foreach (var group in Model.SelectMany(f => f.Bars).GroupBy(b => b.Name)) 
    { 
     <tr> 
      <td>@group.Key 
      </td> 
      @foreach (var b in group.OrderBy(b => b.FooID)) 
      { 
       <td>@b.Value 
       </td> 
      } 
     </tr> 
    } 
</table> 

注:我已经添加了OrderBy(b => b.FooID),以确保该Bar值正确地与Foo.Number头对齐。

而这个结果看起来像:

enter image description here

+0

**谢谢** sooo much @nemesv!你的代码工作。它看起来有点把foo吧的情况翻译回我的应用程序,但我把它运用起来了。再次感谢! – 2012-07-21 20:52:04

0

这里有一种可能的方法...我正在努力想出一个使用标准ActionResult的解决方案(虽然我确信这是可能的),所以我认为返回一个扁平化的匿名json对象可能会诀窍。在你的Controller上粘贴一个JsonResult方法,通过jQuery调用它然后建立你的表。这个解决方案取决于Bar.Name排序的记录(警告一些未经测试的代码!)

编辑:我刚刚意识到这并不完全正确,需要重构。它适用于Bar条数相同的情况,但实际上每个Foo可能会有一个可变数字,因此添加到每行的元素数量需要等于Bar条目的最大数量。

public JsonResult GetBarsForFoos() 
{ 
    var foos = from f in repositoryOrContext.Foos.Include("Bar") 
     select f; 

    return foos == null 
    ? Json(new object[0], JsonRequestBehavior.AllowGet) 
    : Json(foos.Bars.OrderBy(bar => bar.Name).Select(
     bar => new { foos.Number, bar.Name, bar.Value }).ToArray(), 
     JsonRequestBehavior.AllowGet); 
} 

然后在jQuery的:

function populateFoos() { 
    $.ajax({ 
     url: '/Foo/GetBarsForFoos', 
     async: false 
    }).done(function (data) { 
     // have an empty table in your Razor with an id of tblFoos 
     var fooTable = $('#tblFoos'); 
     fooTable.html(''); 
     fooTable.append(createFooTable(data)); 
    }).error(function (msg, url, line) { 
     alert("Error - error message: " + line); 
    }); 
} 

function createFooTable(data) { 
    var html = '', 
    len = data.length, 
    currentBarName = '', 
    allBarNumbers = []; 

    html = '<table><tr><td></td>'; 

    // Create 1st row that contains foo.Number 
    for (var i = 0; i < len; i++) { 

     if (allBarNumbers.indexOf(data[i].Number) === -1) { 
      allBarNumbers.push(data[i].Number); 

      html += '<td>' + data[i].Number + '</td>'; 
     }   
    } 

    html += '</tr>'; 

    // Create further rows that line up Name and Value under their foo.Number values 
    for (var x = 0; x < len; x++) { 

     if (x === 0) { 
      html += '<tr>'; 
     } 

     // grab Bar name if changed 
     if (currentBarName != data[x].Name) { 
      currentBarName = data[x].Name; 

      if (x !== 0) { 
       html += '</tr><tr>'; 
      } 
      html += '<td>' + currentBarName + '</td>'; 
     } 

     html += '<td>' + data[x].Value + '</td>'; 
    } 

    html += '</tr>/<table>'; 

    return html; 
} 

您可以使用此测试createFooTable:

function testFooTable() { 

    var data = [ 
     { Number: 1, Name: 'apple', Value: 100 }, 
     { Number: 2, Name: 'apple', Value: 200 }, 
     { Number: 1, Name: 'orange', Value: 110 }, 
     { Number: 2, Name: 'orange', Value: 40 } 
    ]; 

    var fooTable = createFooTable(data); 

    return fooTable; 
}