Потребители данных отображают данные, полученные из классов-источников данных. Они предоставляют много полезных функций. Например, элемент управления может не только показывать данные, но и сортировать, выбирать, редактировать их. Если этой функциональности недостаточно, ее можно расширить, написав собственные обработчики событий.
Элементы, которые могут быть связаны с элементами-источниками данных, многообразны. Во-первых, это уже хорошо знакомые DropDownList, ListBox, CheckBoxList, RadioButtonList, BulletedList. Однако для всех них необходимо в качестве источника данных указывать не DataSource, а DataSourceID. Все эти элементы отображать могут только одно поле, указанное в DataTextField, с возможностью задания второго в качестве индексного в свойстве DataValueField:
<asp:SqlDataSource ID="SqlDataSource3" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [CategoryName], [CategoryID] FROM
[Categories]">
</asp:SqlDataSource>
<asp:CheckBoxList ID="CheckBoxList1" runat="server"
AppendDataBoundItems="True" DataSourceID="SqlDataSource3"
DataTextField="CategoryName" DataValueField="CategoryID">
</asp:CheckBoxList>
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="SqlDataSource3" DataTextField="CategoryName">
</asp:DropDownList>
<asp:BulletedList ID="BulletedList1" runat="server"
BulletStyle="UpperRoman" DataSourceID="SqlDataSource3"
DataTextField="CategoryName" DataValueField="CategoryName">
</asp:BulletedList>
AppendDataBoundItems — это новое свойство. Оно позволяет комбинировать данные из элемента-источника с данными, статически объявленными на странице.
Очень интересны элементы управления
Можно получать данные, связанные с элементом управления, в его декларации на странице. Это делается с помощью разновидности автоматически отображают данные, но и в них для создания нужных эффектов используются столбцы-шаблоны.
Для привязки к данным используются разделители <%# %>. В жизненном цикле каждого элемента управления наступает событие DataBinding, во время которого и вычисляются все выражения, заключенные в этот тег.
Если в функции Page_Load мы писали
ContinentDropDownList.DataSource = ContinentArrayList;
то на странице это можно сделать с помощью
<asp: DropDownList id=" ContinentDropDownList " datasource='<%# ContinentArrayList %>' runat="server">
В ASP .NET 1.x данные читались в объекты DataSet или DataReader, после чего вызывался DataBind. В ASP .NET 2.0, если же установлено свойство DataSourceID, то событие DataBinding вызывается автоматически.
В сгенерированном ASP .NET классе страницы в обработчике этого события для ContinentDropDownList будет выполняться код
datasource = ContinentArrayList;
При этом в ItemDataBound, для — в RowDataBound. Эти события вызываются столько раз, сколько записей в источнике данных. Каждый раз, когда ASP .NET встречает эти разделители в шаблоне, внутри элемента Item ( RepeaterItem, DataListItem, DataGridItem ) создается элемент типа DataBoundLiteralControl, внутри которого записывается выражение внутри разделителей. В обработчике события DataBinding этого элемента определена переменная Container, которая указывает на этот самый Item, то есть секцию элемента. Классы Item хранят данные в свойстве DataItem. Поэтому в шаблонах доступ к данным
происходит с помощью синтаксиса Container.DataItem.
Возможный синтаксис для доступа к полю:
<%# ((System.Data.DataRowView)Container.DataItem)["City"]%>
в случае, когда данные получены из DataReader,
<%# ((System.Data.IDataRecord)Container.DataItem)["City"]%>
в случае, когда данные получены из DataSet,
или
<%# DataBinder.Eval(Container.DataItem, "City") %>
Этот способ заменяет оба предыдущие, так как DataBinder с помощью статической функции Eval сам определяет тип источника и соответственно его обрабатывает. Метод Eval перегружен, его второй вариант принимает аргумент для форматирования данных:
DataBinder.Eval(Container.DataItem, "Age","{0:2d}")
В ASP .NET 2.0 синтаксис можно упростить и написать
<%# Eval("City")%>
В новых элементах управления , , , где поддерживается двунаправленный вывод данных, можно вызывать метод Bind. Его используют в шаблонах редактируемых строк:
<asp:TextBox ID="EditFirstNameTextBox" Runat="Server" Text='<%#
Bind("FirstName") %>' />
Шаблон — это множество тегов HTML и серверных элементов управления, которые задают образец для отображения составной части сложного элемента управления. DataSourceID и DataMember, собственных свойств у него нет. Поэтому у программиста есть полный контроль над тем, как выводится
Как минимум, должен быть описан шаблон ItemTemplate. HeaderTemplate отображается один раз в начале отрисовки FooterTemplate в конце, SeparatorTemplate между отображением каждого пункта, AlternatingItemTemplate — для четных пунктов. Все серверные элементы управления в шаблон помещаются целиком, поэтому, чтобы получить таблицу, используют простые теги HTML. Например, открывающий тег < table > помещают в HeaderTemplate, а закрывающий — в FooterTemplate.
В этом примере составляются характеристики сотрудников:
<asp:Repeater ID="Repeater1" runat="server"
DataSourceID="SqlDataSource1" >
<HeaderTemplate><asp:Label runat="server" ID="Header1"
BackColor="DarkOrange" ForeColor="ActiveCaptionText"
Font-Bold="true" Font-Underline="true" Font-Size="Large">
We present our valued Employees!</asp:Label>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Panel ID="Panel1" runat="server"
BackColor="LightPink">
<asp:Image ID="Photo" runat="server" ImageUrl=<%#
Eval("PhotoPath")%>/>
<%# Eval( "TitleOfCourtesy") %>
<%# DataBinder.Eval(Container.DataItem,
"FirstName") %>
<%# DataBinder.Eval(Container.DataItem,
"LastName") %>
was born in <%# Eval("BirthDate",
"{0:dd.MM.yyyy}") %>.<p>
<%# Eval("TitleOfCourtesy").ToString() == "Mr."
|| Eval("TitleOfCourtesy").ToString() == "Dr." ? "He" : "She"%>
lives in beautiful city
<%#
((System.Data.DataRowView)Container.DataItem)["City"]%>,
<%# Eval( "Region") %> in
<%# DataBinder.Eval(Container.DataItem,
"Country") %>.</p>
<p>We appreciate <%#
Eval("TitleOfCourtesy").ToString() == "Mr." ||
Eval("TitleOfCourtesy").ToString() == "Dr." ? "his" : "her"%>
work as <%# Eval("Title") %>.</p>
<p><%# DataBinder.Eval(Container.DataItem,
"Notes") %></p>
</asp:Panel>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table></FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$
ConnectionStrings:NorthwindConnectionString1 %>"
SelectCommand="SELECT * FROM [Employees]"
></asp:SqlDataSource>
В браузере это выглядит так:
(рис 8.1) Обратите внимание на условные выражения:
<%# Eval("TitleOfCourtesy").ToString() == "Mr." ||
Eval("TitleOfCourtesy").ToString() == "Dr." ? "He" : "She"%>
Благодаря этому в предложении о мужчине употребляются местоимения мужского, а в предложении о женщине — женского рода. В таблице нет поля для пола, но его можно вычислить по полю TitleOfCourtesy, который у мужчин бывает или "Mr. ", или "Dr.".
Если нужно изменить внешний вид всего шаблона, проще всего поместить все его содержимое или весь элемент в Panel и определить в нем стили.
С помощью элемента управления
SelectedItemTemplate и EditItemTemplate. Кроме того, у него есть верхний и нижний колонтитулы со стилями HeaderStyle и FooterStyle.
Во-вторых, можно изменить способы отображения. По умолчанию RepeatLayout, установленное как Flow, убирает табличные теги из выходного потока. RepeatDirection меняет направление вывода с вертикального на горизонтальное. RepeatColumns задает количество столбцов таблицы, по умолчанию равное 1.
BaseDataList, который наследует WebControl. Поэтому у него, в отличие от CellPadding и CellSpacing.
У SmartTag — Edit Templates. После того, как редактирование окончено, не забудьте выйти из режима — End Template Editing.
Можно спроектировать этот элемент так, чтобы в обычном состоянии отображалась краткая информация, а в выбранном состоянии — более подробная.
Посмотрим пример из Quickstarts:
<asp:DataList id="DataList1" runat="server"
BorderColor="black" BorderWidth="1"
GridLines="Both" CellPadding="3"
Font-Names="Verdana" Font-Size="8pt"
Width="150px"
HeaderStyle-BackColor="#aaaadd"
AlternatingItemStyle-BackColor="Gainsboro"
SelectedItemStyle-BackColor="yellow"
OnItemCommand="DataList_ItemCommand"
>
<HeaderTemplate>
Items
</HeaderTemplate>
<ItemTemplate>
<asp:LinkButton id="button1" runat="server" Text="Show
details" CommandName="select" />
<%# DataBinder.Eval(Container.DataItem, "StringValue") %>
</ItemTemplate>
<SelectedItemTemplate>
Item:
<%# DataBinder.Eval(Container.DataItem, "StringValue") %>
<br>
Order Date:
<%# DataBinder.Eval(Container.DataItem, "DateTimeValue",
"{0:d}") %>
<br>
Quantity:
<%# DataBinder.Eval(Container.DataItem, "IntegerValue",
"{0:N1}") %>
<br>
</SelectedItemTemplate>
</asp:DataList>
А обработчик выбора записи такой:
void DataList_ItemCommand(object Sender,
DataListCommandEventArgs e) {
string cmd = ((LinkButton)e.CommandSource).CommandName;
if (cmd == "select")
DataList1.SelectedIndex = e.Item.ItemIndex;
BindList();
}
Чтобы реализовать редактирование, тоже нужно обрабатывать событие. Поэтому в ASP .NET 2.0 .
Свойство DataKeyField имеется и у
Это очень популярный элемент управления, и неудивительно. Особенно много он применялся в ASP .NET 1.x, но теперь его функции перекрываются . Тем не менее его стоит изучить, так как многие его свойства схожи со свойствами . DataSource и получить готовую таблицу на странице. Формат таблицы можно менять независимо от данных. Данные можно сортировать, выбирать, редактировать.
В простейшем варианте нужно установить только свойство DataSource, его значением может быть объект, реализующий интерфейс IEnumerable, например SqlDataReader, DataTable. При этом на странице выводится таблица, где строкам соответствуют записи, а столбцам — поля.
Создадим простой XML-файл с табличной информацией. Это будут данные о лауреатах Нобелевской премии по литературе и физике. Назовите ее nobel.xml:
<?xml version="1.0" encoding="utf-8" ?>
<nobel>
<phisics>
<phisisist>
<name>Basov</name>
<nationality>Russia(USSR)</nationality>
</phisisist>
<phisisist>
<name>Rentgen</name>
<nationality>Germany</nationality>
</phisisist>
<phisisist>
<name>Bor</name>
<nationality> Denmark</nationality>
</phisisist>
</phisics>
<literature>
<writer>
<name>Boris Pasternak</name>
<nationality>Russia</nationality>
<work>"Doctor Zhivago"</work>
<winningdate>1958</winningdate>
</writer>
<writer>
<name>Romain Rollan</name>
<nationality>France</nationality>
<work>"Jean-Cristophe"</work>
<winningdate>1915</winningdate>
</writer>
<writer>
<name>Gabriel Garsia Marquez </name>
<nationality>Columbia</nationality>
<work>"100 years of solitude"</work>
<winningdate>1982</winningdate>
</writer>
<writer>
<name>George Bernard Shaw</name>
<nationality>Great Britain</nationality>
<work></work>
<winningdate>1925</winningdate>
</writer>
</literature>
</nobel>
Тут построена трехуровневая иерархия. Узел < nobel > должен быть прочитан в DataSet. Внутри него есть 2 узла: один с данными о физике, второй — о литературе. Каждый из них будет помещен в DataTable. Узлы < name >, < nationality >, < work >, < winningdate > вложены в < literature > и повторяются для каждого писателя. Они будут считаны в DataColumns таблицы.
Почему узел < work ></ work > у Шоу пустой? Как считал сам Шоу, Нобелевскую премию 1925 года ему дали за то, что в этом году он ничего не написал.
Через методы ReadXml, WriteXml DataSet может читать данные из XML-файла.
Форма, которая читает информацию из этого файла:
<%@ Page Language="C#" Debug="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Xml" %>
<script runat="server">
void bindData()
{
String xmlFilename = Server.MapPath("") + "\\nobel.xml";
DataSet newDataSet = new DataSet();
newDataSet.ReadXml(xmlFilename);
DataTable newDataTable = newDataSet.Tables[1];
DataGrid1.DataSource = newDataTable;
DataGrid1.DataBind();
}
void Page_Load()
{
if (!IsPostBack)
bindData();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Data Grid Control example</title>
</head>
<body>
<form runat="server">
<asp:DataGrid id="DataGrid1" runat="server"
CellSpacing="10"
BorderWidth ="0" BackColor="AliceBlue" EditItemIndex =
"1">
<HeaderStyle BackColor="#AAAADD" Font-Size="20pt" Font-
Bold = "True">
</HeaderStyle>
<AlternatingItemStyle BackColor="#80FF80" />
</asp:DataGrid>
</form>
</body>
</html>
Поменяв индекс в DataTable newDataTable = newDataSet.Tables[1] на 3, получим страницу с другими данными — лауреатов премии по литературе.
По умолчанию элемент AutoGenerateColumns. С элементом управления DataTime и Decimal. Если в поле неподдерживаемый тип, столбец не будет создан. Если ни одного подходящего поля нет, будет выброшено исключение.
Header ), который по умолчанию виден, и нижний колонтитул ( Footer ). При автоматической генерации в заголовке каждого столбца выводится название поля.
Если AutoGenerateColumns установить в False, можно самим управлять колонками и определять более сложный его вид. В таком случае надо включать в BoundColumn. Некоторые свойства BoundColumn:
DataField определяет поле источника данных;DataFormatString задает формат вывода данных;ReadOnly делает поле недоступным для редактирования.В заголовке и нижнем колонтитуле можно установить любой текст, а в заголовке — еще и картинку ( HeaderText, FooterText, HeaderImageUrl ).
В ячейку генерируемой LiteralControl, текст которого берется из источника данных и форматируется в соответствии с DataFormatString. Для редактируемой строки в ячейке появляется TextBox.
Есть и другие типы колонок.
ButtonColumn отображает в каждой строке командную кнопку. Если связать ее с полем, на кнопках будут надписи из этого поля.
EditCommandColumn показывает кнопки для редактирования.
HyperLinkColumn превращает текст в гиперссылки. Например, поле PhotoPath можно показать в такой колонке, и тогда щелчок по ссылке покажет фотографию.
TemplateColumn позволяет определить шаблон отображения, как в
При желании можно программно скрывать и показывать колонки, например:
DataGrid1.Columns[1].Visible = !(DataGrid1.Columns[1].Visible);
У элемента TableItemStyle. Это AlternatingItemStyle, EditItemStyle, FooterStyle, HeaderStyle, ItemStyle, PagerStyle и SelectedItemStyle. Стили образуют иерархию, то есть атрибут "Стиль", который выше в иерархии, наследует те, которые ниже, если он его не переопределяет. Порядок в ней такой:
EditItemStyle — стиль редактируемой строки;SelectedItemStyle — стиль выбранной строки;AlternatingItemStyle — стиль каждой второй строки;ItemStyle — стиль строки по умолчанию;ControlStyle — все свойства, которые влияют на внешний вид элемента, например BackColor. PagerStyle, FooterStyle, HeaderStyle тоже его наследуют.PagerStyle — стиль пейджера, то есть номеров страниц-гиперссылок, при выборе которых таблица перелистывается. Чтобы AllowPaging и количество записей должно быть больше PageSize. Все эти свойства удобно устанавливать с помощью PropertyBuilder.В Visual Studio 2005 есть возможность автоформатирования, как и у
Новый вариант, без автоматической генерации колонок и со стилями:
<asp:DataGrid ID="DataGrid2" runat="server" BackColor="#FFE0C0"
ShowFooter="True" AutoGenerateColumns="False" PageSize="3">
<AlternatingItemStyle BackColor="#C0FFC0" />
<ItemStyle BackColor="#FFFFC0" />
<EditItemStyle BackColor="#C0C000" Font-Size="XX-Large" />
<Columns>
<asp:BoundColumn DataField="name" FooterText="Name"
HeaderText="Фамилия"></asp:BoundColumn>
<asp:BoundColumn DataField="nationality"
FooterText="Country" HeaderText="Страна"></asp:BoundColumn>
<asp:BoundColumn DataField="winningdate" FooterText="Year
won" HeaderText="Год"></asp:BoundColumn>
<asp:BoundColumn DataField="work" FooterText="Work"
HeaderText="Произведение"></asp:BoundColumn>
</Columns>
<FooterStyle Font-Bold="True" Font-Italic="False" Font-
Overline="False" Font-Strikeout="False" Font-Underline="False" />
<HeaderStyle Font-Bold="True" Font-Italic="False" Font-
Overline="False" Font-Strikeout="False" Font-Underline="False" />
</asp:DataGrid>
Добавим в эту форму возможность сортировки по столбцам. AllowSorting. Но это только потенциальная возможность сортировки, так как сам элемент сортировать не может, это должен обеспечить программист. При AllowSorting = True в заголовке выводятся гиперссылки, при нажатии на которые вызывается событие SortCommand. Так как нет автогенерации, в описание BoundColumn нужно вставить SortExpression:
<asp:BoundColumn DataField="name" FooterText="Name"
HeaderText="Фамилия" SortExpression="name">
</asp:BoundColumn>
Метод-обработчик события SortCommand принимает параметр типа DataGridSortCommandEventArgs, в свойстве SortExpression которого содержится строка — выражение сортировки SortExpression. Необходимо использовать это выражение для сортировки данных, полученных из источника данных
protected void DataGrid2_SortCommand(object source, DataGridSortCommandEventArgs e)
{
ViewState["sort"] = e.SortExpression;
bindData();
}
где bindData() вынесен в отдельную функцию и вызывается также из Page_Load:
private void bindData()
{
String xmlFilename = Server.MapPath("") + "\\nobel.xml";
DataSet newDataSet = new DataSet();
newDataSet.ReadXml(xmlFilename);
if (ViewState["sort"] != null)
newDataSet.Tables[3].DefaultView.Sort =
(string)ViewState["sort"];
DataTable newDataTable = newDataSet.Tables[3];
DataGrid2.DataSource = newDataTable;
DataGrid2.DataBind();
}
void Page_Load()
{
if (!IsPostBack)
bindData();
}
| Фамилия | Страна | Год | Произведение |
|---|---|---|---|
| Romain Rollan | France | 1915 | "Jean-Cristophe" |
| George Bernard Shaw | Great Britain | 1925 | |
| Boris Pasternak | Russia | 1958 | "Doctor Zhivago" |
| Gabriel Garsia Marquez | Columbia | 1982 | "100 years of solitude" |
| Name | Country | Year won | Work |
такую технику можно считать устаревшей, так как позволяет делать все это с помощью одного только декларативного связывания.
Покажем возможность удаления, обновления и редактирования данных в .
Создайте на сервере SQL в базе DemoBase таблицу Users с тремя полями:
| Column Name | Data Type | Allow Nulls |
|---|---|---|
| UID | int | |
| Name | varchar(50) | |
| Comments | varchar(250) | + |
| IsRegistered | bit | + |
Поле UID — автоинкрементное. Поэтому операция INSERT не будет требовать задания его значения. Конечно, это первичный ключ. В таблице свойств найдите IdentitySpecification, раскройте его и выберите ( IsIdentity ).
Будем работать с таблицей с помощью трех процедур.
CREATE PROCEDURE dbo.SelectUsers ( @Col INT = 0 ) AS IF @Col = 0 SELECT * FROM Users ELSE IF @Col = 1 SELECT * FROM Users ORDER BY NAME RETURN
Процедура EditUser будет использоваться для вставки записей, если @UID=0, и для обновления в противном случае:
CREATE PROCEDURE dbo.EditUser ( @UID int = 0, @Name varchar(50), @Comments varchar(250), @Registered bit ) AS IF @UID = 0 INSERT INTO Users(Name, Comments, IsRegistered) VALUES(@Name, @Comments, @Registered) ELSE UPDATE Users SET Name = @Name, Comments = @Comments, IsRegistered = @Registered WHERE UID = @UID RETURN
Процедура для удаления записей.
CREATE PROCEDURE dbo.DeleteUser ( @UID int ) AS DELETE FROM Users WHERE UID = @UID RETURN
На форме будет находиться, кроме NameTextBox, а также CommentTextBox и кнопка Add. Для наших тайных целей добавим элемент управления типа HiddenField. Эти цели — хранить id текущего элемента и передавать его .
Добавим на форму следующий источник данных:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$
ConnectionStrings:DemoBaseConnectionString %>"
SelectCommand="dbo.SelectUsers"
SelectCommandType="StoredProcedure"
DeleteCommand="dbo.DeleteUser"
DeleteCommandType="StoredProcedure"
UpdateCommand="dbo.EditUser"
UpdateCommandType="StoredProcedure"
InsertCommand="dbo.EditUser"
InsertCommandType="StoredProcedure"
OldValuesParameterFormatString="">
<InsertParameters>
<asp:Parameter Direction="ReturnValue" Name="RETURN_VALUE"
Type="Int32" />
<asp:Parameter Name="UID" Type="Int32" DefaultValue="0" />
<asp:ControlParameter Name="Name" Type="String"
ControlID="NameTextBox"/>
<asp:ControlParameter Name="Comments" Type="String"
ControlID="CommentTextBox" PropertyName="Text"/>
<asp:ControlParameter Name="Registered" Type="Boolean"
ControlID="Registered" PropertyName="Checked"/>
</InsertParameters>
<UpdateParameters>
<asp:Parameter Direction="ReturnValue"
Name="RETURN_VALUE"
Type="Int32" />
<asp:ControlParameter Name="UID" Type="Int32"
ControlID="HiddenField1" />
<asp:ControlParameter Name="Name" Type="String"
ControlID="NameTextBox"/>
<asp:ControlParameter Name="Comments" Type="String"
ControlID="CommentTextBox"/>
<asp:ControlParameter Name="Registered" Type="Boolean"
ControlID="Registered" PropertyName="Checked"/>
</UpdateParameters>
<DeleteParameters>
<asp:ControlParameter ControlID="HiddenField1"
PropertyName="Value" Name="UID" Type="Int32" />
</DeleteParameters>
</asp:SqlDataSource>
Обратите внимание на то, что в InsertParameters значение параметра UID по умолчанию 0 и он не связан с элементом управления. В остальных случаях он связан с HiddenField1. Значение в это поле будет передаваться в обработчиках.
На этот раз TemplateColumn. Этот тип столбца CheckBox:
<asp:DataGrid id="UsersDataGrid" runat="server"
AutoGenerateColumns="False" DataKeyField="UID"
OnDeleteCommand="UsersDataGrid_DeleteCommand"
OnUpdateCommand="UsersDataGrid_UpdateCommand"
OnEditCommand="UsersDataGrid_EditCommand"
DataSourceID="SqlDataSource1"
AllowSorting="True" Caption="Users" CaptionAlign="Top">
<Columns>
<asp:TemplateColumn HeaderText= "Имя">
<ItemTemplate>
<asp:Label id="Label1" runat="server"
Text='<%#DataBinder.Eval(Container, "DataItem.Name")%>'>
</asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox id=NameTextBox runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.Name") %>'>
</asp:TextBox>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Комментарии">
<ItemTemplate>
<asp:Label id="Label2" runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.Comments")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox id= CommentTextBox runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.Comments")%>'>
</asp:TextBox>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText= "Зарегистрирован">
<ItemTemplate>
<asp:CheckBox runat="server" ID="Registered"
Checked='<%# (bool) DataBinder.Eval(Container,
"DataItem.isRegistered") %>'
Enabled="False"></asp:CheckBox >
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBox runat="server" ID="Registered" Checked='<%#
(bool) DataBinder.Eval(Container, "DataItem.isRegistered")
%>'></asp:CheckBox>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn>
<ItemTemplate>
<asp:LinkButton id="LinkButton1" runat="server"
CommandName="edit">редактировать</asp:LinkButton> ::
<asp:LinkButton id="LinkButton2" runat="server"
CommandName="delete">удалить</asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton id="LinkButton3" runat="server"
CommandName="update">принять</asp:LinkButton> ::
<asp:LinkButton id="LinkButton4" runat="server"
CommandName="cancel">отменить</asp:LinkButton>
</EditItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
И остальные элементы:
<asp:TextBox ID="NameTextBox" runat="server" ></asp:TextBox> <asp:TextBox ID="CommentTextBox" runat="server"></asp:TextBox> <asp:CheckBox ID="Registered" runat="server" /><br /><br /> <asp:Button ID="Button1" runat="server" Text="Add" OnClick="Add_Click" /> <asp:HiddenField ID="HiddenField1" runat="server" />
уже знает параметры команды Delete, это единственный параметр, и связан он был с HiddenField1. Нужно записать значение ключа id в это поле:
protected void UsersDataGrid_DeleteCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
HiddenField1.Value =
UsersDataGrid.DataKeys[e.Item.ItemIndex].ToString();
// Удаление
SqlDataSource1.Delete();
// Обновление данных после удаления
UsersDataGrid.DataBind();
}
Добавление записи происходит еще проще, так как параметры процедуры Insert находятся в тех текстовых полях, которые заполняются для вставки:
protected void Add_Click(object sender, EventArgs e)
{
SqlDataSource1.Insert();
UsersDataGrid.DataBind();
}
В момент начала редактирования текстовые поля прячутся, так как значения из полей редактирования внутри таблицы будут копироваться туда, и нужно скрыть это от пользователя. Кроме того, эти элементы управления во время редактирования не нужны:
protected void UsersDataGrid_EditCommand(object source,
DataGridCommandEventArgs e)
{
UsersDataGrid.EditItemIndex = e.Item.ItemIndex;
NameTextBox.Visible = false;
CommentTextBox.Visible = false;
Registered.Visible = false;
UsersDataGrid.DataBind();
}
Редактирование — сложнее. В шаблоне столбцов элемента , потому что в момент генерации страницы их там просто нет. Например, для того чтобы установить в режим редактирования строку EditItemIndex элемента управления
В событии UpdateCommand в аргументе e находим текущую строку. Обновляемые данные находятся в TextBox -ах в ячейках 0 и 1. Чтобы выйти из режима редактирования, свойству EditItemIndex нужно присвоить значение - 1:
protected void UsersDataGrid_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
TableCell cell=e.Item.Cells[0];
TextBox cnt = (TextBox)cell.FindControl("NameTextBox");
NameTextBox.Text = cnt.Text;
cell = e.Item.Cells[1];
cnt = (TextBox)cell.FindControl("CommentTextBox");
CommentTextBox.Text = cnt.Text;
HiddenField1.Value =
UsersDataGrid.DataKeys[e.Item.ItemIndex].ToString();
cell = e.Item.Cells[2];
CheckBox check = (CheckBox)cell.FindControl("Registered");
Registered.Checked = check.Checked;
SqlDataSource1.Update();
UsersDataGrid.EditItemIndex = -1;
UsersDataGrid.DataBind();
NameTextBox.Text = "";
CommentTextBox.Text = "";
NameTextBox.Visible = true;
CommentTextBox.Visible = true;
Registered.Visible = true;
}
После обновления вновь читаем данные и делаем видимыми поля редактирования.
Отказ от редактирования без сохранения изменений обрабатывается в событии CancelCommand:
protected void UsersDataGrid_CancelCommand(object source,
DataGridCommandEventArgs e)
{
UsersDataGrid.EditItemIndex = -1;
NameTextBox.Visible = true;
CommentTextBox.Visible = true;
UsersDataGrid.DataBind();
}
Мы рассмотрели 3 элемента управления, существовавшие с ASP .NET 1.0.
Объектная модель упрощает связывание с данными, но ее реальная мощь проявляется при использовании новых элементов управления , , , которые мы рассмотрим в следующей лекции.
Потребители данных отображают данные, полученные из классов-источников данных. Они предоставляют много полезных функций. Например, элемент управления может не только показывать данные, но и сортировать, выбирать, редактировать их. Если этой функциональности недостаточно, ее можно расширить, написав собственные обработчики событий.
Элементы, которые могут быть связаны с элементами-источниками данных, многообразны. Во-первых, это уже хорошо знакомые DropDownList, ListBox, CheckBoxList, RadioButtonList, BulletedList. Однако для всех них необходимо в качестве источника данных указывать не DataSource, а DataSourceID. Все эти элементы отображать могут только одно поле, указанное в DataTextField, с возможностью задания второго в качестве индексного в свойстве DataValueField:
<asp:SqlDataSource ID="SqlDataSource3" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [CategoryName], [CategoryID] FROM
[Categories]">
</asp:SqlDataSource>
<asp:CheckBoxList ID="CheckBoxList1" runat="server"
AppendDataBoundItems="True" DataSourceID="SqlDataSource3"
DataTextField="CategoryName" DataValueField="CategoryID">
</asp:CheckBoxList>
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="SqlDataSource3" DataTextField="CategoryName">
</asp:DropDownList>
<asp:BulletedList ID="BulletedList1" runat="server"
BulletStyle="UpperRoman" DataSourceID="SqlDataSource3"
DataTextField="CategoryName" DataValueField="CategoryName">
</asp:BulletedList>
AppendDataBoundItems — это новое свойство. Оно позволяет комбинировать данные из элемента-источника с данными, статически объявленными на странице.
Очень интересны элементы управления
Можно получать данные, связанные с элементом управления, в его декларации на странице. Это делается с помощью разновидности автоматически отображают данные, но и в них для создания нужных эффектов используются столбцы-шаблоны.
Для привязки к данным используются разделители <%# %>. В жизненном цикле каждого элемента управления наступает событие DataBinding, во время которого и вычисляются все выражения, заключенные в этот тег.
Если в функции Page_Load мы писали
ContinentDropDownList.DataSource = ContinentArrayList;
то на странице это можно сделать с помощью
<asp: DropDownList id=" ContinentDropDownList " datasource='<%# ContinentArrayList %>' runat="server">
В ASP .NET 1.x данные читались в объекты DataSet или DataReader, после чего вызывался DataBind. В ASP .NET 2.0, если же установлено свойство DataSourceID, то событие DataBinding вызывается автоматически.
В сгенерированном ASP .NET классе страницы в обработчике этого события для ContinentDropDownList будет выполняться код
datasource = ContinentArrayList;
При этом в ItemDataBound, для — в RowDataBound. Эти события вызываются столько раз, сколько записей в источнике данных. Каждый раз, когда ASP .NET встречает эти разделители в шаблоне, внутри элемента Item ( RepeaterItem, DataListItem, DataGridItem ) создается элемент типа DataBoundLiteralControl, внутри которого записывается выражение внутри разделителей. В обработчике события DataBinding этого элемента определена переменная Container, которая указывает на этот самый Item, то есть секцию элемента. Классы Item хранят данные в свойстве DataItem. Поэтому в шаблонах доступ к данным
происходит с помощью синтаксиса Container.DataItem.
Возможный синтаксис для доступа к полю:
<%# ((System.Data.DataRowView)Container.DataItem)["City"]%>
в случае, когда данные получены из DataReader,
<%# ((System.Data.IDataRecord)Container.DataItem)["City"]%>
в случае, когда данные получены из DataSet,
или
<%# DataBinder.Eval(Container.DataItem, "City") %>
Этот способ заменяет оба предыдущие, так как DataBinder с помощью статической функции Eval сам определяет тип источника и соответственно его обрабатывает. Метод Eval перегружен, его второй вариант принимает аргумент для форматирования данных:
DataBinder.Eval(Container.DataItem, "Age","{0:2d}")
В ASP .NET 2.0 синтаксис можно упростить и написать
<%# Eval("City")%>
В новых элементах управления , , , где поддерживается двунаправленный вывод данных, можно вызывать метод Bind. Его используют в шаблонах редактируемых строк:
<asp:TextBox ID="EditFirstNameTextBox" Runat="Server" Text='<%#
Bind("FirstName") %>' />
Шаблон — это множество тегов HTML и серверных элементов управления, которые задают образец для отображения составной части сложного элемента управления. DataSourceID и DataMember, собственных свойств у него нет. Поэтому у программиста есть полный контроль над тем, как выводится
Как минимум, должен быть описан шаблон ItemTemplate. HeaderTemplate отображается один раз в начале отрисовки FooterTemplate в конце, SeparatorTemplate между отображением каждого пункта, AlternatingItemTemplate — для четных пунктов. Все серверные элементы управления в шаблон помещаются целиком, поэтому, чтобы получить таблицу, используют простые теги HTML. Например, открывающий тег < table > помещают в HeaderTemplate, а закрывающий — в FooterTemplate.
В этом примере составляются характеристики сотрудников:
<asp:Repeater ID="Repeater1" runat="server"
DataSourceID="SqlDataSource1" >
<HeaderTemplate><asp:Label runat="server" ID="Header1"
BackColor="DarkOrange" ForeColor="ActiveCaptionText"
Font-Bold="true" Font-Underline="true" Font-Size="Large">
We present our valued Employees!</asp:Label>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Panel ID="Panel1" runat="server"
BackColor="LightPink">
<asp:Image ID="Photo" runat="server" ImageUrl=<%#
Eval("PhotoPath")%>/>
<%# Eval( "TitleOfCourtesy") %>
<%# DataBinder.Eval(Container.DataItem,
"FirstName") %>
<%# DataBinder.Eval(Container.DataItem,
"LastName") %>
was born in <%# Eval("BirthDate",
"{0:dd.MM.yyyy}") %>.<p>
<%# Eval("TitleOfCourtesy").ToString() == "Mr."
|| Eval("TitleOfCourtesy").ToString() == "Dr." ? "He" : "She"%>
lives in beautiful city
<%#
((System.Data.DataRowView)Container.DataItem)["City"]%>,
<%# Eval( "Region") %> in
<%# DataBinder.Eval(Container.DataItem,
"Country") %>.</p>
<p>We appreciate <%#
Eval("TitleOfCourtesy").ToString() == "Mr." ||
Eval("TitleOfCourtesy").ToString() == "Dr." ? "his" : "her"%>
work as <%# Eval("Title") %>.</p>
<p><%# DataBinder.Eval(Container.DataItem,
"Notes") %></p>
</asp:Panel>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table></FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$
ConnectionStrings:NorthwindConnectionString1 %>"
SelectCommand="SELECT * FROM [Employees]"
></asp:SqlDataSource>
В браузере это выглядит так:
(рис 8.1) Обратите внимание на условные выражения:
<%# Eval("TitleOfCourtesy").ToString() == "Mr." ||
Eval("TitleOfCourtesy").ToString() == "Dr." ? "He" : "She"%>
Благодаря этому в предложении о мужчине употребляются местоимения мужского, а в предложении о женщине — женского рода. В таблице нет поля для пола, но его можно вычислить по полю TitleOfCourtesy, который у мужчин бывает или "Mr. ", или "Dr.".
Если нужно изменить внешний вид всего шаблона, проще всего поместить все его содержимое или весь элемент в Panel и определить в нем стили.
С помощью элемента управления
SelectedItemTemplate и EditItemTemplate. Кроме того, у него есть верхний и нижний колонтитулы со стилями HeaderStyle и FooterStyle.
Во-вторых, можно изменить способы отображения. По умолчанию RepeatLayout, установленное как Flow, убирает табличные теги из выходного потока. RepeatDirection меняет направление вывода с вертикального на горизонтальное. RepeatColumns задает количество столбцов таблицы, по умолчанию равное 1.
BaseDataList, который наследует WebControl. Поэтому у него, в отличие от CellPadding и CellSpacing.
У SmartTag — Edit Templates. После того, как редактирование окончено, не забудьте выйти из режима — End Template Editing.
Можно спроектировать этот элемент так, чтобы в обычном состоянии отображалась краткая информация, а в выбранном состоянии — более подробная.
Посмотрим пример из Quickstarts:
<asp:DataList id="DataList1" runat="server"
BorderColor="black" BorderWidth="1"
GridLines="Both" CellPadding="3"
Font-Names="Verdana" Font-Size="8pt"
Width="150px"
HeaderStyle-BackColor="#aaaadd"
AlternatingItemStyle-BackColor="Gainsboro"
SelectedItemStyle-BackColor="yellow"
OnItemCommand="DataList_ItemCommand"
>
<HeaderTemplate>
Items
</HeaderTemplate>
<ItemTemplate>
<asp:LinkButton id="button1" runat="server" Text="Show
details" CommandName="select" />
<%# DataBinder.Eval(Container.DataItem, "StringValue") %>
</ItemTemplate>
<SelectedItemTemplate>
Item:
<%# DataBinder.Eval(Container.DataItem, "StringValue") %>
<br>
Order Date:
<%# DataBinder.Eval(Container.DataItem, "DateTimeValue",
"{0:d}") %>
<br>
Quantity:
<%# DataBinder.Eval(Container.DataItem, "IntegerValue",
"{0:N1}") %>
<br>
</SelectedItemTemplate>
</asp:DataList>
А обработчик выбора записи такой:
void DataList_ItemCommand(object Sender,
DataListCommandEventArgs e) {
string cmd = ((LinkButton)e.CommandSource).CommandName;
if (cmd == "select")
DataList1.SelectedIndex = e.Item.ItemIndex;
BindList();
}
Чтобы реализовать редактирование, тоже нужно обрабатывать событие. Поэтому в ASP .NET 2.0 .
Свойство DataKeyField имеется и у
Это очень популярный элемент управления, и неудивительно. Особенно много он применялся в ASP .NET 1.x, но теперь его функции перекрываются . Тем не менее его стоит изучить, так как многие его свойства схожи со свойствами . DataSource и получить готовую таблицу на странице. Формат таблицы можно менять независимо от данных. Данные можно сортировать, выбирать, редактировать.
В простейшем варианте нужно установить только свойство DataSource, его значением может быть объект, реализующий интерфейс IEnumerable, например SqlDataReader, DataTable. При этом на странице выводится таблица, где строкам соответствуют записи, а столбцам — поля.
Создадим простой XML-файл с табличной информацией. Это будут данные о лауреатах Нобелевской премии по литературе и физике. Назовите ее nobel.xml:
<?xml version="1.0" encoding="utf-8" ?>
<nobel>
<phisics>
<phisisist>
<name>Basov</name>
<nationality>Russia(USSR)</nationality>
</phisisist>
<phisisist>
<name>Rentgen</name>
<nationality>Germany</nationality>
</phisisist>
<phisisist>
<name>Bor</name>
<nationality> Denmark</nationality>
</phisisist>
</phisics>
<literature>
<writer>
<name>Boris Pasternak</name>
<nationality>Russia</nationality>
<work>"Doctor Zhivago"</work>
<winningdate>1958</winningdate>
</writer>
<writer>
<name>Romain Rollan</name>
<nationality>France</nationality>
<work>"Jean-Cristophe"</work>
<winningdate>1915</winningdate>
</writer>
<writer>
<name>Gabriel Garsia Marquez </name>
<nationality>Columbia</nationality>
<work>"100 years of solitude"</work>
<winningdate>1982</winningdate>
</writer>
<writer>
<name>George Bernard Shaw</name>
<nationality>Great Britain</nationality>
<work></work>
<winningdate>1925</winningdate>
</writer>
</literature>
</nobel>
Тут построена трехуровневая иерархия. Узел < nobel > должен быть прочитан в DataSet. Внутри него есть 2 узла: один с данными о физике, второй — о литературе. Каждый из них будет помещен в DataTable. Узлы < name >, < nationality >, < work >, < winningdate > вложены в < literature > и повторяются для каждого писателя. Они будут считаны в DataColumns таблицы.
Почему узел < work ></ work > у Шоу пустой? Как считал сам Шоу, Нобелевскую премию 1925 года ему дали за то, что в этом году он ничего не написал.
Через методы ReadXml, WriteXml DataSet может читать данные из XML-файла.
Форма, которая читает информацию из этого файла:
<%@ Page Language="C#" Debug="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Xml" %>
<script runat="server">
void bindData()
{
String xmlFilename = Server.MapPath("") + "\\nobel.xml";
DataSet newDataSet = new DataSet();
newDataSet.ReadXml(xmlFilename);
DataTable newDataTable = newDataSet.Tables[1];
DataGrid1.DataSource = newDataTable;
DataGrid1.DataBind();
}
void Page_Load()
{
if (!IsPostBack)
bindData();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Data Grid Control example</title>
</head>
<body>
<form runat="server">
<asp:DataGrid id="DataGrid1" runat="server"
CellSpacing="10"
BorderWidth ="0" BackColor="AliceBlue" EditItemIndex =
"1">
<HeaderStyle BackColor="#AAAADD" Font-Size="20pt" Font-
Bold = "True">
</HeaderStyle>
<AlternatingItemStyle BackColor="#80FF80" />
</asp:DataGrid>
</form>
</body>
</html>
Поменяв индекс в DataTable newDataTable = newDataSet.Tables[1] на 3, получим страницу с другими данными — лауреатов премии по литературе.
По умолчанию элемент AutoGenerateColumns. С элементом управления DataTime и Decimal. Если в поле неподдерживаемый тип, столбец не будет создан. Если ни одного подходящего поля нет, будет выброшено исключение.
Header ), который по умолчанию виден, и нижний колонтитул ( Footer ). При автоматической генерации в заголовке каждого столбца выводится название поля.
Если AutoGenerateColumns установить в False, можно самим управлять колонками и определять более сложный его вид. В таком случае надо включать в BoundColumn. Некоторые свойства BoundColumn:
DataField определяет поле источника данных;DataFormatString задает формат вывода данных;ReadOnly делает поле недоступным для редактирования.В заголовке и нижнем колонтитуле можно установить любой текст, а в заголовке — еще и картинку ( HeaderText, FooterText, HeaderImageUrl ).
В ячейку генерируемой LiteralControl, текст которого берется из источника данных и форматируется в соответствии с DataFormatString. Для редактируемой строки в ячейке появляется TextBox.
Есть и другие типы колонок.
ButtonColumn отображает в каждой строке командную кнопку. Если связать ее с полем, на кнопках будут надписи из этого поля.
EditCommandColumn показывает кнопки для редактирования.
HyperLinkColumn превращает текст в гиперссылки. Например, поле PhotoPath можно показать в такой колонке, и тогда щелчок по ссылке покажет фотографию.
TemplateColumn позволяет определить шаблон отображения, как в
При желании можно программно скрывать и показывать колонки, например:
DataGrid1.Columns[1].Visible = !(DataGrid1.Columns[1].Visible);
У элемента TableItemStyle. Это AlternatingItemStyle, EditItemStyle, FooterStyle, HeaderStyle, ItemStyle, PagerStyle и SelectedItemStyle. Стили образуют иерархию, то есть атрибут "Стиль", который выше в иерархии, наследует те, которые ниже, если он его не переопределяет. Порядок в ней такой:
EditItemStyle — стиль редактируемой строки;SelectedItemStyle — стиль выбранной строки;AlternatingItemStyle — стиль каждой второй строки;ItemStyle — стиль строки по умолчанию;ControlStyle — все свойства, которые влияют на внешний вид элемента, например BackColor. PagerStyle, FooterStyle, HeaderStyle тоже его наследуют.PagerStyle — стиль пейджера, то есть номеров страниц-гиперссылок, при выборе которых таблица перелистывается. Чтобы AllowPaging и количество записей должно быть больше PageSize. Все эти свойства удобно устанавливать с помощью PropertyBuilder.В Visual Studio 2005 есть возможность автоформатирования, как и у
Новый вариант, без автоматической генерации колонок и со стилями:
<asp:DataGrid ID="DataGrid2" runat="server" BackColor="#FFE0C0"
ShowFooter="True" AutoGenerateColumns="False" PageSize="3">
<AlternatingItemStyle BackColor="#C0FFC0" />
<ItemStyle BackColor="#FFFFC0" />
<EditItemStyle BackColor="#C0C000" Font-Size="XX-Large" />
<Columns>
<asp:BoundColumn DataField="name" FooterText="Name"
HeaderText="Фамилия"></asp:BoundColumn>
<asp:BoundColumn DataField="nationality"
FooterText="Country" HeaderText="Страна"></asp:BoundColumn>
<asp:BoundColumn DataField="winningdate" FooterText="Year
won" HeaderText="Год"></asp:BoundColumn>
<asp:BoundColumn DataField="work" FooterText="Work"
HeaderText="Произведение"></asp:BoundColumn>
</Columns>
<FooterStyle Font-Bold="True" Font-Italic="False" Font-
Overline="False" Font-Strikeout="False" Font-Underline="False" />
<HeaderStyle Font-Bold="True" Font-Italic="False" Font-
Overline="False" Font-Strikeout="False" Font-Underline="False" />
</asp:DataGrid>
Добавим в эту форму возможность сортировки по столбцам. AllowSorting. Но это только потенциальная возможность сортировки, так как сам элемент сортировать не может, это должен обеспечить программист. При AllowSorting = True в заголовке выводятся гиперссылки, при нажатии на которые вызывается событие SortCommand. Так как нет автогенерации, в описание BoundColumn нужно вставить SortExpression:
<asp:BoundColumn DataField="name" FooterText="Name"
HeaderText="Фамилия" SortExpression="name">
</asp:BoundColumn>
Метод-обработчик события SortCommand принимает параметр типа DataGridSortCommandEventArgs, в свойстве SortExpression которого содержится строка — выражение сортировки SortExpression. Необходимо использовать это выражение для сортировки данных, полученных из источника данных
protected void DataGrid2_SortCommand(object source, DataGridSortCommandEventArgs e)
{
ViewState["sort"] = e.SortExpression;
bindData();
}
где bindData() вынесен в отдельную функцию и вызывается также из Page_Load:
private void bindData()
{
String xmlFilename = Server.MapPath("") + "\\nobel.xml";
DataSet newDataSet = new DataSet();
newDataSet.ReadXml(xmlFilename);
if (ViewState["sort"] != null)
newDataSet.Tables[3].DefaultView.Sort =
(string)ViewState["sort"];
DataTable newDataTable = newDataSet.Tables[3];
DataGrid2.DataSource = newDataTable;
DataGrid2.DataBind();
}
void Page_Load()
{
if (!IsPostBack)
bindData();
}
| Фамилия | Страна | Год | Произведение |
|---|---|---|---|
| Romain Rollan | France | 1915 | "Jean-Cristophe" |
| George Bernard Shaw | Great Britain | 1925 | |
| Boris Pasternak | Russia | 1958 | "Doctor Zhivago" |
| Gabriel Garsia Marquez | Columbia | 1982 | "100 years of solitude" |
| Name | Country | Year won | Work |
такую технику можно считать устаревшей, так как позволяет делать все это с помощью одного только декларативного связывания.
Покажем возможность удаления, обновления и редактирования данных в .
Создайте на сервере SQL в базе DemoBase таблицу Users с тремя полями:
| Column Name | Data Type | Allow Nulls |
|---|---|---|
| UID | int | |
| Name | varchar(50) | |
| Comments | varchar(250) | + |
| IsRegistered | bit | + |
Поле UID — автоинкрементное. Поэтому операция INSERT не будет требовать задания его значения. Конечно, это первичный ключ. В таблице свойств найдите IdentitySpecification, раскройте его и выберите ( IsIdentity ).
Будем работать с таблицей с помощью трех процедур.
CREATE PROCEDURE dbo.SelectUsers ( @Col INT = 0 ) AS IF @Col = 0 SELECT * FROM Users ELSE IF @Col = 1 SELECT * FROM Users ORDER BY NAME RETURN
Процедура EditUser будет использоваться для вставки записей, если @UID=0, и для обновления в противном случае:
CREATE PROCEDURE dbo.EditUser ( @UID int = 0, @Name varchar(50), @Comments varchar(250), @Registered bit ) AS IF @UID = 0 INSERT INTO Users(Name, Comments, IsRegistered) VALUES(@Name, @Comments, @Registered) ELSE UPDATE Users SET Name = @Name, Comments = @Comments, IsRegistered = @Registered WHERE UID = @UID RETURN
Процедура для удаления записей.
CREATE PROCEDURE dbo.DeleteUser ( @UID int ) AS DELETE FROM Users WHERE UID = @UID RETURN
На форме будет находиться, кроме NameTextBox, а также CommentTextBox и кнопка Add. Для наших тайных целей добавим элемент управления типа HiddenField. Эти цели — хранить id текущего элемента и передавать его .
Добавим на форму следующий источник данных:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$
ConnectionStrings:DemoBaseConnectionString %>"
SelectCommand="dbo.SelectUsers"
SelectCommandType="StoredProcedure"
DeleteCommand="dbo.DeleteUser"
DeleteCommandType="StoredProcedure"
UpdateCommand="dbo.EditUser"
UpdateCommandType="StoredProcedure"
InsertCommand="dbo.EditUser"
InsertCommandType="StoredProcedure"
OldValuesParameterFormatString="">
<InsertParameters>
<asp:Parameter Direction="ReturnValue" Name="RETURN_VALUE"
Type="Int32" />
<asp:Parameter Name="UID" Type="Int32" DefaultValue="0" />
<asp:ControlParameter Name="Name" Type="String"
ControlID="NameTextBox"/>
<asp:ControlParameter Name="Comments" Type="String"
ControlID="CommentTextBox" PropertyName="Text"/>
<asp:ControlParameter Name="Registered" Type="Boolean"
ControlID="Registered" PropertyName="Checked"/>
</InsertParameters>
<UpdateParameters>
<asp:Parameter Direction="ReturnValue"
Name="RETURN_VALUE"
Type="Int32" />
<asp:ControlParameter Name="UID" Type="Int32"
ControlID="HiddenField1" />
<asp:ControlParameter Name="Name" Type="String"
ControlID="NameTextBox"/>
<asp:ControlParameter Name="Comments" Type="String"
ControlID="CommentTextBox"/>
<asp:ControlParameter Name="Registered" Type="Boolean"
ControlID="Registered" PropertyName="Checked"/>
</UpdateParameters>
<DeleteParameters>
<asp:ControlParameter ControlID="HiddenField1"
PropertyName="Value" Name="UID" Type="Int32" />
</DeleteParameters>
</asp:SqlDataSource>
Обратите внимание на то, что в InsertParameters значение параметра UID по умолчанию 0 и он не связан с элементом управления. В остальных случаях он связан с HiddenField1. Значение в это поле будет передаваться в обработчиках.
На этот раз TemplateColumn. Этот тип столбца CheckBox:
<asp:DataGrid id="UsersDataGrid" runat="server"
AutoGenerateColumns="False" DataKeyField="UID"
OnDeleteCommand="UsersDataGrid_DeleteCommand"
OnUpdateCommand="UsersDataGrid_UpdateCommand"
OnEditCommand="UsersDataGrid_EditCommand"
DataSourceID="SqlDataSource1"
AllowSorting="True" Caption="Users" CaptionAlign="Top">
<Columns>
<asp:TemplateColumn HeaderText= "Имя">
<ItemTemplate>
<asp:Label id="Label1" runat="server"
Text='<%#DataBinder.Eval(Container, "DataItem.Name")%>'>
</asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox id=NameTextBox runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.Name") %>'>
</asp:TextBox>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Комментарии">
<ItemTemplate>
<asp:Label id="Label2" runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.Comments")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox id= CommentTextBox runat="server" Text='<%#
DataBinder.Eval(Container, "DataItem.Comments")%>'>
</asp:TextBox>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText= "Зарегистрирован">
<ItemTemplate>
<asp:CheckBox runat="server" ID="Registered"
Checked='<%# (bool) DataBinder.Eval(Container,
"DataItem.isRegistered") %>'
Enabled="False"></asp:CheckBox >
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBox runat="server" ID="Registered" Checked='<%#
(bool) DataBinder.Eval(Container, "DataItem.isRegistered")
%>'></asp:CheckBox>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn>
<ItemTemplate>
<asp:LinkButton id="LinkButton1" runat="server"
CommandName="edit">редактировать</asp:LinkButton> ::
<asp:LinkButton id="LinkButton2" runat="server"
CommandName="delete">удалить</asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton id="LinkButton3" runat="server"
CommandName="update">принять</asp:LinkButton> ::
<asp:LinkButton id="LinkButton4" runat="server"
CommandName="cancel">отменить</asp:LinkButton>
</EditItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
И остальные элементы:
<asp:TextBox ID="NameTextBox" runat="server" ></asp:TextBox> <asp:TextBox ID="CommentTextBox" runat="server"></asp:TextBox> <asp:CheckBox ID="Registered" runat="server" /><br /><br /> <asp:Button ID="Button1" runat="server" Text="Add" OnClick="Add_Click" /> <asp:HiddenField ID="HiddenField1" runat="server" />
уже знает параметры команды Delete, это единственный параметр, и связан он был с HiddenField1. Нужно записать значение ключа id в это поле:
protected void UsersDataGrid_DeleteCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
HiddenField1.Value =
UsersDataGrid.DataKeys[e.Item.ItemIndex].ToString();
// Удаление
SqlDataSource1.Delete();
// Обновление данных после удаления
UsersDataGrid.DataBind();
}
Добавление записи происходит еще проще, так как параметры процедуры Insert находятся в тех текстовых полях, которые заполняются для вставки:
protected void Add_Click(object sender, EventArgs e)
{
SqlDataSource1.Insert();
UsersDataGrid.DataBind();
}
В момент начала редактирования текстовые поля прячутся, так как значения из полей редактирования внутри таблицы будут копироваться туда, и нужно скрыть это от пользователя. Кроме того, эти элементы управления во время редактирования не нужны:
protected void UsersDataGrid_EditCommand(object source,
DataGridCommandEventArgs e)
{
UsersDataGrid.EditItemIndex = e.Item.ItemIndex;
NameTextBox.Visible = false;
CommentTextBox.Visible = false;
Registered.Visible = false;
UsersDataGrid.DataBind();
}
Редактирование — сложнее. В шаблоне столбцов элемента , потому что в момент генерации страницы их там просто нет. Например, для того чтобы установить в режим редактирования строку EditItemIndex элемента управления
В событии UpdateCommand в аргументе e находим текущую строку. Обновляемые данные находятся в TextBox -ах в ячейках 0 и 1. Чтобы выйти из режима редактирования, свойству EditItemIndex нужно присвоить значение - 1:
protected void UsersDataGrid_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
TableCell cell=e.Item.Cells[0];
TextBox cnt = (TextBox)cell.FindControl("NameTextBox");
NameTextBox.Text = cnt.Text;
cell = e.Item.Cells[1];
cnt = (TextBox)cell.FindControl("CommentTextBox");
CommentTextBox.Text = cnt.Text;
HiddenField1.Value =
UsersDataGrid.DataKeys[e.Item.ItemIndex].ToString();
cell = e.Item.Cells[2];
CheckBox check = (CheckBox)cell.FindControl("Registered");
Registered.Checked = check.Checked;
SqlDataSource1.Update();
UsersDataGrid.EditItemIndex = -1;
UsersDataGrid.DataBind();
NameTextBox.Text = "";
CommentTextBox.Text = "";
NameTextBox.Visible = true;
CommentTextBox.Visible = true;
Registered.Visible = true;
}
После обновления вновь читаем данные и делаем видимыми поля редактирования.
Отказ от редактирования без сохранения изменений обрабатывается в событии CancelCommand:
protected void UsersDataGrid_CancelCommand(object source,
DataGridCommandEventArgs e)
{
UsersDataGrid.EditItemIndex = -1;
NameTextBox.Visible = true;
CommentTextBox.Visible = true;
UsersDataGrid.DataBind();
}
Мы рассмотрели 3 элемента управления, существовавшие с ASP .NET 1.0.
Объектная модель упрощает связывание с данными, но ее реальная мощь проявляется при использовании новых элементов управления , , , которые мы рассмотрим в следующей лекции.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.