Как получить общее количество строк и почему свойство DataSource объекта GridView является нулевым в обработчике событий DataBound? - PullRequest
0 голосов
/ 22 июля 2010

Я хотел получить общее количество строк в обработчике событий с привязкой к базе данных GridView, поэтому я попробовал следующее:

   protected void grid_DataBound(object sender, EventArgs e)
   {
       GridView grid = (GridView)sender;
       DataSet data = grid.DataSource as DataSet;
       if (data == null)
         return;
       int totalRows = data.Tables[0].Rows.Count;
   }

Проблема в том, что свойство grid.DataSource имеет значение null.Свойство DataSourceID не является нулевым, поэтому это означает, что я не могу получить доступ к объекту DataSource в обработчике событий DataBound, если не назначу свойство DataSource напрямую?

Редактировать

Вот код в моем классе GridHelper для добавления счетчика строк в BottomPagerRow.Я хотел бы избавиться от требования передать ObjectDataSource, но не могу, потому что мне нужно использовать событие Selected, чтобы получить общее количество строк.Отсюда причина вопроса.

Я также думаю, что это может быть лучше в пользовательском элементе управления, где я могу получить доступ к ViewState и / или создать дочерние элементы управления во время события Init (мне все еще не удается решить проблему с помощьюспособ отображения пейджера с дополнительной ячейкой), но тогда у меня все еще будет проблема с тем, как добраться до общего числа строк, когда сам DataSource, по-видимому, недоступен в каких-либо событиях GridView.

Редактировать 2 На самом деле не имеет отношения к конкретной проблеме, но я решил проблему с рендерингом пейджера, поэтому обновил опубликованный код.Я нашел трюк здесь: http://michaelmerrell.com/2010/01/dynamically-modifying-the-asp-net-gridview-paging-control/

#region Fields
private int totalRows = -1;
#endregion

#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="GridHelper"/> class.
/// Adds EventHandlers to the GridView to display results from the ObjectDataSource in the footer.
/// Marked as obsolete because AddResultsToFooter method provides a static access to the same functionality
/// An instance of GridHelper is required by the passed in GridView to store the totalRows value between the two event handlers
/// </summary>
/// <param name="grid">The grid.</param>
/// <param name="source">The ObjectDataSource linked to the GridView.</param>
[Obsolete("Use AddResultsToFooter instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public GridHelper(GridView grid, ObjectDataSource source)
{
    source.Selected += source_Selected;
    grid.PreRender += grid_PreRender;
}
#endregion

#region Event Handlers

private void grid_PreRender(object sender, EventArgs e)
{
    GridView grid = (GridView)sender;

    if (grid.HeaderRow != null)
        grid.HeaderRow.TableSection = TableRowSection.TableHeader;

    //Add a cell to the bottom pager row to display the total results
    if (grid.BottomPagerRow == null || !grid.BottomPagerRow.Visible)
        return;

    //Get the control used to render the pager
    //http://michaelmerrell.com/2010/01/dynamically-modifying-the-asp-net-gridview-paging-control/
    Table tblPager = grid.BottomPagerRow.Cells[0].Controls[0] as Table;
    if (tblPager == null)
        return;

    if (totalRows < 0)
    {
        //The DataSource has not been refreshed so get totalRows from round trip to client
        addResultsToPagerTable(tblPager, grid.Attributes["results"]);
        return;
    }

    int firstRow = grid.PageIndex * grid.PageSize + 1;
    int lastRow = firstRow + grid.Rows.Count - 1;

    string results;
    if (totalRows <= grid.PageSize)
        results = string.Format("<span class='grid-pager'>{0} Results</span>", totalRows);
    else
        results = string.Format("Results <b>{0}</b> to <b>{1}</b> of <b>{2}</b>", firstRow, lastRow, totalRows);

    addResultsToPagerTable(tblPager, results);

    //Need to store the information somewhere that is persisted via ViewState, and we don't have access to ViewState here
    grid.Attributes.Add("results", results);
}

/// <summary>
/// Handles the Selected event of the source control. Gets the total rows, since it is not possible to access them from the GridView.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Web.UI.WebControls.ObjectDataSourceStatusEventArgs"/> instance containing the event data.</param>
private void source_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
    if (e.ReturnValue is DataView)
        totalRows = ((DataView)e.ReturnValue).Count;
    else if (e.ReturnValue is EntitySet)
        totalRows = ((EntitySet)e.ReturnValue).Count;
}
#endregion

#region Private Methods
private static void addResultsToPagerTable(Table tblPager, string results)
{
    //http://michaelmerrell.com/2010/01/dynamically-modifying-the-asp-net-gridview-paging-control/

    //Get a handle to the original pager row
    TableRow pagesTableRow = tblPager.Rows[0];

    //Add enough cells to make the pager row bigger than the label we're adding
    while (pagesTableRow.Cells.Count < 10)
        pagesTableRow.Cells.Add(new TableCell { BorderStyle = BorderStyle.None });

    //Add a new cell in a new row to the table
    TableRow newTableRow = new TableRow();
    newTableRow.Cells.AddAt(0, new TableCell
    {
        Text = results,
        BorderStyle = BorderStyle.None,
        ColumnSpan = pagesTableRow.Cells.Count
    });

    tblPager.Rows.AddAt(0, newTableRow);

}
#endregion

#region Public Methods
/// <summary>
/// Adds EventHandlers to the GridView to display results from the ObjectDataSource in the footer.
/// </summary>
/// <param name="grid">The GridView.</param>
/// <param name="source">The ObjectDataSource linked to the GridView.</param>
public static void AddResultsToFooter(GridView grid, ObjectDataSource source)
{
    if (grid == null)
        throw new ArgumentNullException("grid", "grid is null.");
    if (source == null)
        throw new ArgumentNullException("source", "source is null.");

    new GridHelper(grid, source);
}
#endregion

1 Ответ

0 голосов
/ 22 июля 2010

В VS вы можете отладить это, поместив точку останова и наведя курсор на DataSource, но я думаю, это потому, что GridView извлекает DataView из DataTable, к которому он привязывается, поэтому он не смотрит на DataSet ...

Отладка выяснит.

HTH.

...