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


Обзор событий, связанных со вставкой, обновлением и удалением (VB)

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

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

В этом руководстве мы рассмотрим события, возникающие до, во время и после операции вставки, обновления или удаления веб-элемента управления ASP.NET данных. Мы также увидим, как настроить интерфейс редактирования только для обновления подмножества полей продукта.

Введение

При использовании встроенных функций вставки, редактирования или удаления функций элементов управления GridView, DetailsView или FormView выполняется ряд шагов, когда конечный пользователь завершает процесс добавления новой записи или обновления или удаления существующей записи. Как описано в предыдущем руководстве, когда строка редактируется в GridView, кнопка "Изменить" заменяется кнопкой "Обновить" и "Отмена" и "BoundFields" превращается в TextBoxes. После обновления данных и нажатия кнопки "Обновить" конечный пользователь выполняет следующие действия при обратной отправке:

  1. GridView заполняет его ОбъектDataSource UpdateParameters уникальными полями идентификации измененной записи (через DataKeyNames свойство) вместе со значениями, введенными пользователем.
  2. GridView вызывает метод ObjectDataSource Update() , который, в свою очередь, вызывает соответствующий метод в базовом объекте (ProductsDAL.UpdateProductв предыдущем руководстве).
  3. Базовые данные, которые теперь включают обновленные изменения, отскок в GridView

Во время этой последовательности действий выполняется несколько событий, что позволяет создавать обработчики событий, чтобы добавить пользовательскую логику по мере необходимости. Например, до шага 1 событие GridView RowUpdating запускается. На этом этапе можно отменить запрос на обновление, если возникла ошибка проверки. Update() При вызове метода событие ObjectDataSource Updating запускается, предоставляя возможность добавлять или настраивать значения любого из элементовUpdateParameters. После завершения выполнения метода базового объекта ObjectDataSource вызывается событие ObjectDataSource Updated . Обработчик событий для Updated события может проверить сведения об операции обновления, например количество затронутых строк и наличие исключения. Наконец, после шага 2 событие GridView RowUpdated запускается; обработчик событий для этого события может изучить дополнительные сведения об операции обновления, выполняемой только что.

На рисунке 1 показана эта серия событий и шагов при обновлении GridView. Шаблон события на рис. 1 не является уникальным для обновления с помощью GridView. Вставка, обновление или удаление данных из GridView, DetailsView или FormView создает одинаковую последовательность событий предварительного и последующего уровня для веб-элемента управления данными и ObjectDataSource.

Серия событий предварительного и последующего выполнения при обновлении данных в GridView

Рис. 1. Ряд событий до и после событий при обновлении данных в GridView (щелкните, чтобы просмотреть полноразмерное изображение)

В этом руководстве мы рассмотрим использование этих событий для расширения встроенных возможностей вставки, обновления и удаления возможностей веб-элементов управления ASP.NET данных. Мы также увидим, как настроить интерфейс редактирования только для обновления подмножества полей продукта.

Шаг 1. Обновление полей иUnitPriceпродуктовProductName

В интерфейсы редактирования из предыдущего руководства должны быть включены все поля продукта, которые не были доступны только для чтения. Если бы мы удалили поле из GridView , скажем QuantityPerUnit , при обновлении данных веб-элемент управления данными не будет задавать значение ObjectDataSource QuantityPerUnit UpdateParameters . ОбъектDataSource затем передает значение Nothing UpdateProduct в метод уровня бизнес-логики (BLL), который изменит столбец измененной записи QuantityPerUnit базы данных на NULL значение. Аналогичным образом, если необходимое поле, например ProductName, удаляется из интерфейса редактирования, обновление завершится ошибкой с исключением "Имя_продукта" не допускает значение NULL. Причина этого поведения заключается в том, что ОбъектDataSource был настроен для вызова ProductsBLL метода класса UpdateProduct , который ожидал входной параметр для каждого поля продукта. Поэтому коллекция ObjectDataSource UpdateParameters содержит параметр для каждого входного параметра метода.

Если требуется предоставить веб-элемент управления данными, позволяющий пользователю обновлять только подмножество полей, необходимо либо программно задать отсутствующие UpdateParameters значения в обработчике событий ObjectDataSource Updating , либо создать и вызвать метод BLL, который ожидает только подмножество полей. Давайте рассмотрим этот последний подход.

В частности, давайте создадим страницу, отображающую только ProductName поля в UnitPrice редактируемом GridView. Этот интерфейс редактирования GridView позволяет пользователю обновлять два отображаемых поля ProductName и UnitPrice. Так как этот интерфейс редактирования предоставляет только подмножество полей продукта, необходимо создать ObjectDataSource, который использует существующий метод BLL UpdateProduct и имеет отсутствующие значения поля продукта, заданные программным способом в обработчике Updating событий, или необходимо создать новый метод BLL, который ожидает только подмножество полей, определенных в GridView. В этом руководстве мы используем последний параметр и создадим перегрузку UpdateProduct метода, которая принимает только три входных параметра: productName, unitPriceи productID:

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Update, False)> _
    Public Function UpdateProduct(productName As String, _
        unitPrice As Nullable(Of Decimal), productID As Integer) _
        As Boolean

    Dim products As Northwind.ProductsDataTable = _
        Adapter.GetProductByProductID(productID)

    If products.Count = 0 Then
        Return False
    End If

    Dim product As Northwind.ProductsRow = products(0)

    product.ProductName = productName
    If Not unitPrice.HasValue Then
        product.SetUnitPriceNull()
    Else
        product.UnitPrice = unitPrice.Value
    End If

    Dim rowsAffected As Integer = Adapter.Update(product)

    Return rowsAffected = 1
End Function

Как и исходный UpdateProduct метод, эта перегрузка начинается с проверки наличия продукта в базе данных с указанным ProductID. В противном случае возвращается Falseсообщение, указывающее, что запрос на обновление сведений о продукте завершился ошибкой. В противном случае он обновляет существующие записи ProductName продукта и UnitPrice поля соответствующим образом и фиксирует обновление путем вызова метода TableAdapter Update() , передавая экземпляр ProductsRow .

С помощью этого дополнения к нашему ProductsBLL классу мы готовы создать упрощенный интерфейс GridView. DataModificationEvents.aspx Откройте папку EditInsertDelete и добавьте GridView на страницу. Создайте объект ObjectDataSource и настройте его для использования ProductsBLL класса с Select() сопоставлением GetProducts методов и сопоставлением его Update() методов с UpdateProduct перегрузкой, которая принимает только unitPriceproductNameвходные параметры и productID параметры ввода. На рисунке 2 показан мастер создания источника данных при сопоставлении метода ObjectDataSource Update() с ProductsBLL перегрузкой нового UpdateProduct метода класса.

Сопоставление метода UpdateSource ObjectDataSource с перегрузкой New UpdateProduct

Рис. 2. Сопоставление метода ObjectDataSource Update() с новой UpdateProduct перегрузкой (щелкните, чтобы просмотреть изображение полного размера)

Так как в нашем примере изначально потребуется только возможность изменять данные, но не вставлять или удалять записи, используйте момент, чтобы явно указать, что методы ObjectDataSource Insert() и методы не должны быть сопоставлены ни с какими из ProductsBLL методов класса, перейдя на вкладки INSERT и Delete() DELETE и выбрав (Нет) из раскрывающегося списка.

Выберите (нет) В раскрывающемся списке для вкладок INSERT и DELETE

Рис. 3. Выберите (нет) В раскрывающемся списке для вкладок INSERT и DELETE (щелкните, чтобы просмотреть изображение полного размера)

После завершения работы мастера установите флажок "Включить редактирование" из смарт-тега GridView.

После завершения мастера создания источника данных и привязки к GridView Visual Studio создал декларативный синтаксис для обоих элементов управления. Перейдите в представление источника, чтобы проверить декларативную разметку ObjectDataSource, которая показана ниже:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts"
    TypeName="ProductsBLL" UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Так как для методов и методов ObjectDataSource Insert() нет сопоставлений, InsertParameters нет или DeleteParameters разделов.Delete() Кроме того, так как Update() метод сопоставляется с UpdateProduct перегрузкой метода, которая принимает только три входных параметра, раздел UpdateParameters имеет всего три Parameter экземпляра.

Обратите внимание, что для свойства ObjectDataSource OldValuesParameterFormatString задано значение original_{0}. Это свойство устанавливается автоматически Visual Studio при использовании мастера настройки источника данных. Однако, так как наши методы BLL не ожидают передачи исходного ProductID значения, удалите это назначение свойства полностью из декларативного синтаксиса ObjectDataSource.

Примечание.

Если вы просто удалите OldValuesParameterFormatString значение свойства из окно свойств в представлении конструктора, свойство по-прежнему будет существовать в декларативном синтаксисе, но будет задано пустой строкой. Удалите свойство полностью из декларативного синтаксиса или из окно свойств задайте значение по умолчанию{0}.

Хотя объект ObjectDataSource имеет UpdateParameters только имя, цену и идентификатор продукта, Visual Studio добавил BoundField или CheckBoxField в GridView для каждого поля продукта.

GridView содержит boundField или CheckBoxField для каждого поля продукта

Рис. 4. GridView содержит BoundField или CheckBoxField для каждого поля продукта (щелкните, чтобы просмотреть изображение полного размера)

Когда конечный пользователь редактирует продукт и нажимает кнопку "Обновить", GridView перечисляет те поля, которые не были доступны только для чтения. Затем он задает значение соответствующего параметра в коллекции ObjectDataSource UpdateParameters значением, введенным пользователем. Если нет соответствующего параметра, GridView добавляет его в коллекцию. Таким образом, если gridView содержит BoundFields и CheckBoxFields для всех полей продукта, ОбъектDataSource в конечном итоге вызовет UpdateProduct перегрузку, которая принимает во всех этих параметрах, несмотря на то, что декларативная разметка ObjectDataSource указывает только три входных параметра (см. рис. 5). Аналогичным образом, если в GridView есть некоторое сочетание полей продуктов, не доступных только для чтения, в GridView, которые не соответствуют входным параметрам перегрузки UpdateProduct , при попытке обновления будет возникать исключение.

GridView добавит параметры в коллекцию UpdateParameters objectDataSource

Рис. 5. GridView добавит параметры в коллекцию ObjectDataSource UpdateParameters (щелкните, чтобы просмотреть изображение полного размера)

Чтобы объект ObjectDataSource вызвал UpdateProduct перегрузку, которая принимает только имя, цену и идентификатор продукта, необходимо ограничить GridView редактируемыми полями только для ProductName этого.UnitPrice Это можно сделать, удалив другие boundFields и CheckBoxFields, задав для этих полей значение свойства Trueдругих полей ReadOnly или по какой-либо комбинации двух. В этом руководстве мы просто удалим все поля GridView, кроме ProductName UnitPrice полей BoundFields, после чего декларативная разметка GridView будет выглядеть следующим образом:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>

Несмотря на то, что перегрузка UpdateProduct ожидает три входных параметра, у нас есть только два BoundFields в GridView. Это связано с тем, что productID входной параметр является значением первичного DataKeyNames ключа и передается через значение свойства для измененной строки.

Наш GridView вместе с UpdateProduct перегрузкой позволяет пользователю изменять только имя и цену продукта, не теряя ни одного из других полей продукта.

Интерфейс позволяет изменять только имя и цену продукта

Рис. 6. Интерфейс позволяет редактировать только имя и цену продукта (щелкните, чтобы просмотреть изображение полного размера)

Примечание.

Как описано в предыдущем руководстве, важно включить состояние представления GridView (поведение по умолчанию). Если для свойства falseGridView EnableViewState задано значение, возникает риск того, что одновременные пользователи непреднамеренно удаляют или редактируют записи.

UnitPriceУлучшение форматирования

Хотя пример GridView, показанный на рисунке 6, UnitPrice поле не отформатировано вообще, что приводит к отображению цены, в котором отсутствуют символы валюты и имеет четыре десятичных разряда. Чтобы применить форматирование валют для нередактируемых строк, просто задайте UnitPrice для свойства BoundField DataFormatString значение {0:c} и его HtmlEncode свойство False.

Задайте свойства DataFormatString и HtmlEncode в UnitPrice соответствующим образом

Рис. 7. Задание UnitPriceпараметров DataFormatString и HtmlEncode свойств соответственно (щелкните, чтобы просмотреть изображение полного размера)

При этом изменении строки, не редактируемые, форматируют цену как валюту; Измененная строка, однако, по-прежнему отображает значение без символа валюты и с четырьмя десятичными знаками.

Строки, не редактируемые, теперь форматируются в виде значений валюты

Рис. 8. Строки, не редактируемые, теперь форматируются как значения валют (щелкните, чтобы просмотреть изображение полного размера)

Инструкции по форматированию, указанные в DataFormatString свойстве, можно применить к интерфейсу редактирования, задав для свойства BoundField ApplyFormatInEditMode значение True (значение по умолчанию False). Укажите для этого свойства Trueнекоторое время.

Задайте для свойства ApplyFormatInEditMode свойство UnitPrice BoundField значение True

Рис. 9. Задайте UnitPrice для свойства BoundField ApplyFormatInEditMode значение True (щелкните, чтобы просмотреть изображение полного размера)

При этом изменении значение UnitPrice отображаемой в редактируемой строке также форматируется как валюта.

Снимок экрана: GridView с измененным значением UnitPrice строки, отформатированным в виде валюты.

Рис. 10. Значение измененной строки UnitPrice теперь отформатировано как валюта (щелкните, чтобы просмотреть изображение полного размера)

Однако обновление продукта с символом валюты в текстовом поле, например $19,00, вызывает FormatExceptionисключение. Когда GridView пытается назначить пользовательские значения коллекции ObjectDataSource UpdateParameters , не удается преобразовать UnitPrice строку "$19.00" в Decimal необходимый параметр (см. рис. 11). Чтобы устранить эту проблему, можно создать обработчик событий для события GridView RowUpdating и проанализировать предоставленный пользователем UnitPrice код в формате Decimalвалюты.

Событие GridView принимает в качестве второго параметра объект типа GridViewUpdateEventArgsRowUpdating, который включает NewValues словарь в качестве одного из его свойств, содержащих предоставленные пользователем значения, готовые к назначению коллекции ObjectDataSourceUpdateParameters. Можно перезаписать существующее UnitPrice значение в NewValues коллекции с десятичным значением, проанализированным с помощью формата валюты со следующими строками кода в обработчике RowUpdating событий:

Protected Sub GridView1_RowUpdating(sender As Object, e As GridViewUpdateEventArgs) _
    Handles GridView1.RowUpdating
    If e.NewValues("UnitPrice") IsNot Nothing Then
        e.NewValues("UnitPrice") = _
            Decimal.Parse(e.NewValues("UnitPrice").ToString(), _
                System.Globalization.NumberStyles.Currency)
    End If
End Sub

Если пользователь предоставил UnitPrice значение (например, $19,00), это значение перезаписывается с десятичным значением, вычисляемым с помощью Decimal.Parse, анализ значения в виде валюты. Это правильно анализирует десятичное значение в случае любых символов валют, запятых, десятичных точек и т. д., а также использует перечисление NumberStyles в пространстве имен System.Globalization .

На рисунке 11 показана проблема, вызванная символами валют в предоставленном UnitPriceпользователем, а также способ использования обработчика событий GridView RowUpdating для правильного анализа таких входных данных.

Схема, показывающая, как ObjectDataSource обрабатывает поле UnitPrice и как обработчик событий RowUpdate GridView преобразует строку в десятичное значение.

Рис. 11. Значение измененной строки UnitPrice теперь отформатировано как валюта (щелкните, чтобы просмотреть изображение полного размера)

Шаг 2. ЗапретNULL UnitPrices

Хотя база данных настроена для разрешения NULL значений в Products столбце таблицы UnitPrice , может потребоваться запретить пользователям посещать эту конкретную NULL UnitPrice страницу. То есть, если пользователь не может ввести UnitPrice значение при редактировании строки продукта, а не сохранить результаты в базе данных, которую мы хотим отобразить сообщение, информирующее пользователя о том, что на этой странице все измененные продукты должны иметь указанную цену.

Объект GridViewUpdateEventArgs , переданный в обработчик событий GridView RowUpdating , содержит Cancel свойство, которое, если задано True, завершает процесс обновления. Давайте расширим RowUpdating обработчик событий, чтобы задать True e.Cancel и отобразить сообщение, объясняющее, почему UnitPrice значение в NewValues коллекции имеет значениеNothing.

Начните с добавления веб-элемента управления Label На страницу с именем MustProvideUnitPriceMessage. Этот элемент управления Label будет отображаться, если пользователь не может указать UnitPrice значение при обновлении продукта. Задайте свойству Label Text значение "Необходимо указать цену для продукта". Я также создал новый класс CSS с Styles.css именем Warning со следующим определением:

.Warning
{
    color: Red;
    font-style: italic;
    font-weight: bold;
    font-size: x-large;
}

Наконец, задайте для свойства Label CssClass значение Warning. На этом этапе конструктор должен отображать предупреждение в красном, полужирном, курсивном, дополнительном большом размере шрифта над GridView, как показано на рисунке 12.

Метка добавлена над GridView

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

По умолчанию эта метка должна быть скрыта, поэтому задайте его Visible свойство False в обработчике Page_Load событий:

Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    MustProvideUnitPriceMessage.Visible = False
End Sub

Если пользователь пытается обновить продукт без указания UnitPrice, мы хотим отменить обновление и отобразить метку предупреждения. Расширение обработчика событий GridView RowUpdating следующим образом:

Protected Sub GridView1_RowUpdating(sender As Object, e As GridViewUpdateEventArgs) _
    Handles GridView1.RowUpdating

    If e.NewValues("UnitPrice") IsNot Nothing Then
        e.NewValues("UnitPrice") = _
            Decimal.Parse(e.NewValues("UnitPrice").ToString(), _
                System.Globalization.NumberStyles.Currency)
    Else
        MustProvideUnitPriceMessage.Visible = True

        e.Cancel = True
    End If
End Sub

Если пользователь пытается сохранить продукт без указания цены, обновление отменяется и отображается полезное сообщение. Хотя база данных (и бизнес-логика) допускает s NULL UnitPrice , эта конкретная страница ASP.NET не поддерживается.

Пользователь не может оставить unitPrice пустым

Рис. 13. Пользователь не может оставить UnitPrice пустым (щелкните, чтобы просмотреть изображение полного размера)

До сих пор мы видели, как использовать событие GridView RowUpdating для программного изменения значений параметров, назначенных коллекции ObjectDataSource UpdateParameters , а также как полностью отменить процесс обновления. Эти понятия переносятся в элементы управления DetailsView и FormView, а также применяются к вставке и удалению.

Эти задачи также можно выполнять на уровне ObjectDataSource с помощью обработчиков событий для его Insertingсобытий Updatingи Deleting событий. Эти события возникают перед вызовом связанного метода базового объекта и предоставляют последнюю возможность изменить коллекцию входных параметров или отменить операцию прямо. Обработчики событий для этих трех событий передают объект типа ObjectDataSourceMethodEventArgs , имеющий два свойства:

  • Отмена, которая, если задано True, отменяет выполняемую операцию.
  • InputParameters, который является коллекцией InsertParameters, или в зависимости от того, является ли обработчик событий для Insertingобъекта UpdateParameters, Updatingили DeleteParametersDeleting события

Чтобы проиллюстрировать работу со значениями параметров на уровне ObjectDataSource, давайте добавим detailsView на нашей странице, которая позволяет пользователям добавлять новый продукт. Этот элемент DetailsView будет использоваться для предоставления интерфейса для быстрого добавления нового продукта в базу данных. Чтобы сохранить согласованный пользовательский интерфейс при добавлении нового продукта, давайте разрешаем пользователю вводить только значения для ProductName полей и UnitPrice полей. По умолчанию эти значения, не предоставленные в интерфейсе вставки DetailsView, будут иметь NULL значение базы данных. Однако мы можем использовать событие ObjectDataSource Inserting для внедрения различных значений по умолчанию, как мы увидим в ближайшее время.

Шаг 3. Предоставление интерфейса для добавления новых продуктов

Перетащите DetailsView из панели элементов в конструктор над GridView, удалите его Height и Width свойства и привязите его к объекту ObjectDataSource, который уже присутствует на странице. Это добавит BoundField или CheckBoxField для каждого поля продукта. Так как мы хотим использовать этот DetailsView для добавления новых продуктов, необходимо проверить параметр "Включить вставку" из смарт-тега; Однако такой параметр отсутствует, так как метод ObjectDataSource Insert() не сопоставляется с методом в ProductsBLL классе (помните, что при настройке источника данных при настройке источника данных см. рис. 3).

Чтобы настроить ObjectDataSource, выберите ссылку "Настройка источника данных" из смарт-тега, запустите мастер. Первый экран позволяет изменить базовый объект, к которым привязан ОбъектDataSource; оставьте для него значение ProductsBLL. На следующем экране перечислены сопоставления методов ObjectDataSource с базовым объектом. Несмотря на то, что мы явно указали, что методы Delete() не должны быть сопоставлены с любыми методами, если перейти на вкладки INSERT и DELETE, вы увидите, что Insert() сопоставление существует. Это связано с тем, что ProductsBLLAddProduct методы и DeleteProduct методы используют DataObjectMethodAttribute атрибут, чтобы указать, что они являются методами по умолчанию для Insert() и Delete()соответственно. Поэтому мастер ObjectDataSource выбирает их при каждом запуске мастера, если не указано другое значение явно.

Insert() Оставьте метод, указывающий на AddProduct метод, но снова задайте раскрывающийся список вкладки DELETE (Нет).

Задайте раскрывающийся список вкладки INSERT в метод AddProduct

Рис. 14. Задайте раскрывающийся список вкладок INSERT (AddProductщелкните, чтобы просмотреть изображение полного размера)

Задайте раскрывающийся список вкладки DELETE (Нет)

Рис. 15. Задайте раскрывающийся список вкладки DELETE (Нет) (Щелкните, чтобы просмотреть изображение полного размера)

После внесения этих изменений декларативный синтаксис ObjectDataSource будет развернут для включения InsertParameters коллекции, как показано ниже:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    SelectMethod="GetProducts" TypeName="ProductsBLL"
    UpdateMethod="UpdateProduct" OnUpdating="ObjectDataSource1_Updating"
    InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
    <InsertParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="supplierID" Type="Int32" />
        <asp:Parameter Name="categoryID" Type="Int32" />
        <asp:Parameter Name="quantityPerUnit" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="unitsInStock" Type="Int16" />
        <asp:Parameter Name="unitsOnOrder" Type="Int16" />
        <asp:Parameter Name="reorderLevel" Type="Int16" />
        <asp:Parameter Name="discontinued" Type="Boolean" />
    </InsertParameters>
</asp:ObjectDataSource>

Повторное выполнение мастера добавило OldValuesParameterFormatString свойство. Чтобы очистить это свойство, задав его значение по умолчанию ({0}) или удалив его полностью из декларативного синтаксиса.

При использовании ObjectDataSource, предоставляющего возможности вставки, смарт-тег DetailsView теперь будет включать флажок "Включить вставку"; вернитесь в конструктор и проверьте этот параметр. Затем выполните синтаксический анализ detailsView, чтобы он имеет только два BoundFields - ProductName и - и UnitPrice CommandField. На этом этапе декларативный синтаксис DetailsView должен выглядеть следующим образом:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
        <asp:CommandField ShowInsertButton="True" />
    </Fields>
</asp:DetailsView>

На рисунке 16 показана эта страница при просмотре через браузер на этом этапе. Как вы видите, DetailsView перечисляет имя и цену первого продукта (Chai). Однако мы хотим, чтобы интерфейс вставки предоставлял пользователю возможность быстро добавлять новый продукт в базу данных.

Представление DetailsView в настоящее время отрисовывается в режиме только для чтения

Рис. 16. Представление DetailsView в настоящее время отрисовывается в режиме только для чтения (щелкните, чтобы просмотреть изображение полного размера)

Чтобы отобразить DetailsView в его режиме вставки, необходимо задать DefaultMode для свойства Insertingзначение . Это отрисовывает DetailsView в режиме вставки при первом посещении и сохраняет его после вставки новой записи. Как показано на рисунке 17, такой объект DetailsView предоставляет быстрый интерфейс для добавления новой записи.

DetailsView предоставляет интерфейс для быстрого добавления нового продукта

Рис. 17. DetailsView предоставляет интерфейс для быстрого добавления нового продукта (щелкните, чтобы просмотреть изображение полного размера)

Когда пользователь вводит имя продукта и цену (например, Acme Water и 1.99, как на рис. 17) и щелкает "Вставка", обратная обратная связь начинается, и начинается вставка рабочего процесса, кульминацией которого станет новая запись продукта, добавляемая в базу данных. DetailsView сохраняет свой интерфейс вставки, и GridView автоматически возвращается к источнику данных, чтобы включить новый продукт, как показано на рис. 18.

Продукт

Рис. 18. Продукт Acme Water добавлен в базу данных

Хотя GridView на рис. 18 не отображает его, поля продукта, отсутствующие в интерфейсе CategoryIDDetailsView, SupplierIDQuantityPerUnitи т. д., назначаются NULL значения базы данных. Это можно увидеть, выполнив следующие действия.

  1. Перейдите в обозреватель серверов в Visual Studio
  2. Расширение NORTHWND.MDF узла базы данных
  3. Щелкните правой Products кнопкой мыши узел таблицы базы данных
  4. Выбор "Показать данные таблицы"

В этом списке Products будут перечислены все записи в таблице. Как показано на рисунке 19, все столбцы нового продукта, отличные от ProductID, ProductNameи UnitPrice имеют NULL значения.

Поля продукта, не указанные в DetailsView, присваиваются значения NULL

Рис. 19. Поля продукта, не предоставленные в DetailsView, назначаются NULL значения (щелкните, чтобы просмотреть изображение полного размера)

Возможно, мы хотим указать значение по умолчанию, отличное NULL от одного или нескольких из этих значений столбцов, так как не является лучшим параметром по умолчанию или поскольку NULL сам столбец базы данных не разрешает NULL . Для этого можно программно задать значения параметров коллекции DetailsView InputParameters . Это назначение можно сделать в обработчике событий для события DetailsView ItemInserting или события ObjectDataSource Inserting . Так как мы уже рассмотрели использование событий предварительного и постуровневого уровня на уровне веб-элемента управления данными, давайте рассмотрим события ObjectDataSource на этот раз.

Шаг 4. Назначение значенийCategoryIDиSupplierIDпараметров

В этом руководстве мы предположим, что для нашего приложения при добавлении нового продукта через этот интерфейс он должен быть назначен CategoryID и SupplierID значение 1. Как упоминалось ранее, объект ObjectDataSource имеет пару событий предварительного и последующего уровня, которые запускаются во время процесса изменения данных. При вызове метода Insert() объект ObjectDataSource сначала вызывает его Inserting событие, а затем вызывает метод, с которым был сопоставлен его Insert() метод, и, наконец, вызывает Inserted событие. Обработчик Inserting событий предоставляет нам одну последнюю возможность настроить входные параметры или отменить операцию прямо.

Примечание.

В реальном приложении вы, скорее всего, хотите разрешить пользователю указать категорию и поставщика или выбрать для них это значение на основе некоторых критериев или бизнес-логики (а не слепо выбирать идентификатор 1). Независимо от этого, в примере показано, как программно задать значение входного параметра из предварительного события ObjectDataSource.

Создайте обработчик событий для события ObjectDataSource Inserting . Обратите внимание, что второй входной параметр обработчика событий является объектом типа ObjectDataSourceMethodEventArgs, который имеет свойство для доступа к коллекции параметров (InputParameters) и свойству для отмены операции (Cancel).

Protected Sub ObjectDataSource1_Inserting _
    (sender As Object, e As ObjectDataSourceMethodEventArgs) _
    Handles ObjectDataSource1.Inserting

End Sub

На этом этапе InputParameters свойство содержит коллекцию ObjectDataSource InsertParameters со значениями, назначенными в DetailsView. Чтобы изменить значение одного из этих параметров, просто используйте: e.InputParameters("paramName") = value Таким образом, чтобы задать CategoryID значения и SupplierID значения 1, настройте Inserting обработчик событий следующим образом:

Protected Sub ObjectDataSource1_Inserting _
    (sender As Object, e As ObjectDataSourceMethodEventArgs) _
    Handles ObjectDataSource1.Inserting

    e.InputParameters("CategoryID") = 1
    e.InputParameters("SupplierID") = 1
End Sub

На этот раз при добавлении нового продукта (например, Acme Soda), CategoryID для столбцов SupplierID нового продукта задано значение 1 (см. рис. 20).

Новые продукты теперь имеют значения CategoryID и SupplierID, равные 1

Рис. 20. Теперь новые продукты имеют значение CategoryID SupplierID 1 (щелкните, чтобы просмотреть изображение полного размера)

Итоги

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

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

Об авторе

Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Сэмс Учит себя ASP.NET 2.0 в 24 часах. Он может быть достигнут в mitchell@4GuysFromRolla.com. или через его блог, который можно найти на http://ScottOnWriting.NET.

Особое спасибо

Эта серия учебников была проверена многими полезными рецензентами. Ведущие рецензенты для этого руководства были Джеки Гоор и Лиз Шулок. Хотите просмотреть мои предстоящие статьи MSDN? Если да, упадите меня линию в mitchell@4GuysFromRolla.com.