Динамически созданные строки исчезают из Gridview при обновлении / удалении - PullRequest
2 голосов
/ 16 декабря 2011

Ситуация: У меня есть несколько Gridview на одной странице, и у каждого Gridview есть динамически созданная строка для отображения итогов в нижней части. В каждом случае строка итогов создается для события RowDataBound. Стратегия, которую я использую, похожа на стратегию, предоставленную Майком Дуганом в его блоге .

Ниже приведен код для одного из GridView, но все остальные делают что-то очень похожее.

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, который не содержит итогов.

Неудачные попытки решения: Я не могу просто вызвать DataBind для каждого из GridView во время PostBack, потому что это предотвратит обновление / удаление. Хотя событие RowCreated будет происходить для GridView во время PostBack, этого события недостаточно, потому что у GridView не будет привязки к данным, и я получу исключение, когда я попытаюсь вычислить итог. Отключение ViewState для этих GridViews кажется решением, однако будет много данных для перезагрузки каждый раз, когда пользователь нажимает на команду. Сохранение моих данных вручную в ViewState также кажется решением, но не представляется простым способом заставить GridView извлекать эти пользовательские данные из PostBack.

Есть ли способ на самом деле добиться того, что я пытаюсь сделать с ASP.NET? Это кажется простым требованием иметь итоговую строку внизу каждого GridView.

Заранее спасибо за любую помощь.

Ответы [ 3 ]

0 голосов
/ 16 декабря 2011

В соответствии с рекомендацией я попытался поместить код для создания строки итогов в событии PreRender, а не в событии RowDataBound. Казалось, что это работает, за исключением того, что он нарушил все команды для 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);
}
0 голосов
/ 05 января 2012

ОК, я решил это с помощью JQuery.Если кто-то еще сталкивается с подобной проблемой, помните, что итоговые значения должны быть рассчитаны, когда DOM готов, а также в конце любой обратной передачи.Чтобы справиться с ситуацией обратной передачи, вы можете просто вызвать Javascript на клиенте, используя ScriptManager.RegisterStartupScript ().

Опять же, у меня было четыре GridView в моем случае, но я просто покажу код 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);
    }
}
0 голосов
/ 16 декабря 2011

Что делать, если вы попытаетесь создать динамическую строку, используя событие gridView.OnPreRender вместо события gridView.RowDataBound.Таким образом, ваши данные, необходимые для расчета результатов ряда динамиков, доступны, но HTML еще не отправлен в веб-браузер.Пожалуйста, опубликуйте еще немного кода, чтобы мы могли лучше разобраться с вашей проблемой.

...