Я хотел получить общее количество строк в обработчике событий с привязкой к базе данных 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