3

我的数据库中有两个 2 表

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>

哪个输出

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

我真正希望看到的输出如下。

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

有人可以指出我正确的方向吗???

4

2 回答 2

4

也许存在更优雅的解决方案,但这就是我的做法。

您需要一个循环来生成标题行,Foo.Number然后您需要第二个循环,您可以在其中选择所有Bars 并按它们的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

结果是这样的:

在此处输入图像描述

于 2012-07-21T06:33:33.643 回答
0

这是一种可能的方法......我一直在努力想出一个使用标准 ActionResult 的解决方案(尽管我确信这是可能的)所以我认为返回一个扁平的匿名 json 对象可能会解决问题。在控制器上粘贴一个 JsonResult 方法,通过 jQuery 调用它,然后构建你的表。此解决方案取决于按 Bar.Name 排序的记录(警告一些未经测试的代码!)

编辑:我刚刚意识到这不太正确,需要重构。当有相同数量的 Bar itms 时它可以工作,但实际上每个 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;
}
于 2012-07-21T01:14:42.280 回答