如何获取总行数以及为什么GridView DataSource属性在DataBound事件处理程序中为null?

时间:2010-07-22 10:46:47

标签: asp.net data-binding gridview datasource

我想在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属性不为null,这是否意味着我无法访问DataBound事件处理程序中的DataSource对象,除非我直接分配DataSource属性?

修改

以下是GridHelper类中用于将rowcount添加到BottomPagerRow的代码。我想摆脱传递ObjectDataSource的要求,但不能,因为我需要使用Selected事件来获取总行数。因此问题的原因。

我还认为在自定义控件中可能会更好,我可以访问ViewState,和/或在Init事件期间创建子控件(我仍然有问题要通过寻呼机使用额外单元格呈现的方式来解决),但是当数据源本身似乎在任何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 :(得分:0)

在VS中,你可以通过在那里放置一个断点来调试它并将鼠标放在DataSource上,但我认为这是因为GridView从它绑定的DataTable中提取了一个DataView,所以它没有查看DataSet ...

调试会发现。

HTH。