Добавление клиентского подтверждения при удалении (VB)

Скотт Митчелл

Загрузить PDF-файл

В интерфейсах, которые мы создали до сих пор, пользователь может случайно удалить данные, нажав кнопку Удалить, когда он должен был нажать кнопку Изменить. В этом руководстве мы добавим диалоговое окно подтверждения на стороне клиента, которое появляется при нажатии кнопки Удалить.

Введение

В последних нескольких руководствах мы узнали, как совместно использовать архитектуру приложения ObjectDataSource и веб-элементы управления данными для предоставления возможностей вставки, редактирования и удаления. Интерфейсы удаления, которые мы рассмотрели на данный момент, состоят из кнопки Delete, которая при нажатии вызывает обратную передачу и вызывает метод ObjectDataSource Delete() . Delete() Затем метод вызывает настроенный метод из уровня бизнес-логики, который распространяет вызов на уровень доступа к данным, выдавая фактическую DELETE инструкцию в базу данных.

Хотя этот пользовательский интерфейс позволяет посетителям удалять записи с помощью элементов управления GridView, DetailsView или FormView, ему не хватает подтверждения, когда пользователь нажимает кнопку Удалить. Если пользователь случайно нажмет кнопку Удалить, когда он хотел нажать кнопку Изменить, запись, предназначенная для обновления, будет удалена. Чтобы избежать этого, в этом руководстве мы добавим диалоговое окно подтверждения на стороне клиента, которое появляется при нажатии кнопки Удалить.

Функция JavaScript confirm(string) отображает свой строковый входной параметр в виде текста в модальном диалоговом окне, оснащенном двумя кнопками — "ОК" и "Отмена" (см. рис. 1). Функция confirm(string) возвращает логическое значение в зависимости от того, какая кнопка нажата (trueесли пользователь нажимает кнопку ОК и false нажимает кнопку Отмена).

Метод javaScript confirm(string) отображает модальное Client-Side messagebox

Рис. 1. Метод JavaScript confirm(string) отображает модальное Client-Side messagebox

Если во время отправки формы из обработчика false событий на стороне клиента возвращается значение , отправка формы отменяется. Используя эту функцию, можно заставить клиентский onclick обработчик событий кнопки Удалить возвращать значение вызова .confirm("Are you sure you want to delete this product?") Если пользователь нажимает кнопку Отмена, confirm(string) возвращает значение false, что приведет к отмене отправки формы. Без обратной передачи продукт, на который была нажата кнопка "Удалить", не будет удален. Однако если пользователь нажимает кнопку ОК в диалоговом окне подтверждения, обратная связь будет продолжаться без ослабения, а продукт будет удален. Дополнительные сведения об этом методе confirm() см. в статье Использование метода JavaScript для управления отправкой форм .

Добавление необходимого клиентского скрипта немного отличается при использовании шаблонов, чем при использовании CommandField. Поэтому в этом руководстве мы рассмотрим примеры FormView и GridView.

Примечание

При использовании методов подтверждения на стороне клиента, как описано в этом руководстве, предполагается, что пользователи посещают браузеры, поддерживающие JavaScript, и что у них включен JavaScript. Если одно из этих предположений не соответствует действительности для конкретного пользователя, нажатие кнопки Удалить немедленно вызовет обратную передачу (не отображая поле подтверждения сообщения).

Шаг 1. Создание FormView, поддерживающего удаление

Начните с добавления FormView на ConfirmationOnDelete.aspx страницу в папке EditInsertDelete , привязав его к новому объекту ObjectDataSource, который извлекает сведения о продукте ProductsBLL с помощью метода класса s GetProducts() . Кроме того, настройте ObjectDataSource так, чтобы ProductsBLL метод класса DeleteProduct(productID) сопоставляется с методом ObjectDataSource; Delete() убедитесь, что для раскрывающихся списков вкладок INSERT и UPDATE задано значение (Нет). Наконец, проверка флажок Включить разбиение по страницам в смарт-теге FormView.

После выполнения этих действий новая декларативная разметка ObjectDataSource будет выглядеть следующим образом:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    DeleteMethod="DeleteProduct" OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
    <DeleteParameters>
        <asp:Parameter Name="productID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

Как и в предыдущих примерах, где не использовался оптимистичный параллелизм, уделите некоторое время, чтобы очистить свойство ObjectDataSource OldValuesParameterFormatString .

Так как он привязан к элементу управления ObjectDataSource, который поддерживает только удаление, в FormView ItemTemplate предлагается только кнопка Удалить без кнопок Создать и Обновить. Однако декларативная разметка FormView содержит лишние EditItemTemplate и InsertItemTemplate, которые можно удалить. ItemTemplate Настройте так, чтобы отображалось только подмножество полей данных о продукте. Я настроила название продукта в заголовке <h3> над названиями поставщиков и категорий (вместе с кнопкой Удалить).

<asp:FormView ID="FormView1" AllowPaging="True" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" runat="server">
    <ItemTemplate>
        <h3><i><%# Eval("ProductName") %></i></h3>
        <b>Category:</b>
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'>
        </asp:Label><br />
        <b>Supplier:</b>
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'>
        </asp:Label><br />
        <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
            CommandName="Delete" Text="Delete">
        </asp:LinkButton>
    </ItemTemplate>
</asp:FormView>

Благодаря этим изменениям у нас есть полностью функциональная веб-страница, которая позволяет пользователю переключаться между продуктами по одному, с возможностью удаления продукта, просто нажав кнопку Удалить. На рисунке 2 показан снимок экрана с нашими достижениями в браузере.

FormView отображает сведения об одном продукте

Рис. 2. В FormView отображаются сведения об одном продукте (щелкните для просмотра полноразмерного изображения)

Шаг 2. Вызов функции confirm(string) из кнопки удаления Client-Side событие onclick

После создания FormView последним шагом является настройка кнопки Удалить таким образом, чтобы при ее нажатии посетителем вызывалась функция JavaScript confirm(string) . Добавление клиентского скрипта onclick в клиентское событие Button, LinkButton или ImageButton можно выполнить с помощью OnClientClick property, который является новым для ASP.NET 2.0. Так как мы хотим, чтобы возвращаемое значение confirm(string) функции было возвращено, просто присвойте этому свойству значение: return confirm('Are you certain that you want to delete this product?');

После этого изменения декларативный синтаксис удаления LinkButton должен выглядеть примерно так:

<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
    CommandName="Delete" Text="Delete"
    OnClientClick="return confirm('Are you certain you want to delete this product?');">
</asp:LinkButton>

Это все, что есть к нему! На рисунке 3 показан снимок экрана с этим подтверждением в действии. При нажатии кнопки Удалить откроется диалоговое окно подтверждения. Если пользователь нажимает кнопку Отмена, обратная связь отменяется, а продукт не удаляется. Однако если пользователь нажимает кнопку ОК, обратная связь продолжается и вызывается метод ObjectDataSource Delete() , который завершается удалением записи базы данных.

Примечание

Строка, передаваемая в функцию confirm(string) JavaScript, разделена апострофами (а не кавычками). В JavaScript строки можно разделять с помощью любого символа. Здесь используются апострофы, чтобы разделители для строки, передаваемой в confirm(string) , не вводят неоднозначность с разделителями, используемыми для OnClientClick значения свойства.

При нажатии кнопки

Рис. 3. При нажатии кнопки "Удалить" отображается подтверждение (щелкните для просмотра полноразмерного изображения)

Шаг 3. Настройка свойства OnClientClick для кнопки "Удалить" в CommandField

При работе с Button, LinkButton или ImageButton непосредственно в шаблоне диалоговое окно подтверждения можно связать с ним, просто настроив его OnClientClick свойство для возврата результатов функции JavaScript confirm(string) . Однако commandField, добавляющий поле кнопок Удалить в GridView или DetailsView, не имеет OnClientClick свойства, которое можно задать декларативно. Вместо этого мы должны программно ссылаться на кнопку Удалить в соответствующем DataBound обработчике событий GridView или DetailsView, а затем задать ее OnClientClick свойство.

Примечание

При задании свойства "Удалить" кнопки OnClientClick в соответствующем DataBound обработчике событий у нас есть доступ к данным, привязанным к текущей записи. Это означает, что мы можем расширить сообщение с подтверждением, чтобы включить сведения о конкретной записи, например"Вы действительно хотите удалить продукт Chai?" Такая настройка также возможна в шаблонах с использованием синтаксиса привязки данных.

Чтобы попрактиковаться в настройке OnClientClick свойства для кнопок Удалить в CommandField, добавьте GridView на страницу. Настройте этот GridView для использования того же элемента управления ObjectDataSource, что и FormView. Кроме того, ограничьте BoundFields GridView, включив только имя продукта, категорию и поставщика. Наконец, проверка флажок Включить удаление из смарт-тега GridView. Это приведет к добавлению CommandField в коллекцию GridView Columns со свойством ShowDeleteButtontrue.

После внесения этих изменений декларативная разметка GridView должна выглядеть следующим образом:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True"
            SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True"
            SortExpression="SupplierName" />
    </Columns>
</asp:GridView>

CommandField содержит один экземпляр Delete LinkButton, к которому можно получить доступ программным способом из обработчика RowDataBound событий GridView. После ссылки можно задать его OnClientClick свойство соответствующим образом. Создайте обработчик событий для события, RowDataBound используя следующий код:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
    Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Then
        ' reference the Delete LinkButton
        Dim db As LinkButton = CType(e.Row.Cells(0).Controls(0), LinkButton)

        ' Get information about the product bound to the row
        Dim product As Northwind.ProductsRow = _
            CType(CType(e.Row.DataItem, System.Data.DataRowView).Row, _
            Northwind.ProductsRow)

        db.OnClientClick = String.Format( _
            "return confirm('Are you certain you want to delete the {0} product?');", _
            product.ProductName.Replace("'", "\'"))
    End If
End Sub

Этот обработчик событий работает со строками данных (которые будут иметь кнопку Удалить) и начинается с программной ссылки на кнопку Удалить. Как правило, используйте следующий шаблон:

Dim obj As ButtonType = _
    CType(e.Row.Cells(commandFieldIndex).Controls(controlIndex), ButtonType)

ButtonType — это тип кнопки, используемой CommandField — Button, LinkButton или ImageButton. По умолчанию CommandField использует LinkButtons, но это можно настроить с помощью CommandField s ButtonType property. CommandFieldIndex — это порядковый индекс CommandField в коллекции GridViewColumns, а controlIndex — это индекс кнопки Delete в коллекции CommandField.Controls Значение controlIndex зависит от положения кнопки относительно других кнопок в CommandField. Например, если в CommandField отображается только кнопка Удалить, используйте индекс 0. Однако если перед кнопкой Удалить есть кнопка Изменить, используйте индекс 2. Причина использования индекса 2 заключается в том, что CommandField добавляет два элемента управления перед кнопкой Удалить: кнопка Изменить и LiteralControl, который используется для добавления пространства между кнопками Изменить и Удалить.

В нашем конкретном примере CommandField использует LinkButtons и, будучи самым левым полем, имеет commandFieldIndex 0. Так как в CommandField нет других кнопок, кроме кнопки Удалить, мы используем controlIndex 0.

После ссылки на кнопку Удалить в CommandField мы получаем сведения о продукте, привязанном к текущей строке GridView. Наконец, мы задаем для свойства кнопки OnClientClick Удалить соответствующий Код JavaScript, который включает название продукта. Так как строка JavaScript, передаваемая в функцию confirm(string) , разделена апострофами, необходимо экранировать все апострофы, которые отображаются в имени продукта. В частности, все апострофы в названии продукта экранируются с "\'".

После завершения этих изменений при нажатии кнопки Удалить в GridView отображается настраиваемое диалоговое окно подтверждения (см. рис. 4). Как и в случае с окном сообщения подтверждения из FormView, если пользователь нажимает кнопку Отмена, обратная связь будет отменена, тем самым предотвращая удаление.

Примечание

Этот метод также можно использовать для программного доступа к кнопке Удалить в CommandField в DetailsView. Однако для DetailsView необходимо создать обработчик DataBound события, так как DetailsView не имеет RowDataBound события.

Нажатие кнопки удаления GridView отображает диалоговое окно настраиваемого подтверждения

Рис. 4. Нажатие кнопки удаления GridView отображает диалоговое окно настраиваемого подтверждения (щелкните для просмотра полноразмерного изображения)

Использование TemplateFields

Одним из недостатков CommandField является то, что доступ к его кнопкам должен осуществляться через индексирование и что результирующий объект должен быть приведен к соответствующему типу кнопки (Button, LinkButton или ImageButton). Использование "магических чисел" и жестко заданных типов вызывает проблемы, которые не могут быть обнаружены до выполнения. Например, если вы или другой разработчик добавите новые кнопки в CommandField в какой-то момент в будущем (например, кнопка Изменить) или измените ButtonType свойство, существующий код будет компилироваться без ошибок, но при посещении страницы может возникнуть исключение или непредвиденное поведение в зависимости от того, как был написан код и какие изменения были внесены.

Альтернативным способом является преобразование CommandFields GridView и DetailsView в TemplateFields. При этом будет создан шаблон TemplateField с элементом ItemTemplate , который содержит LinkButton (или Button или ImageButton) для каждой кнопки в CommandField. Эти свойства кнопок OnClientClick можно назначить декларативно, как мы видели в FormView, или получить программный доступ в соответствующем DataBound обработчике событий, используя следующий шаблон:

Dim obj As ButtonType = CType(e.Row.FindControl("controlID"), ButtonType)

Где controlID — это значение свойства кнопки ID . Хотя для этого шаблона по-прежнему требуется жестко заданный тип для приведения, он устраняет необходимость в индексировании, что позволяет изменять макет без возникновения ошибки среды выполнения.

Сводка

Функция JavaScript confirm(string) — это часто используемый метод управления рабочим процессом отправки форм. При выполнении функции отображается модальное клиентское диалоговое окно с двумя кнопками: ОК и Отмена. Если пользователь нажимает кнопку ОК, confirm(string) функция возвращает true. При нажатии кнопки Отмена возвращается falseзначение . Эта функция в сочетании с поведением браузера при отмене отправки формы, если обработчик событий во время отправки возвращает false, может использоваться для отображения сообщения подтверждения при удалении записи.

Функцию confirm(string) можно связать с клиентским обработчиком событий веб-элемента onclick управления Button с помощью свойства элемента управления .OnClientClick При работе с кнопкой Удалить в шаблоне (в одном из шаблонов FormView или TemplateField в DetailsView или GridView) это свойство можно задать декларативно или программно, как мы видели в этом руководстве.

Счастливого программирования!

Об авторе

Скотт Митчелл( Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часах. Он может быть доступен в mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.