Основы ASP.NET 2.0

         

DetailsView


Элемент управления DetailsView — еще одна новинка ASP .NET 2.0. Он показывает каждый раз одну запись из источника данных в таблице с двумя столбцами, где слева отображается название поля, а справа — значение. Так же как и GridView, DetailsView позволяет производить разбивку на страницы, редактирование и удаление с автоматическим связыванием с источником данных. Он также является наследником CompositeDataBoundControl.

Visual Studio 2005 предоставляет, как обычно, SmartTag, с помощью которого можно задать источник данных, автоформатировать элемент управления, отредактировать поля и шаблоны полей. У него есть шаблон InsertItemTemplate, которого нет в GridView. DetailsView поддерживает разбиение на страницы, хотя на странице всегда только одна запись.

Пример DetailsView, где данные берутся из базы данных Northwind, таблица Employees:

<asp:DetailsView ID="DetailsView1" runat="server" DataSourceID="SqlDataSource2" Height="50px" Width="561px" CellPadding="4" GridLines="None" ForeColor="#333333" HeaderText="Личное дело" AutoGenerateRows="False" DataKeyNames="EmployeeID" AutoGenerateInsertButton="True" <Fields> <asp:BoundField DataField="LastName" HeaderText="Фамилия" SortExpression="LastName" /> <asp:BoundField DataField="FirstName" HeaderText="Имя" SortExpression="FirstName" /> <asp:BoundField DataField="Title" HeaderText="Должность" SortExpression="Title" /> <asp:BoundField DataField="BirthDate" HeaderText="Дата рожде- ния" SortExpression="BirthDate" /> <asp:TemplateField HeaderText="Дата приема" SortExpression="HireDate"> <EditItemTemplate> <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("HireDate") %>'></asp:TextBox> </EditItemTemplate> <InsertItemTemplate> <asp:Calendar ID="CalendarHireDate" runat="server" BackColor="#EFF3FB" ForeColor="#003399" ></asp:Calendar> </InsertItemTemplate> <ItemTemplate> <asp:Label ID="Label1" runat="server" Text='<%# Bind("HireDate") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="HomePhone" HeaderText="Телефон" SortExpression="HomePhone" /> </Fields> <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> <EditRowStyle BackColor="#2461BF" /> <RowStyle BackColor="#EFF3FB" /> <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" /> <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> <AlternatingRowStyle BackColor="White" /> <CommandRowStyle BackColor="#D1DDF1" Font-Bold="True" /> <FieldHeaderStyle BackColor="#DEE8F5" Font-Bold="True" /> </asp:DetailsView>


А так это выглядит на форме:


Рис. 9.2. 

В отличие от GridView, DetailsView позволяет вставлять записи. Для этого нужно установить значение свойства AutoGenerateInsert Button= "True". При отображении появится кнопка New. Ее нажатие переводит элемент в режим вставки, по умолчанию для каждого поля генерируются TextBox-ы.


Рис. 9.3. 

Если источник данных для DetailsView — SqlDataSource, то у него должны быть определены свойство InsertCommand и набор параметров.

У DetailsView имеются пары событий, которые происходят при связывании с данными, при переходе из режима просмотра в режим вставки, при перелистывании страницы.

ItemCreatedнет пары
ItemDeletingItemDeleted
ItemInsertedItemInserting
ItemUpdatedItemUpdating
ModeChangedModeChanging
В таблице Employees некоторые поля должны быть заполнены, у них стоит AllowNulls=false. Поэтому при работе нашей формы произойдет исключение, если попытаться вставить запись, не введя имя и фамилию. Чтобы избежать этого, во время обработки события ItemInserting нужно сделать проверку. Также обработаем событие ModeChanged, чтобы напомнить клиенту о необходимости ввести эти поля:

protected void DetailsView1_ModeChanged(object sender, EventArgs e) { switch (DetailsView1.CurrentMode) { case DetailsViewMode.Insert: DetailsView1.HeaderText = "Заполните, пожалуйста, форму. Имя и фамилия обязательны."; DetailsView1.HeaderStyle.ForeColor = System.Drawing.Color.Purple; DetailsView1.HeaderStyle.BackColor = System.Drawing.Color.AliceBlue; break; case DetailsViewMode.ReadOnly: DetailsView1.HeaderText = "Личное дело"; DetailsView1.HeaderStyle.ForeColor = System.Drawing.Color.White; DetailsView1.HeaderStyle.BackColor = System.Drawing.Color.FromArgb(0x507CD1); break; } }



Так как DetailsView1 все- таки таблица, ищем поля ввода в 0 и 1 строке в 1 столбце. Если там пусто, отменяем вставку:

protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e) { TextBox textbox1 = (TextBox)DetailsView1.Rows[0].Controls[1].Controls[0]; textbox1.Text.Trim(); TextBox textbox2 = (TextBox)DetailsView1.Rows[1].Controls[1].Controls[0]; textbox2.Text.Trim(); if (textbox1.Text == "" || textbox2.Text == "") e.Cancel= true; }

DetailsView можно использовать совместно с другими элементами управления. Тогда нужную запись можно будет найти не перелистывая страниц, а выбирая, например в DropDownList:

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString2 %>" DeleteCommand="DELETE FROM [Suppliers] WHERE [SupplierID] = @SupplierID" InsertCommand="INSERT INTO [Suppliers] ([CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax], [HomePage]) VALUES (@CompanyName, @ContactName, @ContactTitle, @Address, @City, @Region, @PostalCode, @Country, @Phone, @Fax, @HomePage)" ProviderName="<%$ ConnectionStrings:NorthwindConnectionString2.ProviderName %>" SelectCommand="SELECT [SupplierID], [CompanyName], [ContactName], [ContactTitle], [Address], [City], [Region], [PostalCode], [Country], [Phone], [Fax], [HomePage] FROM [Suppliers] WHERE [SupplierID] = @SupplierID" UpdateCommand="UPDATE [Suppliers] SET [CompanyName] = @CompanyName, [ContactName] = @ContactName, [ContactTitle] = @ContactTitle, [Address] = @Address, [City] = @City, [Region] = @Region, [PostalCode] = @PostalCode, [Country] = @Country, [Phone] = @Phone, [Fax] = @Fax, [HomePage] = @HomePage WHERE [SupplierID] = @SupplierID" EnableCaching="True"> <SelectParameters> <asp:ControlParameter ControlID="DropDownList1" Name="SupplierID" PropertyName="SelectedValue" Type="String" /> </SelectParameters> <InsertParameters> <asp:Parameter Name="CompanyName" Type="String" /> <asp:Parameter Name="ContactName" Type="String" /> <asp:Parameter Name="ContactTitle" Type="String" /> <asp:Parameter Name="Address" Type="String" /> <asp:Parameter Name="City" Type="String" /> <asp:Parameter Name="Region" Type="String" /> <asp:Parameter Name="PostalCode" Type="String" /> <asp:Parameter Name="Country" Type="String" /> <asp:Parameter Name="Phone" Type="String" /> <asp:Parameter Name="Fax" Type="String" /> <asp:Parameter Name="HomePage" Type="String" /> </InsertParameters> <UpdateParameters> <asp:Parameter Name="CompanyName" Type="String" /> <asp:Parameter Name="ContactName" Type="String" /> <asp:Parameter Name="ContactTitle" Type="String" /> <asp:Parameter Name="Address" Type="String" /> <asp:Parameter Name="City" Type="String" /> <asp:Parameter Name="Region" Type="String" /> <asp:Parameter Name="PostalCode" Type="String" /> <asp:Parameter Name="Country" Type="String" /> <asp:Parameter Name="Phone" Type="String" /> <asp:Parameter Name="Fax" Type="String" /> <asp:Parameter Name="HomePage" Type="String" /> <asp:Parameter Name="SupplierID" Type="Int32" /> </UpdateParameters> <DeleteParameters> <asp:Parameter Name="SupplierID" Type="Int32" /> </DeleteParameters> </asp:SqlDataSource> <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString2 %>" ProviderName="<%$ ConnectionStrings:NorthwindConnectionString2.ProviderName %>" SelectCommand="SELECT [SupplierID], [CompanyName] FROM [Suppliers]"> </asp:SqlDataSource> <asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlDataSource2" DataTextField="CompanyName" DataValueField="SupplierID" AutoPostBack="True"> </asp:DropDownList> <asp:DetailsView ID="DetailsView1" runat="server" DataSourceID="SqlDataSource1" Height="86px" Width="452px" DataKeyNames="SupplierID" BackColor="White" BorderColor="#3366CC" BorderWidth="1px" CellPadding="4"> <Fields> <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" ShowInsertButton="True" /> </Fields> <FooterStyle BackColor="#99CCCC" ForeColor="#003399" /> <EditRowStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" /> <RowStyle BackColor="White" ForeColor="#003399" /> <PagerStyle BackColor="#99CCCC" ForeColor="#003399" HorizontalAlign="Left" /> <HeaderStyle BackColor="#003399" Font-Bold="True" ForeColor="#CCCCFF" /> </asp:DetailsView>

Значение AutoPostBack="True" в DropDownList1 необходимо, чтобы страница обновлялась и запись в DetailsView1 менялась.


FormView


Еще один новый элемент FormView похож на DetailsView, но отличается от него тем, что нуждается в шаблоне для своего представления:

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:pubsConnectionString1 %>" DeleteCommand="DELETE FROM [authors] WHERE [au_id] = @au_id" InsertCommand="INSERT INTO [authors] ([au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [con- tract]) VALUES (@au_id, @au_lname, @au_fname, @phone, @address, @city, @state, @zip, @contract)" ProviderName="<%$ ConnectionStrings:pubsConnectionString1.ProviderName %>" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]" UpdateCommand="UPDATE [authors] SET [au_lname] = @au_lname, [au_fname] = @au_fname, [phone] = @phone, [address] = @address, [city] = @city, [state] = @state, [zip] = @zip, [contract] = @contract WHERE [au_id] = @au_id" EnableCaching="true" CacheDuration="120"> <InsertParameters> <asp:Parameter Name="au_id" Type="String" /> <asp:Parameter Name="au_lname" Type="String" /> <asp:Parameter Name="au_fname" Type="String" /> <asp:Parameter Name="phone" Type="String" /> <asp:Parameter Name="address" Type="String" /> <asp:Parameter Name="city" Type="String" /> <asp:Parameter Name="state" Type="String" /> <asp:Parameter Name="zip" Type="String" /> <asp:Parameter Name="contract" Type="Boolean" /> </InsertParameters> <UpdateParameters> <asp:Parameter Name="au_lname" Type="String" /> <asp:Parameter Name="au_fname" Type="String" /> <asp:Parameter Name="phone" Type="String" /> <asp:Parameter Name="address" Type="String" /> <asp:Parameter Name="city" Type="String" /> <asp:Parameter Name="state" Type="String" /> <asp:Parameter Name="zip" Type="String" /> <asp:Parameter Name="contract" Type="Boolean" /> <asp:Parameter Name="au_id" Type="String" /> </UpdateParameters> <DeleteParameters> <asp:Parameter Name="au_id" Type="String" /> </DeleteParameters> </asp:SqlDataSource>


<asp:FormView ID="FormView1" runat="server" DataKeyNames="au_id" DataSourceID="SqlDataSource1"> <EditItemTemplate> au_id: <asp:Label ID="au_idLabel1" runat="server" Text='<%# Eval("au_id") %>'></asp:Label><br /> au_lname: <asp:TextBox ID="au_lnameTextBox" runat="server" Text='<%# Bind("au_lname") %>'> </asp:TextBox><br /> au_fname: <asp:TextBox ID="au_fnameTextBox" runat="server" Text='<%# Bind("au_fname") %>'> </asp:TextBox><br /> phone: <asp:TextBox ID="phoneTextBox" runat="server" Text='<%# Bind("phone") %>'> </asp:TextBox><br /> address: <asp:TextBox ID="addressTextBox" runat="server" Text='<%# Bind("address") %>'> </asp:TextBox><br /> city: <asp:TextBox ID="cityTextBox" runat="server" Text='<%# Bind("city") %>'> </asp:TextBox><br /> state: <asp:TextBox ID="stateTextBox" runat="server" Text='<%# Bind("state") %>'> </asp:TextBox><br /> zip: <asp:TextBox ID="zipTextBox" runat="server" Text='<%# Bind("zip") %>'> </asp:TextBox><br /> contract: <asp:CheckBox ID="contractCheckBox" runat="server" Checked='<%# Bind("contract") %>' /><br /> <asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update" Text="Update"> </asp:LinkButton> <asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"> </asp:LinkButton> </EditItemTemplate> <InsertItemTemplate> au_id: <asp:TextBox ID="au_idTextBox" runat="server" Text='<%# Bind("au_id") %>'> </asp:TextBox><br /> au_lname: <asp:TextBox ID="au_lnameTextBox" runat="server" Text='<%# Bind("au_lname") %>'> </asp:TextBox><br /> au_fname: <asp:TextBox ID="au_fnameTextBox" runat="server" Text='<%# Bind("au_fname") %>'> </asp:TextBox><br /> phone: <asp:TextBox ID="phoneTextBox" runat="server" Text='<%# Bind("phone") %>'> </asp:TextBox><br /> address: <asp:TextBox ID="addressTextBox" runat="server" Text='<%# Bind("address") %>'> </asp:TextBox><br /> city: <asp:TextBox ID="cityTextBox" runat="server" Text='<%# Bind("city") %>'> </asp:TextBox><br /> state: <asp:TextBox ID="stateTextBox" runat="server" Text='<%# Bind("state") %>'> </asp:TextBox><br /> zip: <asp:TextBox ID="zipTextBox" runat="server" Text='<%# Bind("zip") %>'> </asp:TextBox><br /> contract: <asp:CheckBox ID="contractCheckBox" runat="server" Checked='<%# Bind("contract") %>' /><br /> <asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert" Text="Insert"> </asp:LinkButton> <asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"> </asp:LinkButton> </InsertItemTemplate> <ItemTemplate> au_id: <asp:Label ID="au_idLabel" runat="server" Text='<%# Eval("au_id") %>'></asp:Label><br /> Author' s name: <asp:Label ID="au_fnameLabel" runat="server" Text='<%# Bind("au_fname") %>'></asp:Label>



<asp:Label ID="au_lnameLabel" runat="server" Text='<%# Bind("au_lname") %>'></asp:Label><br /> phone: <asp:Label ID="phoneLabel" runat="server" Text='<%# Bind("phone") %>'></asp:Label>

address: <asp:Label ID="addressLabel" runat="server" Text='<%# Bind("address") %>'></asp:Label><br /> city: <asp:Label ID="cityLabel" runat="server" Text='<%# Bind("city") %>'></asp:Label>



state: <asp:Label ID="stateLabel" runat="server" Text='<%# Bind("state") %>'></asp:Label>

zip: <asp:Label ID="zipLabel" runat="server" Text='<%# Bind("zip") %>'></asp:Label><br /> contract: <asp:CheckBox ID="contractCheckBox" runat="server" Checked='<%# Bind("contract") %>' Enabled="false" /><br /> <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"> </asp:LinkButton> <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete"> </asp:LinkButton> <asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New" Text="New"> </asp:LinkButton> </ItemTemplate> </asp:FormView>

На этом мы завершим рассмотрение работы с базами данных.


Элемент управления GridView является усовершенствованным


Элемент управления GridView является усовершенствованным элементом, призванным заменить DataGrid. Все сказанное о DataGrid относится к GridView, но с немного другими названиями. Так, вместо BoundColumn употребляется BoundField, а в названиях стилей вместо Item находится Row. Таким образом, любой DataGrid можно преобразовать в GridView, но не наоборот. Хотя в простейшем варианте DataGrid отображает такую же таблицу, он наследник не DataGrid, а CompositeDataBoundControl.

Главное преимущество GridView — автоматическое связывание с данными, благодаря чему нет необходимости писать обработчики событий, чтобы обеспечить функциональность, такую как удаление, редактирование, сортировка, разбиение на страницы при условии связывания с элементами-источниками данных. Он обеспечивает стандартную обработку подобных событий, но ее всегда можно расширить, чтобы обеспечить дополнительные возможности.

В отличие от версии 1.1, новые элементы могут работать и на мобильных устройствах.

GridView вместе с SqlDataSource появится простым перетаскиванием таблицы Users на форму:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="UID" DataSourceID="SqlDataSource1" EmptyDataText="There are no data records to display."> <Columns> <asp:BoundField DataField="name" HeaderText="name" SortExpression="name" /> <asp:BoundField DataField="Comments" HeaderText="Comments" SortExpression="Comments" /> </Columns> </asp:GridView> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:DemoBaseConnectionString1 %>" DeleteCommand="DELETE FROM [Users] WHERE [UID] = @UID" InsertCommand="INSERT INTO [Users] ([UID], [name], [Comments]) VALUES (@UID, @name, @Comments)" ProviderName="<%$ ConnectionStrings:DemoBaseConnectionString1.ProviderName %>" SelectCommand="SELECT [UID], [name], [Comments] FROM [Users]" UpdateCommand="UPDATE [Users] SET [name] = @name, [Comments] = @Comments WHERE [UID] = @UID"> <InsertParameters> <asp:Parameter Name="UID" Type="Int32" /> <asp:Parameter Name="name" Type="String" /> <asp:Parameter Name="Comments" Type="String" /> </InsertParameters> <UpdateParameters> <asp:Parameter Name="name" Type="String" /> <asp:Parameter Name="Comments" Type="String" /> <asp:Parameter Name="UID" Type="Int32" /> </UpdateParameters> <DeleteParameters> <asp:Parameter Name="UID" Type="Int32" /> </DeleteParameters> </asp:SqlDataSource>



Установка свойства AllowSorting создает в заголовке гиперссылки, при нажатии на которые таблица будет сортироваться по выбранному полю. В этом проявляется преимущество перед DataGrid, для сортировки необходимо переопределить событие SortCommand (рис. 9.1).

После повторного нажатия на заголовок таблица сортируется по этому полю в убывающем порядке.

Иногда значения в каком-либо поле могут повторяться, и нужно отсортировать значения сначала по первому полю, затем по второму. Но сортировка по умолчанию сортирует только по одному полю. Если теперь нажать мышкой на Comments, сортировка по имени пропадет.


Рис. 9.1. 

ИмяComments
BurdaОдесса, ведущий кулинар
BurdaРедактор журнала мод
BushВашингтон, президент
BushБуш-отец
В таком случае поможет немного кодирования. Переопределим событие Sorting:

protected void GridView1_Sorting(object sender, GridViewSortEventArgs e) { string oldExpression = GridView1.SortExpression; string newExpression = e.SortExpression; if (oldExpression.IndexOf(newExpression) < 0) { if (oldExpression.Length > 0) e.SortExpression = oldExpression + ", " + newExpression; else e.SortExpression = newExpression; } else { e.SortExpression = oldExpression; } }

Отсортируем сначала по имени, потом по Comments:

ИмяComments
BurdaОдесса, ведущий кулинар
BurdaРедактор журнала мод
BushБуш-отец
BushВашингтон, президент


Пейджер можно настроить разнообразными способами через настройку PagerSettings, например:

<PagerSettings FirstPageText="Первая" Mode="NextPreviousFirstLast" LastPageText="Последняя" NextPageText="->" />

Вместо текста элементами пейджера могут служить картинки:

<PagerSettings Mode="NextPreviousFirstLast" FirstPageImageUrl="~/RW_btn.gif" LastPageImageUrl="~/FF_btn.gif" NextPageImageUrl="~/fwd_btn.gif" PreviousPageImageUrl="~/RW_btn.gif" />

Поле Comments в таблице может быть пустым, то есть его значение допускает Null. Можно задать текст, который отображается для таких значений:

<asp:BoundField DataField="Comments" HeaderText="Comments" SortExpression="Comments" NullDisplayText="N/A"/>

Введен также шаблон на случай, когда в источнике данных нет ни одной записи:

<asp:GridView ID="GridView1" runat="server"> <EmptyDataTemplate> No records </EmptyDataTemplate> </asp:GridView>

Удаление и редактирование записей делается добавлением в контейнер <Columns> столбца

<asp:CommandField ShowEditButton="True" ShowDeleteButton="True" />

В столбце появляются гиперссылки "Delete", "Edit".

Свойство ButtonType может принимать значение Image, в таком случае нужно задать путь к картинке или кнопке:

<asp:CommandField ButtonType="Image" DeleteImageUrl="~/button- delete.gif" ShowDeleteButton="True" /> <asp:CommandField ButtonType="Button" ShowDeleteButton="True" />



До сих пор все данные отображались в виде простого текста. GridView позволяет настраивать столбцы, чтобы в них появлялись различные элементы управления. Например, если в источнике данных есть булевское поле, то GridView будет показывать Checkbox.

Типы колонок те же, что и в DataGrid, и к ним прибавилось 2 новых типа:

CheckBoxField — в каждой строке выводится флажок CheckBox.

ImageField позволяет выводить картинку, если в поле хранится путь к ней.

HyperLinkField — аналог HyperLinkColumn в DataGrid. Его можно использовать для передачи параметров QueryStringParameter, чтобы в результате выводить отфильтрованную информацию. На странице CustomersByCountry находится источник данных, знакомый по 7-й лекции.

<asp:SqlDataSource ID="SqlDataSource4" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT * FROM [Customers] where @Country is null or Country = @Country" ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>" CancelSelectOnNullParameter="False"> <SelectParameters> <asp:QueryStringParameter Name="Country" QueryStringField="Country" /> </SelectParameters> </asp:SqlDataSource>

К нему привязан GridView с полем типа HyperLinkField:

<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource4" OnRowUpdating="GridView1_RowUpdating" OnRowDataBound="GridView1_RowDataBound" OnRowUpdated="GridView1_RowUpdated" AutoGenerateColumns="False"> <Columns> <asp:BoundField DataField="CompanyName" HeaderText="CompanyName" SortExpression="CompanyName" /> <asp:BoundField DataField="ContactName" HeaderText="ContactName" SortExpression="ContactName" /> <asp:BoundField DataField="ContactTitle" HeaderText="ContactTitle" SortExpression="ContactTitle" /> <asp:BoundField DataField="Address" HeaderText="Address" SortExpression="Address" /> <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" /> <asp:HyperLinkField HeaderText="Country" DataNavigateUrlFields="Country" DataNavigateUrlFormatString="~/CustomersByCountry.aspx?coun- try={0}" DataTextField="Country" /> </Columns> </asp:GridView> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/CustomersByCountry.aspx">View all</asp:HyperLink>


События GridView


Элементы управления, описываемые в этой лекции, имеют по два события для каждой операции. Одно из них возникает до начала выполнения операции, второе — после. Например, RowUpdated — когда пользователь обновляет запись, происходит событие RowUpdating, выполняется команда Update источника данных и затем происходит событие RowUpdated.

В RowUpdating мы можем узнать, какая информация посылается источнику данных и изменить ее, а, возможно, и отменить обновление.

В обработчике события RowUpdating передается аргумент типа GridViewUpdateEventArgs. Его свойство RowIndex определяет индекс текущей строки. Чтобы отменить операцию, установите свойство Cancel в true.

В коллекциях OldValues и NewValues содержатся старые и новые значения полей. В этом примере перед обновлением данные кодируются с целью защиты от хакеров:

protected void GridView1_RowUpdating(Object sender, GridViewUpdateEventArgs e) { foreach (DictionaryEntry entry in e.NewValues) { if(entry.Value!=null) e.NewValues[entry.Key] = Server.HtmlEncode(entry.Value.ToString()); } } }

Событие RowUpdated можно использовать, чтобы обрабатывать ошибки при вводе данных. В таблице Customers поле CompanyName не допускает пустого значения. Если пользователь его введет, будет выброшено исключение. Чтобы не допустить появления экрана с непонятным текстом, добавляем метку

<asp:Label ID="ErrorLabel" runat="server" Text=" " Font- Bold="True" ForeColor="Red"></asp:Label><br />


Перехватываем и обрабатываем ошибку редактирования:
protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e) { if (e.Exception != null) { ErrorLabel.Text = e.Exception.Message; e.ExceptionHandled = true; } }
Другие парные события:
RowDeletingRowDeleted
PageIndexChangedPageIndexChanging
SelectedIndexChangedSelectedIndexChanging
SortedSorting

В программном режиме можно манипулировать коллекцией Rows, состоящей из объектов типа GridViewRow. Строки GridView имеют свойства RowState и RowType. RowState может принимать значения из перечисления: Normal, Edit, Alternate, Insert и Selected.
Данные, хранящиеся в строке, можно получить из коллекции DataItem, которая индексируется названиями полей.
Создайте страницу Products.aspx и опять с помощью drag-and-drop таблицы Products создайте GridView. Посмотрим, как можно в обработчике события RowDataBound изменять внешний вид таблицы. Пусть нужно установить различные цвета фона в зависимости от категории товара. Добавим обработчик RowDataBound. У аргумента события есть свойство Row, которое позволяет манипулировать строкой GridView:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { switch ((int)((DataRowView)e.Row.DataItem)["CategoryID"]) { case 1: e.Row.BackColor = Color.AliceBlue; break; case 2: e.Row.BackColor = Color.AntiqueWhite; break; case 3: e.Row.BackColor = Color.FloralWhite; break; case 4: e.Row.BackColor = Color.Beige; break; default: e.Row.BackColor = Color.White; break; } } }


Можно сделать так, чтобы стиль строк менялся при наведении курсора мыши:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { e.Row.Attributes["onmouseover"] = "this.style.backgroundColor='#FFE4B5'"; e.Row.Attributes["onmouseout"] = "this.style.backgroundColor='#FFFFFF'"; } }
Наш GridView выводит числовые значения полей CategoryId и SupplierId. Но, конечно, пользователю нужны названия, и брать их приходится из других таблиц. Можно связать GridView и с представлением (View), но представления не поддерживают редактирование.
Установим свойство AutoGenerateEditButton в True и превратим столбец CategoryId в TemplateField, а также добавим второй источник данных:
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Categories] ORDER BY [CategoryName]"> </asp:SqlDataSource>
Visual Studio 2005 сгенерировал шаблон, который предстоит изменить на такой:
<asp:TemplateField HeaderText="Категория" SortExpression="CategoryID"> <EditItemTemplate> <asp:DropDownList ID="CatDropDownList" runat="server" DataSourceID="SqlDataSource2" DataValueField="CategoryId" DataTextField="CategoryName" SelectedValue=<%# Bind("CategoryId") %>> </asp:DropDownList > </EditItemTemplate> <ItemTemplate> <asp:Label ID="CatLabel" runat="server" ></asp:Label> </ItemTemplate> </asp:TemplateField>


При этом в режиме отображения строки в колонке "Категория" ничего не выводится. Чтобы получить нужное значение из таблицы Categories, напишем обработчик события RowDataBound:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) if (e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate) { // получить данные из SqlDataSource2 DataView ds = (DataView)SqlDataSource2.Select(DataSourceSelectArguments.Empty); // получить значение текущей категории DataRowView view = (DataRowView)e.Row.DataItem; int catid = (int)view.Row[3]; // отфильтровать нужную категорию ds.RowFilter = string.Format("CategoryID='{0}'", catid); Label Text1 = (Label)e.Row.FindControl("CatLabel"); Text1.Text = ds[0].Row["CategoryName"].ToString(); } }
Точно так же можно поступить с полем SupplierID.

в пользование программистам архитектуру привязки


ASP .NET 2.0 дает в пользование программистам архитектуру привязки данных, которая облегчает эту задачу. Вместо того чтобы вручную заполнять элементы управления данными, полученными в результате запроса, мы создаем элемент-источник данных и привязываем к ним один или несколько потребителей данных.