Достаточно
простой вопрос сортировки данных в DataGrid, неплохо освещенный в тех же
квикстартах, оказывается все таки вызывает вопросы его реализации у
начинающих ASP.NET программистов. Что в итоге и послужило поводом
написания этой статьи. Что же может предложить элемент DataGrid для
помощи в сортировке данных? В элемент DataGrid встроена возможность
сортировки данных. Но именно возможность, т.е. реально DataGrid не может
сам сортировать встроенные в него данные. Да и как он мог бы это делать,
если все, что ему нужно для вывода данных, это объект, реализующий
интерфейсы IEnumerable. Фактически все, что делает установка свойства
AllowSorting элемента DataGrid в true, это вывод заголовков столбцов в
виде кнопок, при нажатии на которые вызывается событие SortCommand. А
как его обрабатывать да как при этом сортировать данные в DataGrid – это
уже забота программиста.
Рассмотрим простейший пример сортировки данных в DataGrid. На веб
форме расположен элемент DataGrid со свойствами AutoGenerateColumn и
AllowSorting установленными в true.
<asp:DataGrid id="DataGrid1" runat="server" AllowSorting="True"
AutoGenerateColumns=”True”>
</asp:DataGrid>
Для связывания данных из источника данных используется
вспомогательный метод bindData(), который заполняет DataSet данными и
затем связывает полученный DataSet и DataGrid:
private void bindData()
{
SqlConnection myConn = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlDataAdapter myData = new SqlDataAdapter("select * from authors",
myConn);
DataSet ds = new DataSet();
myData.Fill(ds);
DataGrid1.DataSource = ds.Tables[0].DefaultView;
DataGrid1.DataBind();
}
Вызывается этот метод в обработчике события Load страницы:
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
bindData();
}
Подготовительная работа произведена, теперь пора и реализовать
сортировку. Для этого необходимо обработать событие SortCommand элемента
DataGrid И внести небольшие изменения в метод bindData().
Метод-обработчик события Sortcommand принимает параметр типа
DataGridSortCommandEventArgs, в свойстве SortExpression которого
содержится строка – выражение сортировки. И все, что необходимо сделать
– использовать это выражение для сортировки данных, полученных из
источника данных.
В примере передаваемое значение SortExpression сохраняется в
ViewState для дальнейшего использования и после этого вызывается метод
bindData() для связывания данных:
private void DataGrid1_SortCommand(object source,
System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
ViewState["sort"] = e.SortExpression;
bindData();
}
Для того, чтобы использовать значение сортировки для реальной
сортировки данных в методе bindData() после вызова myData.Fill(ds)
необходимо вставить следующие строки:
if(ViewState["sort"] != null)
ds.Tables[0].DefaultView.Sort = (string) ViewState["sort"];
Все. Работа по сортировке данных в DataGrid выполнена.
Использование автоматической генерации столбцов не раскрывает всей
мощности возможностей сортировки в DataGrid. Для того, чтобы несколько
расширить наши знания в этом рассмотрим следующий пример, в котором
элемент DataGrid будет иметь описанные столбцы различных типов.
<asp:DataGrid id="DataGrid1" runat="server" AllowSorting="True"
AutoGenerateColumns="False">
<Columns>
<asp:TemplateColumn SortExpression="au_lname, au_fname"
HeaderText="Last Name">
<ItemTemplate>
<asp:Label runat="server" Text='<%# DataBinder.Eval(Container,
"DataItem.au_lname") %>'> </asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn SortExpression="au_lname, au_fname"
HeaderText="First Name">
<ItemTemplate>
<asp:Label runat="server" Text='<%# DataBinder.Eval(Container,
"DataItem.au_fname") %>'> </asp:Label>
</ItemTemplate>
</asp:TemplateColumn>
<asp:HyperLinkColumn DataTextField="phone" SortExpression="phone"
HeaderText="Phone" NavigateUrl="#"></asp:HyperLinkColumn>
<asp:BoundColumn DataField="address"
HeaderText="Address"></asp:BoundColumn>
<asp:BoundColumn DataField="city" SortExpression="state, city
desc" HeaderText="City"></asp:BoundColumn>
<asp:ButtonColumn Text="X" ButtonType="PushButton"
SortExpression="contract desc"
HeaderText="Fiction"></asp:ButtonColumn>
</Columns>
</asp:DataGrid>
Классы столбцов элемента DataGrid являются наследниками абстрактного
класса DataGridColumn, который в свою очередь имеет свойство
SortExpression, определяющее выражение сортировки для столбца.
Соответственно возможность сортировки можно использовать для столбца
любого типа – необходимо только установить соответствующие значения для
свойства SortExpression. Выражением сортировки может быть любое
правильное с точки зрения языка SQL выражение для ORDER BY. В
приведенном выше примере используются столбцы всех четырех типов для
элемента DataGrid (в том числе и столбец типа ButtonColumn, для него,
как ни странно, тоже можно устанавливать выражение сортировки). При этом
изменилось только описание столбцов в DataGrid, весь код остался для
этого примера неизменным.
Свойство SortExpression можно изменять в режиме выполнения.
Соответственно данную возможность можно использовать для создания
двунаправленной сортировки в DataGrid (эх, сколько приходилось мучаться
для реализации подобной функциональности в asp :)). Все, что для этого
нужно – небольшая дополнительная обработка свойств SortExpression в
обработчике события SortCommand. В этом примере будет использоваться
DataGrid со следующим описанием столбцов:
<asp:BoundColumn DataField="au_id" SortExpression="au_id"
HeaderText="ID"></asp:BoundColumn>
<asp:BoundColumn DataField="au_lname" SortExpression="au_lname"
HeaderText="Last Name"></asp:BoundColumn>
<asp:BoundColumn DataField="au_fname" SortExpression="au_fname"
HeaderText="First Name"></asp:BoundColumn>
<asp:BoundColumn DataField="phone" SortExpression="phone"
HeaderText="Phone"></asp:BoundColumn>
<asp:BoundColumn DataField="address" SortExpression="address"
HeaderText="Address"></asp:BoundColumn>
<asp:BoundColumn DataField="city" SortExpression="city"
HeaderText="City"></asp:BoundColumn>
<asp:BoundColumn DataField="state" SortExpression="state"
HeaderText="State"></asp:BoundColumn>
<asp:BoundColumn DataField="zip" SortExpression="zip"
HeaderText="Zip"></asp:BoundColumn>
<asp:BoundColumn DataField="contract" SortExpression="contract"
HeaderText="Contract"></asp:BoundColumn>
В обработчике события SortCommand после сохранения выражения
сортировки необходимо пройтись по всем столбцам DataGrid, найти текущий
столбец (столбец, у которого свойство SortExpression равно выражению,
переданному в обработчик) и поменять направление сортировки для этого
столбца (добавить или удалить строку " desc". Также в коде в заголовок
столбца добавляются символы, указывающие текущее направление сортировки.
Весь код обработчика SortCommand представлен ниже:
private void DataGrid1_SortCommand(object source,
System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
ViewState["sort"] = e.SortExpression;
foreach(DataGridColumn column in DataGrid1.Columns)
{
column.HeaderText = column.HeaderText.Replace(" v", "");
column.HeaderText = column.HeaderText.Replace(" ^", "");
if(column.SortExpression == e.SortExpression)
{
if(e.SortExpression.IndexOf(" desc") != -1)
{
column.SortExpression = column.SortExpression.Replace(" desc",
"");
column.HeaderText += " ^";
}
else
{
column.SortExpression += " desc";
column.HeaderText += " v";
}
}
}
bindData();
}
Ничего сложного, не так ли? :)
Возможность сортировки, имеющаяся в элементе управления DataGrid,
представляет собой простое, но вместе с тем и мощное средство сортировки
данных. С помощью данной функциональности ваши данные будут иметь еще
более удобный вид для пользователей. И все это при минимальных затратах. |