2

状況: 1ページに複数のGridviewがあり、各Gridviewには動的に作成された行があり、合計が下部に表示されます。いずれの場合も、合計行はRowDataBoundイベントで作成されます。私が使用している戦略は、MikeDuganが彼のブログで提供しているものと似ています。

以下は、GridViewの1つのコードですが、他のすべては非常に似たようなことをします。

protected void gvWorkerHours_RowDataBound(object sender, GridViewRowEventArgs e)
{
    // Keep running total of hours.  
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        totalBillableHours += Convert.ToDouble(DataBinder.Eval(e.Row.DataItem, "Hours"));
    }

    if (e.Row.RowType == DataControlRowType.Footer)
    {
        int numColumns = gvWorkerHours.Columns.Count;
        int hoursIndex = 4; //5th column, 0-based
        int rowIndex = gvWorkerHours.Rows.Count + 1;

        CreateTotalRow((Table)e.Row.Parent, rowIndex, totalBillableHours, hoursIndex, numColumns);
    }
}

private void CreateTotalRow(Table table, int rowIndex, double totalValue, int totalIndex, int numColumns)
{
    TableCell[] cells = new TableCell[numColumns];
    for (int i = 0; i < numColumns; i++)
    {
        TableCell cell = new TableCell();
        Label label = new Label();
        label.Font.Bold = true;

        if (i == 0)
        {
            label.Text = "Total";
        }
        else if (i == totalIndex)
        {
            label.Text = totalValue.ToString();
        }
        else
        {
            label.Text = "";
        }

        cell.Controls.Add(label);
        cells[i] = cell;
    }
    GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);
    row.Cells.AddRange(cells);
    table.Rows.AddAt(rowIndex, row);
}

問題:ユーザーがこれらのグリッドビューのいずれかの行の編集/削除コマンドをクリックすると、他のすべてのグリッドビューの合計行が非表示になります。私が理解しているように、これはPostBackが発生しているためですが、RowDataBoundイベントは他のGridViewに対しては発生せず、合計を含まないViewStateからデータをリロードするだけです。

解決の試みの失敗: PostBack中に各GridViewでDataBindを呼び出すことはできません。これにより、更新/削除が発生しなくなります。PostBack中にGridViewsに対してRowCreatedイベントが発生しますが、GridViewsにはデータがバインドされておらず、合計を計算しようとすると例外がスローされるため、このイベントでは不十分です。これらのGridViewのViewStateを無効にすることは解決策のように思えますが、ユーザーがコマンドをクリックするたびにリロードするデータが大量にあります。データを手動でViewStateに保存することも解決策のようですが、GridViewにこのカスタムデータをPostBackで取得させる簡単な方法はないようです。

ASP.NETでやろうとしていることを実際に達成する方法はありますか?各GridViewの下部に合計行を配置するのは簡単な要件のようです。

助けてくれてありがとう。

4

3 に答える 3

0

gridView.OnPreRenderイベントの代わりにイベントを使用して動的行を作成しようとするとどうなりますかgridView.RowDataBound。このようにして、動的行の結果を計算するために必要なデータが利用可能になりますが、htmlはまだWebブラウザーに送信されていません。問題を修正するためのより多くの洞察を提供できるように、さらにコードを投稿してください。

于 2011-12-15T21:13:41.743 に答える
0

推奨されているように、RowDataBoundイベントではなくPreRenderイベントに合計行を作成するコードを配置してみました。これは、使用されていたGridViewのすべてのコマンドを壊したことを除いて、機能しているように見えました。GridViewを手動で変更すると、自動動作が中断されるようです。

protected void gvWorkerHours_PreRender(object sender, EventArgs e)
{
    double total = 0;
    int numColumns = gvWorkerHours.Columns.Count;
    int hoursIndex = 4; //5th column, 0-based
    int rowIndex = gvWorkerHours.Rows.Count + 1;

    foreach (GridViewRow row in gvWorkerHours.Rows)
    {
        if (row.RowType == DataControlRowType.DataRow)
        {
            Label label = (Label)row.FindControl("lblHours");
            total += Convert.ToDouble(label.Text);
        }
    }

    CreateTotalRow((Table)gvWorkerHours.Rows[0].Parent, rowIndex, total, hoursIndex, numColumns);
}
于 2011-12-16T16:09:59.770 に答える
0

OK、私がこれを解決することになった方法は、JQueryを使用することでした。他の誰かが同様の問題に直面している場合は、DOMの準備ができたとき、およびポストバックの最後に合計を計算する必要があることに注意してください。ポストバックの状況を処理するには、ScriptManager.RegisterStartupScript()を使用してクライアントでJavascriptを呼び出すだけです。

繰り返しになりますが、私の状況では4つのGridViewがありましたが、そのうちの1つのJQueryコードを表示します。

$(document).ready(function () {
    setTotals();
});

function setTotals() {

    var totalHours = getBillableHoursTotal();
    if (isNaN(totalHours)) totalHours = '...editing';
    $('#spanBillableHoursTotal').html(totalHours);

    //... etc.
}

function getBillableHoursTotal() {
    var total = 0.0;
    var rows = $('table[id*="_gvWorkerHours"] tr.RegularRows');
    $(rows).each(function () {
        total = total + parseFloat($(this).children('td').children('span[id*="lblHours"]').html()); 
    });
    return total;
}

そして、背後にあるコードのC#の場合:

protected void Page_Load(object sender, EventArgs e)
{
    // ... preceeding Page Load code

    if (IsPostBack)
    {
        ScriptManager.RegisterStartupScript(this, this.GetType(), "?", "setTotals()", true);
    }
}
于 2012-01-04T21:41:17.507 に答える