Сортировка данных в элементе управления DataList или Repeater (C#)
В этом руководстве мы рассмотрим, как включить поддержку сортировки в DataList и Repeater, а также как создать DataList или Repeater, данные которого можно сортировать на страницы.
Введение
В предыдущем руководстве мы рассмотрели, как добавить поддержку разбиения по страницам в DataList. Мы создали новый метод в ProductsBLL
классе (GetProductsAsPagedDataSource
), который вернул PagedDataSource
объект . При привязке к DataList или Repeater в dataList или Repeater отображается только запрошенная страница данных. Этот метод аналогичен тому, который используется внутри элементов управления GridView, DetailsView и FormView для предоставления встроенных функций разбиения по страницам по умолчанию.
Помимо поддержки разбиения по страницам, GridView также включает встроенную поддержку сортировки. Ни DataList, ни Repeater не предоставляют встроенные функции сортировки; Однако функции сортировки можно добавить с помощью немного кода. В этом руководстве мы рассмотрим, как включить поддержку сортировки в DataList и Repeater, а также как создать DataList или Repeater, данные которого можно сортировать на страницы.
Обзор сортировки
Как было показано в руководстве по разбиению на страницы и сортировке данных отчета , элемент управления GridView обеспечивает встроенную поддержку сортировки. Каждое поле GridView может иметь связанный SortExpression
объект , который указывает поле данных, по которому сортируются данные. Если свойству GridView AllowSorting
присвоено значение true
, каждое поле GridView со значением SortExpression
свойства имеет заголовок, отображаемый как LinkButton. Когда пользователь щелкает заголовок определенного поля GridView, происходит обратная передача и данные сортируются в соответствии с щелкнутым полем SortExpression
.
Элемент управления GridView также имеет SortExpression
свойство , в котором хранится SortExpression
значение поля GridView, по которому отсортированы данные. Кроме того, свойство указывает, SortDirection
следует ли отсортировать данные по возрастанию или убыванию (если пользователь дважды последовательно щелкает ссылку на заголовок определенного поля GridView, порядок сортировки переключается).
Когда GridView привязан к элементу управления источником данных, он передает свойства SortExpression
и SortDirection
элементу управления источником данных. Элемент управления источником данных извлекает данные, а затем сортирует их в соответствии с предоставленными SortExpression
свойствами и SortDirection
. После сортировки данных элемент управления источником данных возвращает их в GridView.
Чтобы реплицировать эту функцию с помощью элементов управления DataList или Repeater, необходимо:
- Создание интерфейса сортировки
- Запоминание поля данных для сортировки и сортировки в порядке возрастания или убывания
- Указание ObjectDataSource сортировать данные по определенному полю данных
Мы рассмотрим эти три задачи на шагах 3 и 4. После этого мы рассмотрим, как включить поддержку разбиения по страницам и сортировки в DataList или Repeater.
Шаг 2. Отображение продуктов в ретрансляторе
Прежде чем мы рассмотрим реализацию любой из функций, связанных с сортировкой, давайте начнем с перечисления продуктов в элементе управления Repeater. Начните с открытия страницы Sorting.aspx
в папке PagingSortingDataListRepeater
. Добавьте элемент управления Repeater на веб-страницу, задав для его ID
свойства значение SortableProducts
. В смарт-теге Repeater создайте объект ObjectDataSource с именем ProductsDataSource
и настройте его для получения данных из ProductsBLL
метода класса .GetProducts()
Выберите параметр (Нет) в раскрывающихся списках на вкладках ВСТАВКА, ОБНОВЛЕНИЕ и УДАЛЕНИЕ.
Рис. 1. Создание objectDataSource и настройка для него использования GetProductsAsPagedDataSource()
метода (щелкните для просмотра полноразмерного изображения)
Рис. 2. Задайте для Drop-Down Списки на вкладках UPDATE, INSERT и DELETE значение (Нет) (Щелкните для просмотра полноразмерного изображения)
В отличие от DataList, Visual Studio не создает ItemTemplate
автоматически для элемента управления Repeater после привязки его к источнику данных. Кроме того, мы должны добавить это ItemTemplate
декларативно, так как смарт-тег элемента управления Repeater не имеет параметра Изменить шаблоны, который находится в dataList. Давайте воспользуемся тем же ItemTemplate
, что и в предыдущем руководстве, в котором отображались название продукта, поставщик и категория.
После добавления ItemTemplate
декларативная разметка Repeater и ObjectDataSource должна выглядеть примерно так:
<asp:Repeater ID="SortableProducts" DataSourceID="ProductsDataSource"
EnableViewState="False" runat="server">
<ItemTemplate>
<h4><asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Eval("ProductName") %>'></asp:Label></h4>
Category:
<asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Eval("CategoryName") %>'></asp:Label><br />
Supplier:
<asp:Label ID="SupplierNameLabel" runat="server"
Text='<%# Eval("SupplierName") %>'></asp:Label><br />
<br />
<br />
</ItemTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
SelectMethod="GetProducts">
</asp:ObjectDataSource>
На рисунке 3 показана эта страница при просмотре в браузере.
Рис. 3. Отображается имя, поставщик и категория каждого продукта (щелкните, чтобы просмотреть полноразмерное изображение)
Шаг 3. Указание ObjectDataSource сортировать данные
Чтобы отсортировать данные, отображаемые в repeater, необходимо сообщить ObjectDataSource о выражении сортировки, по которому следует отсортировать данные. Прежде чем ObjectDataSource извлекает свои данные, он сначала запускает своеSelecting
событие, которое дает возможность указать выражение сортировки. Обработчику Selecting
событий передается объект типа ObjectDataSourceSelectingEventArgs
, который имеет свойство с именем Arguments
типа DataSourceSelectArguments
. Класс DataSourceSelectArguments
предназначен для передачи запросов, связанных с данными, от потребителя данных в элемент управления источником данных и включает SortExpression
свойство .
Чтобы передать сведения о сортировке со страницы ASP.NET в ObjectDataSource, создайте обработчик Selecting
события и используйте следующий код:
protected void ProductsDataSource_Selecting
(object sender, ObjectDataSourceSelectingEventArgs e)
{
e.Arguments.SortExpression = sortExpression;
}
Значению sortExpression должно быть присвоено имя поля данных для сортировки данных (например, ProductName). Свойство, связанное с направлением сортировки, отсутствует, поэтому если вы хотите отсортировать данные в порядке убывания, добавьте строку DESC к значению sortExpression (например, ProductName DESC ).
Попробуйте несколько разных жестко заданных значений для sortExpression и протестируйте результаты в браузере. Как показано на рисунке 4, при использовании ProductName DESC в качестве sortExpression продукты сортируются по имени в обратном алфавитном порядке.
Рис. 4. Продукты сортируются по имени в обратном алфавитном порядке (щелкните для просмотра полноразмерного изображения)
Шаг 4. Создание интерфейса сортировки и запоминание выражения и направления сортировки
Включение поддержки сортировки в GridView преобразует текст заголовка каждого поля сортировки в LinkButton, который при щелчке сортирует данные соответствующим образом. Такой интерфейс сортировки имеет смысл для GridView, где его данные аккуратно размещены в столбцах. Однако для элементов управления DataList и Repeater требуется другой интерфейс сортировки. Общий интерфейс сортировки для списка данных (в отличие от сетки данных) — это раскрывающийся список, содержащий поля, по которым можно отсортировать данные. Давайте реализуем такой интерфейс для этого руководства.
Добавьте веб-элемент управления DropDownList над SortableProducts
Repeater и задайте для его ID
свойства значение SortBy
. В окно свойств щелкните многоточие в свойстве Items
, чтобы открыть Редактор Коллекция ListItem. Добавьте ListItem
для сортировки данных по полям ProductName
, CategoryName
и SupplierName
. Также добавьте , ListItem
чтобы отсортировать продукты по их имени в обратном алфавитном порядке.
Свойствам ListItem
Text
можно присвоить любое значение (например, Имя ), но Value
для свойств должно быть задано имя поля данных (например, ProductName). Чтобы отсортировать результаты в порядке убывания, добавьте строку DESC к имени поля данных, например ProductName DESC.
Рис. 5. ListItem
Добавление для каждого поля сортируемых данных
Наконец, добавьте элемент управления Button Web справа от DropDownList. Задайте для свойства ID
значение , RefreshRepeater
а для свойства Text
— значение Refresh .
После создания ListItem
и добавления кнопки Обновить декларативный синтаксис DropDownList и Button должен выглядеть примерно так:
<asp:DropDownList ID="SortBy" runat="server">
<asp:ListItem Value="ProductName">Name</asp:ListItem>
<asp:ListItem Value="ProductName DESC">Name (Reverse Order)
</asp:ListItem>
<asp:ListItem Value="CategoryName">Category</asp:ListItem>
<asp:ListItem Value="SupplierName">Supplier</asp:ListItem>
</asp:DropDownList>
<asp:Button runat="server" ID="RefreshRepeater" Text="Refresh" />
После завершения сортировки DropDownList необходимо обновить обработчик событий ObjectDataSource Selecting
таким образом, чтобы он использовал выбранное SortBy``ListItem
свойство s Value
вместо жестко запрограммированного выражения сортировки.
protected void ProductsDataSource_Selecting
(object sender, ObjectDataSourceSelectingEventArgs e)
{
// Have the ObjectDataSource sort the results by the selected
// sort expression
e.Arguments.SortExpression = SortBy.SelectedValue;
}
На этом этапе при первом посещении страницы продукты будут изначально отсортированы по полю ProductName
данных, так как оно выбрано SortBy
ListItem
по умолчанию (см. рис. 6). Выбор другого параметра сортировки, например Категория и нажатие кнопки Обновить, приведет к обратной отправке и повторной сортировке данных по имени категории, как показано на рисунке 7.
Рис. 6. Продукты изначально отсортированы по имени (щелкните, чтобы просмотреть полноразмерное изображение)
Рис. 7. Продукты теперь сортируются по категориям (щелкните, чтобы просмотреть полноразмерное изображение)
Примечание
Нажатие кнопки Обновить приводит к автоматической сортировке данных, так как состояние представления Repeater было отключено, что приводит к повторной привязке repeater к источнику данных при каждой обратной отправке. Если вы оставили состояние представления Repeater включенным, изменение раскрывающегося списка сортировки не повлияет на порядок сортировки. Чтобы устранить эту проблему, создайте обработчик событий для события кнопки Click
обновления и повторно привязывайте repeater к источнику данных (путем вызова метода Repeater s DataBind()
).
Запоминание выражения и направления сортировки
При создании сортируемых данных DataList или Repeater на странице, где могут происходить обратные передачи, не связанные с сортировкой, крайне важно, чтобы выражение сортировки и направление сортировки запоминались между обратными передачами. Например, представьте, что мы обновили Repeater в этом руководстве, чтобы включить кнопку Удалить для каждого продукта. Когда пользователь нажимает кнопку Удалить, мы запускаем код, чтобы удалить выбранный продукт, а затем повторно привязать данные к repeater. Если сведения о сортировке не сохраняются во время обратной передачи, данные, отображаемые на экране, будут отменить изменения в исходном порядке сортировки.
В этом руководстве DropDownList неявно сохраняет выражение сортировки и направление в своем состоянии представления. Если бы мы использовали другой интерфейс сортировки с, скажем, LinkButtons, который предоставлял различные параметры сортировки, мы должны были бы запомнить порядок сортировки между обратными передачами. Это можно сделать, сохранив параметры сортировки в состоянии представления страницы, включив параметр сортировки в строке запроса или используя другой метод сохранения состояния.
В следующих примерах в этом руководстве рассматривается сохранение сведений о сортировке в состоянии просмотра страницы.
Шаг 5. Добавление поддержки сортировки в список данных, использующий разбиение по умолчанию
В предыдущем руководстве мы рассмотрели, как реализовать разбиение по страницам по умолчанию с помощью DataList. Давайте расширим этот предыдущий пример, чтобы включить возможность сортировки постраничных данных. Начните с открытия SortingWithDefaultPaging.aspx
страниц и Paging.aspx
в папке PagingSortingDataListRepeater
. Paging.aspx
На странице нажмите кнопку Источник, чтобы просмотреть декларативную разметку страницы. Скопируйте выделенный текст (см. рис. 8) и вставьте его в декларативную разметку SortingWithDefaultPaging.aspx
между <asp:Content>
тегами.
Рис. 8. Репликация декларативной разметки в <asp:Content>
тегах от Paging.aspx
к SortingWithDefaultPaging.aspx
(щелкните для просмотра полноразмерного изображения)
После копирования декларативной разметки скопируйте методы и свойства класса кода программной части страницы в Paging.aspx
класс кода программной части для SortingWithDefaultPaging.aspx
. Затем просмотрите страницу SortingWithDefaultPaging.aspx
в браузере. Он должен иметь те же функции и внешний вид, что Paging.aspx
и .
Улучшение ProductsBLL для включения метода разбиения по страницам и сортировки по умолчанию
В предыдущем руководстве мы создали GetProductsAsPagedDataSource(pageIndex, pageSize)
метод в ProductsBLL
классе , который вернул PagedDataSource
объект . Этот PagedDataSource
объект был заполнен всеми продуктами (с помощью метода BLL GetProducts()
), но при привязке к DataList отображались только те записи, которые соответствуют указанным входным параметрам pageIndex и pageSize .
Ранее в этом руководстве мы добавили поддержку сортировки, указав выражение сортировки из обработчика Selecting
событий ObjectDataSource. Это хорошо работает, когда ObjectDataSource возвращает объект, который можно отсортировать, например ProductsDataTable
, возвращенный методом GetProducts()
. Однако объект, возвращаемый методом GetProductsAsPagedDataSource
, PagedDataSource
не поддерживает сортировку внутреннего источника данных. Вместо этого необходимо отсортировать результаты, возвращаемые методом GetProducts()
, прежде чем поместить их в PagedDataSource
.
Для этого создайте новый метод в ProductsBLL
классе GetProductsSortedAsPagedDataSource(sortExpression, pageIndex, pageSize)
. Чтобы отсортировать ProductsDataTable
объект , возвращаемый методом GetProducts()
, укажите Sort
свойство по умолчанию DataTableView
:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public PagedDataSource GetProductsSortedAsPagedDataSource
(string sortExpression, int pageIndex, int pageSize)
{
// Get ALL of the products
Northwind.ProductsDataTable products = GetProducts();
// Sort the products
products.DefaultView.Sort = sortExpression;
// Limit the results through a PagedDataSource
PagedDataSource pagedData = new PagedDataSource();
pagedData.DataSource = products.DefaultView;
pagedData.AllowPaging = true;
pagedData.CurrentPageIndex = pageIndex;
pagedData.PageSize = pageSize;
return pagedData;
}
Метод GetProductsSortedAsPagedDataSource
лишь незначительно отличается от метода, созданного GetProductsAsPagedDataSource
в предыдущем руководстве. В частности, GetProductsSortedAsPagedDataSource
принимает дополнительный входной параметр sortExpression
и присваивает это значение свойству Sort
ProductDataTable
объекта s DefaultView
. Через несколько строк кода объекту PagedDataSource
DataSource назначается ProductDataTable
s DefaultView
.
Вызов метода GetProductsSortedAsPagedDataSource и указание значения для входного параметра SortExpression
GetProductsSortedAsPagedDataSource
После завершения метода следующим шагом является предоставление значения для этого параметра. Объект ObjectDataSource в в SortingWithDefaultPaging.aspx
настоящее время настроен для вызова GetProductsAsPagedDataSource
метода и передает два входных параметра через два QueryStringParameters
параметра , которые указаны в SelectParameters
коллекции . Эти два QueryStringParameters
указывают, что источник для GetProductsAsPagedDataSource
параметров pageIndex и pageSize метода поступают из полей pageIndex
строки запроса и pageSize
.
Обновите свойство ObjectDataSource таким SelectMethod
образом, чтобы оно вызовет новый GetProductsSortedAsPagedDataSource
метод . Затем добавьте новый QueryStringParameter
, чтобы доступ к входному параметру sortExpression был получен из поля sortExpression
querystring . Задайте для QueryStringParameter
s DefaultValue
значение ProductName .
После этих изменений декларативная разметка ObjectDataSource должна выглядеть следующим образом:
<asp:ObjectDataSource ID="ProductsDefaultPagingDataSource"
OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
SelectMethod="GetProductsSortedAsPagedDataSource"
OnSelected="ProductsDefaultPagingDataSource_Selected" runat="server">
<SelectParameters>
<asp:QueryStringParameter DefaultValue="ProductName"
Name="sortExpression" QueryStringField="sortExpression"
Type="String" />
<asp:QueryStringParameter DefaultValue="0" Name="pageIndex"
QueryStringField="pageIndex" Type="Int32" />
<asp:QueryStringParameter DefaultValue="4" Name="pageSize"
QueryStringField="pageSize" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
На этом этапе SortingWithDefaultPaging.aspx
страница будет сортировать результаты в алфавитном порядке по названию продукта (см. рис. 9). Это связано с тем, что по умолчанию значение ProductName передается в качестве GetProductsSortedAsPagedDataSource
параметра sortExpression метода.
Рис. 9. По умолчанию результаты сортируются по ProductName
(щелкните для просмотра полноразмерного изображения)
Если вы вручную добавите sortExpression
поле строки запроса, SortingWithDefaultPaging.aspx?sortExpression=CategoryName
например , результаты будут отсортированы по указанному sortExpression
. Однако этот sortExpression
параметр не включается в строку запроса при переходе на другую страницу данных. На самом деле, нажав кнопки Следующая или Последняя страница, мы вернемся к Paging.aspx
! Кроме того, в настоящее время отсутствует интерфейс сортировки. Единственный способ изменить порядок сортировки разостраничных данных — управлять строками запросов напрямую.
Создание интерфейса сортировки
Сначала необходимо обновить RedirectUser
метод для отправки пользователю SortingWithDefaultPaging.aspx
(вместо Paging.aspx
) и включения sortExpression
значения в строка запроса. Следует также добавить именованное SortExpression
свойство уровня страницы, доступное только для чтения. Это свойство, аналогично PageIndex
свойствам и PageSize
, созданным в предыдущем руководстве, возвращает значение sortExpression
поля querystring , если оно существует, и значение по умолчанию ( ProductName ) в противном случае.
В настоящее RedirectUser
время метод принимает только один входной параметр индекса отображаемой страницы. Однако в некоторых случаях может потребоваться перенаправить пользователя на определенную страницу данных с помощью выражения сортировки, отличного от указанного в строках запроса. Через некоторое время мы создадим интерфейс сортировки для этой страницы, который будет включать ряд элементов управления Button Web для сортировки данных по указанному столбцу. При нажатии одной из этих кнопок необходимо перенаправить пользователя, передав соответствующее значение выражения сортировки. Чтобы предоставить эту функцию, создайте две версии RedirectUser
метода . Первый должен принимать только отображаемый индекс страницы, а второй — индекс страницы и выражение сортировки.
private string SortExpression
{
get
{
if (!string.IsNullOrEmpty(Request.QueryString["sortExpression"]))
return Request.QueryString["sortExpression"];
else
return "ProductName";
}
}
private void RedirectUser(int sendUserToPageIndex)
{
// Use the SortExpression property to get the sort expression
// from the querystring
RedirectUser(sendUserToPageIndex, SortExpression);
}
private void RedirectUser(int sendUserToPageIndex, string sendUserSortingBy)
{
// Send the user to the requested page with the requested sort expression
Response.Redirect(string.Format(
"SortingWithDefaultPaging.aspx?pageIndex={0}&pageSize={1}&sortExpression={2}",
sendUserToPageIndex, PageSize, sendUserSortingBy));
}
В первом примере этого руководства мы создали интерфейс сортировки с помощью DropDownList. В этом примере мы будем использовать три элемента управления Button Web, расположенные над DataList, один для сортировки по ProductName
, один для CategoryName
и один для SupplierName
. Добавьте три элемента управления Button Web, задав их ID
свойства и Text
соответствующим образом:
<p>
<asp:Button runat="server" id="SortByProductName"
Text="Sort by Product Name" />
<asp:Button runat="server" id="SortByCategoryName"
Text="Sort by Category" />
<asp:Button runat="server" id="SortBySupplierName"
Text="Sort by Supplier" />
</p>
Затем создайте Click
обработчик событий для каждого из них. Обработчики событий должны вызывать RedirectUser
метод , возвращая пользователя на первую страницу с помощью соответствующего выражения сортировки.
protected void SortByProductName_Click(object sender, EventArgs e)
{
// Sort by ProductName
RedirectUser(0, "ProductName");
}
protected void SortByCategoryName_Click(object sender, EventArgs e)
{
// Sort by CategoryName
RedirectUser(0, "CategoryName");
}
protected void SortBySupplierName_Click(object sender, EventArgs e)
{
// Sort by SupplierName
RedirectUser(0, "SupplierName");
}
При первом посещении страницы данные сортируются по названию продукта в алфавитном порядке (см. рис. 9). Нажмите кнопку Далее, чтобы перейти на вторую страницу данных, а затем нажмите кнопку Сортировать по категориям. Мы вернемся к первой странице данных, отсортированных по имени категории (см. рис. 10). Аналогичным образом при нажатии кнопки Сортировать по поставщику данные сортируются по поставщику, начиная с первой страницы данных. Выбор сортировки запоминается по мере разыкания данных. На рисунке 11 показана страница после сортировки по категориям и последующего продвижения к тринадцатой странице данных.
Рис. 10. Продукты сортируются по категориям (щелкните для просмотра полноразмерного изображения)
Рис. 11. Выражение сортировки запоминается при разбиении по страницам данных (щелкните для просмотра полноразмерного изображения)
Шаг 6. Настраиваемое разбиение записей по страницам в ретрансляторе
Пример DataList, рассмотренный на шаге 5 страниц с использованием неэффективного метода разбиения по страницам по умолчанию. При разбиении по страницам достаточно больших объемов данных крайне важно использовать пользовательское разбиение по страницам. В руководствах По эффективному разбиению по страницам в больших объемах данных и Сортировке пользовательских постраничных данных мы рассмотрели различия между пользовательскими и пользовательскими разбиением по страницам и созданными методами в BLL для использования пользовательского разбиения по страницам и сортировки пользовательских постраничных данных. В частности, в этих двух предыдущих учебниках мы добавили в класс следующие три метода ProductsBLL
:
GetProductsPaged(startRowIndex, maximumRows)
возвращает определенное подмножество записей, начиная с startRowIndex и не превышающее maximumRows.GetProductsPagedAndSorted(sortExpression, startRowIndex, maximumRows)
возвращает определенное подмножество записей, отсортированных по указанному входному параметру sortExpression .TotalNumberOfProducts()
предоставляет общее количество записей вProducts
таблице базы данных.
Эти методы можно использовать для эффективного просмотра и сортировки данных с помощью элемента управления DataList или Repeater. Чтобы проиллюстрировать это, давайте начнем с создания элемента управления Repeater с поддержкой пользовательской разбиения по страницам. Затем мы добавим возможности сортировки.
Откройте страницу SortingWithCustomPaging.aspx
в папке PagingSortingDataListRepeater
и добавьте repeater на страницу, задав для его ID
свойства значение Products
. В смарт-теге Repeater создайте объект ObjectDataSource с именем ProductsDataSource
. Настройте его для выбора данных из ProductsBLL
метода класса .GetProductsPaged
Рис. 12. Настройка ObjectDataSource для использования ProductsBLL
метода Класса GetProductsPaged
(щелкните для просмотра полноразмерного изображения)
Установите для раскрывающихся списков на вкладках UPDATE, INSERT и DELETE значение (Нет), а затем нажмите кнопку Далее. Мастер настройки источника данных теперь запрашивает источники входных GetProductsPaged
параметров метода startRowIndex и maximumRows . Фактически эти входные параметры игнорируются. Вместо этого значения startRowIndex и maximumRows будут передаваться через Arguments
свойство в обработчике событий ObjectDataSource Selecting
, точно так же, как мы указали sortExpression в первой демонстрации этого учебника. Поэтому оставьте раскрывающийся список источника параметров в мастере в поле Нет.
Рис. 13. Оставьте для параметра Источники параметров значение Нет (щелкните для просмотра полноразмерного изображения)
Примечание
Не устанавливайте для свойства true
ObjectDataSource значение EnablePaging
. Это приведет к тому, что ObjectDataSource автоматически включает собственные параметры startRowIndex и maximumRows в существующий SelectMethod
список параметров . Свойство EnablePaging
полезно при привязке пользовательских страничных данных к элементу управления GridView, DetailsView или FormView, так как эти элементы управления ожидают определенного поведения от ObjectDataSource, доступного только в том случае, если EnablePaging
свойство имеет значение true
. Так как необходимо вручную добавить поддержку разбиения на страницы для DataList и Repeater, оставьте для этого свойства значение false
(по умолчанию), так как мы будем создавать необходимые функции непосредственно на странице ASP.NET.
Наконец, определите значения Repeater ItemTemplate
, чтобы отображались название продукта, категория и поставщик. После этих изменений декларативный синтаксис Repeater и ObjectDataSource должен выглядеть примерно так:
<asp:Repeater ID="Products" runat="server" DataSourceID="ProductsDataSource"
EnableViewState="False">
<ItemTemplate>
<h4><asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Eval("ProductName") %>'></asp:Label></h4>
Category:
<asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Eval("CategoryName") %>'></asp:Label><br />
Supplier:
<asp:Label ID="SupplierNameLabel" runat="server"
Text='<%# Eval("SupplierName") %>'></asp:Label><br />
<br />
<br />
</ItemTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsPaged" TypeName="ProductsBLL">
<SelectParameters>
<asp:Parameter Name="startRowIndex" Type="Int32" />
<asp:Parameter Name="maximumRows" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
Посетите страницу через браузер и обратите внимание, что записи не возвращаются. Это связано с тем, что нам еще предстоит указать значения параметров startRowIndex и maximumRows . Поэтому значения 0 передаются для обоих. Чтобы указать эти значения, создайте обработчик событий для события ObjectDataSource Selecting
и программно задайте для этих параметров жестко заданные значения 0 и 5 соответственно:
protected void ProductsDataSource_Selecting
(object sender, ObjectDataSourceSelectingEventArgs e)
{
e.InputParameters["startRowIndex"] = 0;
e.InputParameters["maximumRows"] = 5;
}
При этом изменении на странице при просмотре в браузере отображаются первые пять продуктов.
Рис. 14. Отображаются первые пять записей (щелкните для просмотра полноразмерного изображения)
Примечание
Продукты, перечисленные на рис. 14, отсортированы по названию продукта, так как GetProductsPaged
хранимая процедура, выполняющая эффективный пользовательский запрос разбиения по страницам, упорядочивает результаты по .ProductName
Чтобы позволить пользователю выполнять пошаговое выполнение страниц, необходимо отслеживать индекс начальной строки и максимальное количество строк и запоминать эти значения при обратной отправке. В примере разбиения по страницам по умолчанию мы использовали поля querystring для сохранения этих значений; Для этой демонстрации давайте сохраним эти сведения в состоянии просмотра страницы. Создайте следующие два свойства:
private int StartRowIndex
{
get
{
object o = ViewState["StartRowIndex"];
if (o == null)
return 0;
else
return (int)o;
}
set
{
ViewState["StartRowIndex"] = value;
}
}
private int MaximumRows
{
get
{
object o = ViewState["MaximumRows"];
if (o == null)
return 5;
else
return (int)o;
}
set
{
ViewState["MaximumRows"] = value;
}
}
Затем обновите код в обработчике событий Selecting, чтобы он использовал StartRowIndex
свойства и MaximumRows
вместо жестко заданных значений 0 и 5:
e.InputParameters["startRowIndex"] = StartRowIndex;
e.InputParameters["maximumRows"] = MaximumRows;
На данный момент на нашей странице по-прежнему отображаются только первые пять записей. Однако с помощью этих свойств мы готовы создать интерфейс подкачки.
Добавление интерфейса подкачки
Давайте используем тот же интерфейс подкачки First, Previous, Next, Last, который используется в примере разбиения на страницы по умолчанию, включая элемент управления Label Web, который показывает, какая страница с данными просматривается и сколько всего страниц существует. Добавьте четыре элемента управления Button Web и Label под элементом Repeater.
<p>
<asp:Button runat="server" ID="FirstPage" Text="<< First" />
<asp:Button runat="server" ID="PrevPage" Text="< Prev" />
<asp:Button runat="server" ID="NextPage" Text="Next >" />
<asp:Button runat="server" ID="LastPage" Text="Last >>" />
</p>
<p>
<asp:Label runat="server" ID="CurrentPageNumber"></asp:Label>
</p>
Затем создайте Click
обработчики событий для четырех кнопок. При нажатии одной из этих кнопок необходимо обновить StartRowIndex
и повторно привязать данные к ретранслятору. Код для кнопок First, Previous и Next достаточно прост, но для кнопки Последний как определить индекс начальной строки для последней страницы данных? Чтобы вычислить этот индекс, а также определить, должны ли быть включены кнопки Далее и Последний, необходимо знать, сколько записей в общей сложности выстраиваются. Это можно определить, вызвав ProductsBLL
метод класса .TotalNumberOfProducts()
Создадим доступное только для чтения свойство уровня страницы с именем TotalRowCount
, которое возвращает результаты TotalNumberOfProducts()
метода :
private int TotalRowCount
{
get
{
// Return the value from the TotalNumberOfProducts() method
ProductsBLL productsAPI = new ProductsBLL();
return productsAPI.TotalNumberOfProducts();
}
}
С помощью этого свойства теперь можно определить индекс начальной строки последней страницы. В частности, это целочисленный результат TotalRowCount
минус 1, деленный на MaximumRows
, умноженный на MaximumRows
. Теперь можно написать обработчики Click
событий для четырех кнопок интерфейса подкачки:
protected void FirstPage_Click(object sender, EventArgs e)
{
// Return to StartRowIndex of 0 and rebind data
StartRowIndex = 0;
Products.DataBind();
}
protected void PrevPage_Click(object sender, EventArgs e)
{
// Subtract MaximumRows from StartRowIndex and rebind data
StartRowIndex -= MaximumRows;
Products.DataBind();
}
protected void NextPage_Click(object sender, EventArgs e)
{
// Add MaximumRows to StartRowIndex and rebind data
StartRowIndex += MaximumRows;
Products.DataBind();
}
protected void LastPage_Click(object sender, EventArgs e)
{
// Set StartRowIndex = to last page's starting row index and rebind data
StartRowIndex = ((TotalRowCount - 1) / MaximumRows) * MaximumRows;
Products.DataBind();
}
Наконец, необходимо отключить кнопки Первый и Предыдущий в интерфейсе подкачки при просмотре первой страницы данных и кнопки Next и Last при просмотре последней страницы. Для этого добавьте следующий код в обработчик событий ObjectDataSource Selecting
:
// Disable the paging interface buttons, if needed
FirstPage.Enabled = StartRowIndex != 0;
PrevPage.Enabled = StartRowIndex != 0;
int LastPageStartRowIndex = ((TotalRowCount - 1) / MaximumRows) * MaximumRows;
NextPage.Enabled = StartRowIndex < LastPageStartRowIndex;
LastPage.Enabled = StartRowIndex < LastPageStartRowIndex;
После добавления этих Click
обработчиков событий и кода для включения или отключения элементов интерфейса подкачки на основе текущего индекса начальной строки проверьте страницу в браузере. Как показано на рисунке 15, при первом посещении страницы кнопки Первая и Предыдущая будут отключены. При нажатии кнопки Далее отображается вторая страница данных, а последняя — последняя страница (см. рисунки 16 и 17). При просмотре последней страницы данных отключаются кнопки Далее и Последняя.
Рис. 15. Кнопки "Назад" и "Последняя" отключены при просмотре первой страницы продуктов (щелкните для просмотра полноразмерного изображения)
Рис. 16. Отображается вторая страница продуктов (щелкните, чтобы просмотреть изображение в полном размере)
Рис. 17. Щелчок последняя отображает окончательную страницу данных (щелкните для просмотра полноразмерного изображения)
Шаг 7. Включение поддержки сортировки с помощью пользовательского страничного ретранслятора
Теперь, когда пользовательское разбиение по страницам реализовано, мы готовы включить поддержку сортировки. Метод ProductsBLL
класса s GetProductsPagedAndSorted
имеет те же входные параметры startRowIndex и maximumRows , что GetProductsPaged
и , но разрешает дополнительный входной параметр sortExpression . Чтобы использовать GetProductsPagedAndSorted
метод из SortingWithCustomPaging.aspx
, необходимо выполнить следующие действия:
- Измените свойство ObjectDataSource
SelectMethod
сGetProductsPaged
наGetProductsPagedAndSorted
. - Добавьте объект sortExpression
Parameter
в коллекцию ObjectDataSourceSelectParameters
. - Создайте частное свойство на уровне
SortExpression
страницы, которое сохраняет свое значение во время обратной передачи через состояние просмотра страницы. - Обновите обработчик событий ObjectDataSource
Selecting
, чтобы присвоить параметру sortExpression объекта ObjectDataSource значение свойства уровняSortExpression
страницы. - Создайте интерфейс сортировки.
Начните с обновления свойства ObjectDataSource SelectMethod
и добавления sortExpressionParameter
. Убедитесь, что свойству sortExpressionParameter
задано Type
значение String
. После выполнения этих первых двух задач декларативная разметка ObjectDataSource должна выглядеть следующим образом:
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
SelectMethod="GetProductsPagedAndSorted"
OnSelecting="ProductsDataSource_Selecting">
<SelectParameters>
<asp:Parameter Name="sortExpression" Type="String" />
<asp:Parameter Name="startRowIndex" Type="Int32" />
<asp:Parameter Name="maximumRows" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
Далее необходимо свойство уровня SortExpression
страницы, значение которого сериализуется для просмотра состояния. Если значение выражения сортировки не задано, используйте ProductName по умолчанию:
private string SortExpression
{
get
{
object o = ViewState["SortExpression"];
if (o == null)
return "ProductName";
else
return o.ToString();
}
set
{
ViewState["SortExpression"] = value;
}
}
Перед вызовом GetProductsPagedAndSorted
метода ObjectDataSource необходимо задать для sortExpressionParameter
значение SortExpression
свойства . В обработчике Selecting
событий добавьте следующую строку кода:
e.InputParameters["sortExpression"] = SortExpression;
Осталось реализовать интерфейс сортировки. Как и в предыдущем примере, интерфейс сортировки реализован с помощью трех веб-элементов управления Button, которые позволяют пользователю сортировать результаты по названию продукта, категории или поставщику.
<asp:Button runat="server" id="SortByProductName"
Text="Sort by Product Name" />
<asp:Button runat="server" id="SortByCategoryName"
Text="Sort by Category" />
<asp:Button runat="server" id="SortBySupplierName"
Text="Sort by Supplier" />
Создайте Click
обработчики событий для этих трех элементов управления Button. В обработчике событий сбросьте StartRowIndex
значение 0, задайте SortExpression
для соответствующего значения и повторно привязите данные к repeater:
protected void SortByProductName_Click(object sender, EventArgs e)
{
StartRowIndex = 0;
SortExpression = "ProductName";
Products.DataBind();
}
protected void SortByCategoryName_Click(object sender, EventArgs e)
{
StartRowIndex = 0;
SortExpression = "CategoryName";
Products.DataBind();
}
protected void SortBySupplierName_Click(object sender, EventArgs e)
{
StartRowIndex = 0;
SortExpression = "CompanyName";
Products.DataBind();
}
Это все, что есть к нему! Хотя для реализации пользовательского разбиения по страницам и сортировки было выполнено несколько шагов, эти действия были очень похожи на шаги, необходимые для разбиения по страницам по умолчанию. На рисунке 18 показаны продукты при просмотре последней страницы данных при сортировке по категориям.
Рис. 18. Отображается последняя страница данных, отсортированная по категориям (щелкните для просмотра полноразмерного изображения)
Примечание
В предыдущих примерах при сортировке по поставщику Имя поставщика использовалось в качестве выражения сортировки. Однако для реализации настраиваемого разбиения по страницам необходимо использовать CompanyName. Это связано с тем, что хранимая процедура, отвечающая за реализацию настраиваемого разбиения GetProductsPagedAndSorted
по страницам, передает выражение сортировки в ROW_NUMBER()
ключевое слово, ключевое слово ROW_NUMBER()
требует фактического имени столбца, а не псевдонима. Поэтому для выражения сортировки необходимо использовать CompanyName
(имя столбца в Suppliers
таблице), а не псевдоним, используемый SELECT
в запросе (SupplierName
).
Сводка
Ни DataList, ни Repeater не предлагают встроенной поддержки сортировки, но с помощью немного кода и пользовательского интерфейса сортировки такие функции можно добавить. При реализации сортировки, но не разбиения по страницам, выражение сортировки можно указать с помощью DataSourceSelectArguments
объекта, передаваемого в метод ObjectDataSource Select
. Это DataSourceSelectArguments
свойство объекта SortExpression
можно назначить в обработчике событий ObjectDataSource Selecting
.
Чтобы добавить возможности сортировки в DataList или Repeater, который уже обеспечивает поддержку разбиения по страницам, проще всего настроить уровень бизнес-логики, включив в него метод, который принимает выражение сортировки. Затем эти сведения можно передать через параметр в объекте ObjectDataSource SelectParameters
.
В этом руководстве мы завершаем изучение разбиения по страницам и сортировки с помощью элементов управления DataList и Repeater. В следующем и последнем руководстве рассматривается добавление веб-элементов управления Button в шаблоны DataList и Repeater, чтобы предоставить некоторые пользовательские функции для каждого элемента.
Счастливого программирования!
Об авторе
Скотт Митчелл( Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часах. Он может быть доступен в mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.
Особая благодарность
Эта серия учебников была рассмотрена многими полезными рецензентами. Ведущим рецензентом этого руководства был Дэвид Суру. Хотите просмотреть предстоящие статьи MSDN? Если да, опустите мне строку на mitchell@4GuysFromRolla.com.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по