Поделиться через


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

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

Скачать в формате PDF

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

Введение

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

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

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

Метод JavaScript confirm(string) отображает модальное окно сообщения Client-Side

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

Во время отправки формы, если значение false возвращается из обработчика событий на стороне клиента, то отправка формы будет отменена. Используя эту функцию, мы можем настроить обработчик событий на клиентской стороне кнопки Delete так, чтобы он возвращал значение вызова onclick. Если пользователь нажимает кнопку "Отмена", confirm(string) возвращает значение false, что приводит к отмене отправки формы. Без отправки данных обратно продукт, кнопка "Удалить" которого была нажата, не будет удалён. Однако если пользователь нажимает "ОК" в диалоговом окне подтверждения, postback-запрос продолжится непрерывно, и продукт будет удален. Ознакомьтесь с помощью метода JavaScript confirm() для управления отправкой форм для получения дополнительных сведений об этом методе.

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

Замечание

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

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

Начните с добавления элемента FormView на страницу ConfirmationOnDelete.aspx в папке EditInsertDelete и привяжите его к новому элементу ObjectDataSource, который будет извлекать сведения о продукте посредством метода ProductsBLL класса GetProducts(). Кроме того, настройте ObjectDataSource, чтобы ProductsBLL метод класса DeleteProduct(productID) сопоставляется с методом ObjectDataSource Delete() ; убедитесь, что раскрывающиеся списки вкладок INSERT и UPDATE заданы в значение (None). Наконец, установите флажок "Включить разбиение по страницам" в смарт-теге 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) из события onclick кнопки удаления Client-Side

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

После этого изменения декларативный синтаксис Delete 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

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

Замечание

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

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

После внесения этих изменений декларативная разметка 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, к которому можно получить доступ программным способом из обработчика событий GridView RowDataBound . После того как сделана ссылка, мы можем задать его 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 перед кнопкой "Удалить": кнопка "Изменить" и элемент управления "ЛитералКонтрол", который используется для добавления пробела между кнопками "Изменить" и "Удалить".

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

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

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

Замечание

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

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

Рис. 4. Нажатие кнопки "Удалить GridView" отображает диалоговое окно "Настраиваемое подтверждение" (щелкните, чтобы просмотреть изображение полного размера)

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

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

Альтернативный подход — преобразовать CommandFields в GridView и DetailsView в TemplateFields. Это приведет к формированию TemplateField с элементом ItemTemplate, содержащим для каждой кнопки в CommandField LinkButton (или Button, или ImageButton). Эти свойства кнопок 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) может быть связана с обработчиком событий клиента элемента управления Button Web с помощью свойства onclick элемента управления. При работе с кнопкой "Удалить" в шаблоне ( в одном из шаблонов FormView или в TemplateField в DetailsView или GridView) это свойство можно задать как декларативно, так и программным способом, как мы видели в этом руководстве.

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

Сведения о авторе

Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С ним можно связаться по адресу mitchell@4GuysFromRolla.com.