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

もっとエレガントな解決策が存在するかもしれませんが、これが私がそれを行う方法です。

ヘッダー行を生成するために1つのループが必要Foo.Numberです。次に、すべてのを選択し、Barそれらをそれらでグループ化する2番目のループが必要ですName。これらのグループから、データ行を生成できます。

Bar.Valueこれで、 sを通過してテーブル行を作成するthridループのみが必要になります。

したがって、上記の「アルゴリズム」はコードで次のようになります。

<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)いることを確認するために、を追加しました。BarFoo.Number

そして、これは結果がどのように見えるかです:

ここに画像の説明を入力してください

于 2012-07-21T06:33:33.643 に答える
0

これを行うための1つの可能な方法があります...私は標準の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 に答える