Пейджинг в GridView, как известно, производится с помощью параметров, сохраняемых во ViewState, таким образом при каждом обновлении делается POST-запрос.
Это создает некоторые трудности. В частности, в ссылке не содержится информация о текущей странице, т.е. ее не имеет смысла кому-то передавать. Кроме того при обновлении браузер будет спрашивать передавать ли данные заново на сервер, что раздражает пользователей.
Естественное решение проблемы - использование GET-параметров. В них можно передавать номер страницы и количество элементов на странице.
Создаем класс-наследник GridView
public class ContentList : GridView
{
}
Сделаем 2 публичных свойства чтоб манипулировать GET-параметрами (чтоб избежать возможных конфликтов)
public string PageParamName
{
get { return pageParamName; }
set
{
if ( string.Equals(pageSizeParamName, value,
StringComparison.CurrentCultureIgnoreCase) )
throw new ArgumentException("parameter names are equal");
pageParamName = value;
}
}
public string PageSizeParamName
{
get { return pageSizeParamName; }
set
{
if (string.Equals(pageParamName, value,
StringComparison.CurrentCultureIgnoreCase))
throw new ArgumentException("parameter names are equal");
pageSizeParamName = value;
}
}
private string pageParamName = "page"; //default values
private string pageSizeParamName = "pagesize";
Здесь учитываем возможную ошибку, если пользователь попробует установить одинаковые значения параметров.
Теперь перекрываем метод OnInit, в котором устанавливаем значение размера страницы и номера страницы. Здесь нужно учесть что в C# нумерация массивов начинается с нуля а нам желательно начинать нумерацию с единицы.
В итоге получим
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (! string.IsNullOrEmpty(Context.Request.QueryString[PageSizeParamName]))
{
PageSize = Int32.Parse(Context.Request.QueryString[PageSizeParamName]);
}
if (!string.IsNullOrEmpty(Context.Request.QueryString[PageParamName]))
PageIndex = Int32.Parse(Context.Request.QueryString[PageParamName]) - 1;
}
Таким образом данные берутся из GET-параметров. При желании можно проверять, является ли параметр числом и, если не является, игнорировать его. Сделать это несложно.
Остается последний шаг - перекрыть метод InitializePager и там создать ссылки с нужными GET-параметрами. Подробно описывать его не буду, приведу лишь код функции создающей GET-URL с учетом параметров пейджинга.
private string createPagedPath(int page, int pagesize)
{
string param = string.Empty;
foreach ( string s in Context.Request.QueryString.AllKeys )
{
if (string.Equals(s, PageParamName,
StringComparison.CurrentCultureIgnoreCase) )
continue;
if (string.Equals(s, PageSizeParamName,
StringComparison.CurrentCultureIgnoreCase))
continue;
param += string.Format("&{0}={1}", s, Context.Request.QueryString[s]);
}
return string.Format("{0}?{1}={2}&{3}={4}{5}",
Context.Request.Path, PageParamName, page, PageSizeParamName, pagesize, param);
}
Как видно из кода, проверяем все GET-параметры и копируем из них только те, которые не относятся к нашим параметрам с именами PageParamName и PageSizeParamName. Затем берем Path запроса, добавляем к нему параметры пейджинга и исходные параметры, если таковые имеются в запросе.
P.S. Стоит обратить внимание на изменение свойств PageParamName и PageSizeParamName, желательно прописывать их прямо на странице .aspx и не изменять в коде, поскольку это может привести к труднолокализуемым ошибкам (либо вообще не менять, а оставить значения по умолчанию).