Udostępnij za pośrednictwem


Badanie zdarzeń powiązanych ze wstawianiem, aktualizowaniem i usuwaniem (VB)

Autor: Scott Mitchell

Pobierz plik PDF

W tym samouczku sprawdzimy użycie zdarzeń występujących przed, podczas i po operacji wstawiania, aktualizowania lub usuwania kontrolki sieci Web danych ASP.NET. Zobaczymy również, jak dostosować interfejs edycji, aby zaktualizować tylko podzestaw pól produktu.

Wprowadzenie

W przypadku korzystania z wbudowanych funkcji wstawiania, edytowania lub usuwania funkcji kontrolek GridView, DetailsView lub FormView użytkownik końcowy ukończy proces dodawania nowego rekordu lub aktualizowania lub usuwania istniejącego rekordu. Jak opisano w poprzednim samouczku, gdy wiersz jest edytowany w siatce, przycisk Edytuj jest zastępowany przez przyciski Aktualizuj i Anuluj, a pola BoundFields zamieniają się w Pola tekstowe. Po zaktualizowaniu danych przez użytkownika końcowego i kliknięciu przycisku Aktualizuj następujące kroki są wykonywane po wystąpieniu zwrotnym:

  1. Obiekt GridView wypełnia obiekty ObjectDataSource UpdateParameters unikatowymi polami identyfikacji edytowanego rekordu (za pośrednictwem DataKeyNames właściwości) oraz wartościami wprowadzonymi przez użytkownika
  2. Obiekt GridView wywołuje metodę ObjectDataSource Update() , która z kolei wywołuje odpowiednią metodę w obiekcie bazowym (ProductsDAL.UpdateProductw poprzednim samouczku)
  3. Dane bazowe, które zawierają teraz zaktualizowane zmiany, są przywracane do kontrolki GridView

Podczas tej sekwencji kroków uruchamiana jest wiele zdarzeń, co umożliwia tworzenie procedur obsługi zdarzeń w celu dodania niestandardowej logiki tam, gdzie jest to konieczne. Na przykład przed krokiem 1 zdarzenie GridView RowUpdating jest uruchamiane. W tym momencie możemy anulować żądanie aktualizacji, jeśli wystąpił błąd weryfikacji. Po wywołaniu Update() metody zdarzenie ObjectDataSource Updating jest wyzwalane, co daje możliwość dodania lub dostosowania wartości dowolnego elementu UpdateParameters. Po zakończeniu wykonywania metody obiektu bazowego obiektu ObjectDataSource zostanie zgłoszone zdarzenie ObjectDataSource Updated . Procedura obsługi zdarzeń dla Updated zdarzenia może sprawdzić szczegóły operacji aktualizacji, takie jak liczba wierszy, których dotyczy problem i czy wystąpił wyjątek. Na koniec po wykonaniu kroku 2 zdarzenie GridView RowUpdated zostanie wyzwolony. Program obsługi zdarzeń dla tego zdarzenia może zbadać dodatkowe informacje o właśnie wykonanej operacji aktualizacji.

Rysunek 1 przedstawia tę serię zdarzeń i kroków podczas aktualizowania kontrolki GridView. Wzorzec zdarzenia na rysunku 1 nie jest unikatowy do aktualizowania za pomocą kontrolki GridView. Wstawianie, aktualizowanie lub usuwanie danych z kontrolki GridView, DetailsView lub FormView powoduje utworzenie tej samej sekwencji zdarzeń wstępnych i po poziomie zarówno dla kontrolki sieci Web danych, jak i obiektu ObjectDataSource.

Seria zdarzeń wstępnych i po zdarzeń jest uruchamiana podczas aktualizowania danych w elementy GridView

Rysunek 1. Seria uruchomień przed zdarzeniami podczas aktualizowania danych w siatce (kliknij, aby wyświetlić obraz pełnowymiarowy)

W tym samouczku przeanalizujemy użycie tych zdarzeń, aby rozszerzyć wbudowane funkcje wstawiania, aktualizowania i usuwania kontrolek sieci Web ASP.NET danych. Zobaczymy również, jak dostosować interfejs edycji, aby zaktualizować tylko podzestaw pól produktu.

Krok 1. Aktualizowanie pól iUnitPriceproduktówProductName

W interfejsach edycji z poprzedniego samouczka wszystkie pola produktu, które nie były tylko do odczytu, musiały zostać uwzględnione. Gdybyśmy usunęli pole z kontrolki GridView — powiedzmy QuantityPerUnit — podczas aktualizowania danych kontrolka internetowa danych nie ustawiłaby wartości ObjectDataSource QuantityPerUnit UpdateParameters . Następnie obiekt ObjectDataSource przekaże wartość Nothing do UpdateProduct metody warstwy logiki biznesowej (BLL), co spowoduje zmianę NULL kolumny QuantityPerUnit edytowanego rekordu bazy danych na wartość. Podobnie, jeśli wymagane pole, takie jak ProductName, zostanie usunięte z interfejsu edycji, aktualizacja zakończy się niepowodzeniem z wyjątkiem "Kolumna "ProductName" nie zezwala na wartości null. Przyczyną tego zachowania było to, że obiekt ObjectDataSource został skonfigurowany do wywołania ProductsBLL metody klasy UpdateProduct , która oczekiwała parametru wejściowego dla każdego pola produktu. W związku z tym kolekcja ObjectDataSource UpdateParameters zawierała parametr dla każdego z parametrów wejściowych metody.

Jeśli chcemy podać kontrolkę sieci Web danych, która umożliwia użytkownikowi końcowemu aktualizowanie tylko podzestawu pól, musimy programowo ustawić brakujące UpdateParameters wartości w procedurze obsługi zdarzeń obiektu ObjectDataSource Updating lub utworzyć i wywołać metodę BLL, która oczekuje tylko podzestawu pól. Przyjrzyjmy się temu drugiemu podejściu.

W szczególności utwórzmy stronę wyświetlającą tylko ProductName pola i UnitPrice w edytowalnym widoku GridView. Interfejs edycji kontrolki GridView umożliwi użytkownikowi tylko zaktualizowanie dwóch wyświetlanych pól i ProductName UnitPrice. Ponieważ ten interfejs edycji zawiera tylko podzbiór pól produktu, musimy utworzyć obiekt ObjectDataSource, który używa istniejącej metody BLL i ma brakujące wartości pól produktu ustawione programowo w procedurze Updating obsługi zdarzeń, lub musimy utworzyć nową metodę BLLUpdateProduct, która oczekuje tylko podzestawu pól zdefiniowanych w siatce. W tym samouczku użyjemy tej drugiej opcji i utworzymy przeciążenie UpdateProduct metody , która przyjmuje tylko trzy parametry wejściowe: productName, unitPricei 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

Podobnie jak w przypadku oryginalnej UpdateProduct metody, to przeciążenie rozpoczyna się od sprawdzenia, czy w bazie danych znajduje się produkt z określonym ProductIDelementem . Jeśli nie, zwraca Falsewartość , wskazując, że żądanie zaktualizowania informacji o produkcie nie powiodło się. W przeciwnym razie aktualizuje odpowiednie pola i UnitPrice rekordy istniejącego produktu ProductName oraz zatwierdza aktualizację, wywołując metodę TableAdapterUpdate(), przekazując ProductsRow wystąpienie.

Z tym dodatkiem do naszej ProductsBLL klasy jesteśmy gotowi do utworzenia uproszczonego interfejsu GridView. Otwórz folder DataModificationEvents.aspx w folderze EditInsertDelete i dodaj element GridView do strony. Utwórz nowy obiekt ObjectDataSource i skonfiguruj go tak, aby korzystała z ProductsBLL klasy z mapowaniem Select() metody na GetProducts i mapowaniem Update() metody na UpdateProduct przeciążenie, które przyjmuje tylko productNameparametry , unitPricei productID wejściowe. Rysunek 2 przedstawia kreatora tworzenia źródła danych podczas mapowania metody ObjectDataSource Update() na ProductsBLL przeciążenie nowej UpdateProduct metody klasy.

Mapowanie metody Update() objectDataSource na przeciążenie new UpdateProduct

Rysunek 2. Mapowanie metody ObjectDataSource Update() na nowe UpdateProduct przeciążenie (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Ponieważ nasz przykład początkowo będzie potrzebować tylko możliwości edytowania danych, ale nie wstawiania lub usuwania rekordów, pośmiń chwilę, aby jawnie wskazać, że metody i Delete() objectDataSource Insert() nie powinny być mapowane na żadną ProductsBLL z metod klasy, przechodząc do kart INSERT i DELETE i wybierając pozycję (Brak) z listy rozwijanej.

Wybierz pozycję (Brak) Z listy rozwijanej kart INSERT i DELETE

Rysunek 3. Wybierz pozycję (Brak) Z listy rozwijanej kart INSERT i DELETE (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po ukończeniu pracy z tym kreatorem zaznacz pole wyboru Włącz edytowanie z tagu inteligentnego GridView.

Po zakończeniu pracy kreatora Tworzenia źródła danych i powiązaniu go z kontrolką GridView program Visual Studio utworzył składnię deklaratywną dla obu kontrolek. Przejdź do widoku Źródło, aby sprawdzić deklaratywne znaczniki objectDataSource, które przedstawiono poniżej:

<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>

Ponieważ nie ma mapowań metod i obiektów ObjectDataSourceInsert(), nie InsertParameters ma żadnych sekcji aniDeleteParameters.Delete() Ponadto, ponieważ Update() metoda jest mapowana na UpdateProduct przeciążenie metody, które akceptuje tylko trzy parametry wejściowe, UpdateParameters sekcja zawiera tylko trzy Parameter wystąpienia.

Należy pamiętać, że właściwość ObjectDataSource jest ustawiona OldValuesParameterFormatString na original_{0}wartość . Ta właściwość jest ustawiana automatycznie przez program Visual Studio podczas korzystania z Kreatora konfigurowania źródła danych. Jednak ponieważ nasze metody BLL nie oczekują przekazania oryginalnej ProductID wartości, usuń to przypisanie właściwości całkowicie ze składni deklaratywnej obiektu ObjectDataSource.

Uwaga

Jeśli po prostu wyczyścisz OldValuesParameterFormatString wartość właściwości z okno Właściwości w widoku Projekt, właściwość nadal będzie istnieć w składni deklaratywnej, ale zostanie ustawiona na pusty ciąg. Całkowicie usuń właściwość ze składni deklaratywnej lub z okno Właściwości ustaw wartość na wartość domyślną {0}.

Obiekt ObjectDataSource zawiera UpdateParameters tylko nazwę, cenę i identyfikator produktu, ale program Visual Studio dodał pole BoundField lub CheckBoxField w elementy GridView dla każdego pola produktu.

Kontrolka GridView zawiera pole powiązane lub pole wyboru dla każdego pola produktu

Rysunek 4. Obiekt GridView zawiera pole powiązane lub pole wyboru dla każdego pola produktu (kliknij, aby wyświetlić obraz pełnowymiarowy)

Gdy użytkownik końcowy edytuje produkt i klika przycisk Aktualizuj, funkcja GridView wylicza te pola, które nie były tylko do odczytu. Następnie ustawia wartość odpowiedniego parametru w kolekcji ObjectDataSource UpdateParameters na wartość wprowadzoną przez użytkownika. Jeśli nie ma odpowiedniego parametru, kontrolka GridView dodaje jeden do kolekcji. W związku z tym jeśli obiekt GridView zawiera pola BoundFields i CheckBoxFields dla wszystkich pól produktu, obiekt ObjectDataSource wywoła UpdateProduct przeciążenie, które przyjmuje wszystkie te parametry, pomimo faktu, że znacznik deklaratywny objectDataSource określa tylko trzy parametry wejściowe (patrz Rysunek 5). Podobnie, jeśli w siatce GridView istnieje kilka kombinacji pól produktów nie tylko do odczytu, które nie odpowiadają parametrom wejściowym UpdateProduct przeciążenia, podczas próby aktualizacji zostanie zgłoszony wyjątek.

Kontrolka GridView doda parametry do kolekcji UpdateParameters obiektu ObjectDataSource

Rysunek 5. Obiekt GridView doda parametry do kolekcji ObjectDataSource UpdateParameters (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Aby upewnić się, że obiekt ObjectDataSource wywołuje UpdateProduct przeciążenie, które przyjmuje tylko nazwę, cenę i identyfikator produktu, musimy ograniczyć element GridView do edytowania pól tylko dla ProductName elementów i UnitPrice. Można to osiągnąć, usuwając inne pola BoundFields i CheckBoxFields, ustawiając właściwość tych innych pól ReadOnly na True, lub przez kombinację tych dwóch pól. W tym samouczku po prostu usuńmy wszystkie pola GridView z wyjątkiem ProductName pól i UnitPrice BoundFields, po czym znacznik deklaratywny gridView będzie wyglądać następująco:

<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>

Mimo że UpdateProduct przeciążenie oczekuje trzech parametrów wejściowych, mamy tylko dwa pola BoundFields w siatce. Jest to spowodowane tym, że productID parametr wejściowy jest wartością klucza podstawowego i przekazywany przez wartość DataKeyNames właściwości dla edytowanego wiersza.

Nasz element GridView wraz z UpdateProduct przeciążeniem umożliwia użytkownikowi edytowanie tylko nazwy i ceny produktu bez utraty żadnego z innych pól produktu.

Interfejs umożliwia edytowanie tylko nazwy i ceny produktu

Rysunek 6. Interfejs umożliwia edytowanie tylko nazwy i ceny produktu (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Jak wspomniano w poprzednim samouczku, ważne jest, aby stan widoku GridView był włączony (zachowanie domyślne). Jeśli ustawisz właściwość GridView EnableViewState na falsewartość , wystąpi ryzyko przypadkowego usunięcia lub edytowania rekordów przez współbieżnych użytkowników.

UlepszanieUnitPriceformatowania

Chociaż przykład GridView pokazany na rysunku 6 działa, UnitPrice pole nie jest w ogóle sformatowane, co powoduje wyświetlenie ceny, która nie zawiera symboli waluty i ma cztery miejsca dziesiętne. Aby zastosować formatowanie waluty dla wierszy, które nie można edytować, po prostu ustaw UnitPrice właściwość BoundField DataFormatString na {0:c} i jej HtmlEncode właściwość na False.

Ustaw odpowiednio właściwości DataFormatString i HtmlEncode elementu UnitPrice

Rysunek 7. Ustawienie UnitPricewłaściwości DataFormatString i HtmlEncode właściwości odpowiednio (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Dzięki tej zmianie wiersze nieedytowalne formatuje cenę jako walutę; edytowany wiersz nadal wyświetla jednak wartość bez symbolu waluty i z czterema miejscami dziesiętnymi.

Nieedytowalne wiersze są teraz formatowane jako wartości waluty

Rysunek 8. Wiersze, które nie można edytować, są teraz sformatowane jako wartości waluty (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Instrukcje formatowania określone we DataFormatString właściwości można zastosować do interfejsu edycji, ustawiając właściwość BoundField ApplyFormatInEditMode na True wartość (wartość domyślna to False). Pośmiń chwilę, aby ustawić tę właściwość na True.

Ustaw właściwość ApplyFormatInEditMode właściwości UnitPrice BoundField na true

Rysunek 9. Ustaw UnitPrice właściwość BoundField ApplyFormatInEditMode na True (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Dzięki tej zmianie wartość UnitPrice wyświetlana w edytowanym wierszu jest również formatowana jako waluta.

Zrzut ekranu przedstawiający kontrolkę GridView z edytowaną wartością UnitPrice wiersza sformatowaną jako waluta.

Rysunek 10. Wartość edytowanego wiersza UnitPrice jest teraz sformatowana jako waluta (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jednak zaktualizowanie produktu za pomocą symbolu waluty w polu tekstowym, takiego jak 19,00 USD, zgłasza błąd FormatException. Gdy obiekt GridView próbuje przypisać wartości dostarczone przez użytkownika do kolekcji ObjectDataSource UpdateParameters , nie może przekonwertować UnitPrice ciągu "$19.00" na Decimal wymagany przez parametr (patrz Rysunek 11). Aby rozwiązać ten problem, możemy utworzyć procedurę obsługi zdarzeń dla zdarzenia GridView RowUpdating i przeanalizować użytkownika dostarczonego UnitPrice jako walutę sformatowaną Decimalprzez użytkownika .

Zdarzenie GridView RowUpdating przyjmuje jako drugi parametr obiektu typu GridViewUpdateEventArgs, który zawiera NewValues słownik jako jedną z jego właściwości, które zawierają wartości dostarczone przez użytkownika gotowe do przypisania do kolekcji ObjectDataSource UpdateParameters . Możemy zastąpić istniejącą UnitPrice wartość w NewValues kolekcji wartością dziesiętną przeanalizowaną przy użyciu formatu waluty z następującymi wierszami kodu w procedurze RowUpdating obsługi zdarzeń:

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

Jeśli użytkownik podał UnitPrice wartość (np. "$19.00"), ta wartość jest zastępowana wartością dziesiętną obliczoną przez wartość Dziesiętną.Parse, analizuje wartość jako walutę. Spowoduje to poprawne przeanalizowanie liczby dziesiętnej w przypadku wszelkich symboli walutowych, przecinków, punktów dziesiętnych itd. i używa wyliczenia NumberStyles w przestrzeni nazw System.Globalization .

Rysunek 11 przedstawia zarówno problem spowodowany symbolami walutowymi w podanym UnitPriceprzez użytkownika elememencie , jak również sposób, w jaki program obsługi zdarzeń gridView RowUpdating może być używany do poprawnego analizowania takich danych wejściowych.

Diagram przedstawiający sposób przetwarzania pola UnitPrice obiektu ObjectDataSource oraz sposobu, w jaki program obsługi zdarzeń RowUpdate obiektu GridView konwertuje ciąg na dziesiętny.

Rysunek 11. Wartość edytowanego wiersza UnitPrice jest teraz sformatowana jako waluta (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 2. ZakazNULL UnitPrices

Chociaż baza danych jest skonfigurowana tak, aby zezwalała na NULL wartości w Products kolumnie tabeli UnitPrice , możemy uniemożliwić użytkownikom odwiedzanie tej konkretnej strony przy określaniu NULL UnitPrice wartości. Oznacza to, że jeśli użytkownik nie wprowadzi UnitPrice wartości podczas edytowania wiersza produktu, zamiast zapisywać wyniki w bazie danych, chcemy wyświetlić komunikat informujący użytkownika, że za pośrednictwem tej strony wszystkie edytowane produkty muszą mieć określoną cenę.

Obiekt GridViewUpdateEventArgs przekazany do procedury obsługi zdarzeń kontrolki GridView RowUpdating zawiera Cancel właściwość, która, jeśli jest ustawiona na True, kończy proces aktualizowania. Rozszerzmy procedurę RowUpdating obsługi zdarzeń, aby ustawić wartość e.Cancel na True i wyświetlić komunikat wyjaśniający, dlaczego UnitPrice wartość w NewValues kolekcji ma wartość Nothing.

Zacznij od dodania kontrolki Etykieta sieci Web do strony o nazwie MustProvideUnitPriceMessage. Ta kontrolka Etykieta będzie wyświetlana, jeśli użytkownik nie określi UnitPrice wartości podczas aktualizowania produktu. Ustaw właściwość Label Text na "Musisz podać cenę produktu". Utworzono również nową klasę CSS o Styles.css nazwie o Warning następującej definicji:

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

Na koniec ustaw właściwość Etykieta CssClass na Warning. Na tym etapie Projektant powinien wyświetlić komunikat ostrzegawczy w kolorze czerwonym, pogrubionym, kursywą, dodatkowym dużym rozmiarem czcionki powyżej kontrolki GridView, jak pokazano na rysunku 12.

Etykieta została dodana powyżej kontrolki GridView

Rysunek 12. Etykieta została dodana powyżej kontrolki GridView (kliknij, aby wyświetlić obraz pełnowymiarowy)

Domyślnie ta etykieta powinna być ukryta, więc ustaw jej Visible właściwość na False w procedurze obsługi zdarzeń Page_Load :

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

Jeśli użytkownik próbuje zaktualizować produkt bez określenia UnitPriceelementu , chcemy anulować aktualizację i wyświetlić etykietę ostrzeżenia. Rozszerz procedurę obsługi zdarzeń usługi GridView RowUpdating w następujący sposób:

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

Jeśli użytkownik spróbuje zapisać produkt bez określenia ceny, aktualizacja zostanie anulowana i zostanie wyświetlony pomocny komunikat. Chociaż baza danych (i logika biznesowa) zezwala na NULL UnitPrice s, ta konkretna strona ASP.NET nie.

Użytkownik nie może pozostawić wartości UnitPrice pustej

Rysunek 13. Użytkownik nie może pozostawić UnitPrice pustego (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Do tej pory widzieliśmy, jak za pomocą zdarzenia GridView RowUpdating programowo zmienić wartości parametrów przypisanych do kolekcji ObjectDataSource UpdateParameters , a także jak całkowicie anulować proces aktualizacji. Te pojęcia są przenoszone do kontrolek DetailsView i FormView, a także do wstawiania i usuwania.

Te zadania można również wykonywać na poziomie ObjectDataSource za pomocą procedur obsługi zdarzeń dla zdarzeń Inserting, Updatingi Deleting . Te zdarzenia są uruchamiane przed wywołaną skojarzą metodą obiektu bazowego i zapewniają szansę na ostatnią szansę zmodyfikowania kolekcji parametrów wejściowych lub anulowania operacji wprost. Programy obsługi zdarzeń dla tych trzech zdarzeń są przekazywane obiekt typu ObjectDataSourceMethodEventArgs , który ma dwie interesujące właściwości:

  • Anuluj, co, jeśli jest ustawione na True, anuluje wykonywaną operację
  • InputParameters, który jest kolekcją InsertParameters, UpdateParameterslub DeleteParameters, w zależności od tego, czy program obsługi zdarzeń jest dla InsertingUpdating, , lub Deleting zdarzenia

Aby zilustrować pracę z wartościami parametrów na poziomie ObjectDataSource, dołączmy element DetailsView na naszej stronie, który umożliwia użytkownikom dodawanie nowego produktu. Ten element DetailsView będzie używany do zapewnienia interfejsu do szybkiego dodawania nowego produktu do bazy danych. Aby zachować spójny interfejs użytkownika podczas dodawania nowego produktu, zezwól użytkownikowi na wprowadzanie wartości tylko dla ProductName pól i UnitPrice . Domyślnie te wartości, które nie są podane w interfejsie wstawiania kontrolki DetailsView, zostaną ustawione na NULL wartość bazy danych. Możemy jednak użyć zdarzenia ObjectDataSource Inserting , aby wstrzyknąć różne wartości domyślne, jak zobaczymy wkrótce.

Krok 3. Dostarczanie interfejsu do dodawania nowych produktów

Przeciągnij element DetailsView z przybornika do projektanta nad kontrolką GridView, wyczyść jego Height właściwości i Width powiąż go z obiektem ObjectDataSource już obecnym na stronie. Spowoduje to dodanie pola BoundField lub CheckBoxField dla każdego pola produktu. Ponieważ chcemy użyć tego elementu DetailsView do dodawania nowych produktów, musimy sprawdzić opcję Włącz wstawianie z tagu inteligentnego; Nie ma jednak takiej opcji, ponieważ metoda ObjectDataSource Insert() nie jest mapowana na metodę w ProductsBLL klasie (przypomnij sobie, że to mapowanie jest ustawione na wartość (Brak) podczas konfigurowania źródła danych zobacz Rysunek 3.

Aby skonfigurować obiekt ObjectDataSource, wybierz link Konfiguruj źródło danych z tagu inteligentnego, uruchamiając kreatora. Pierwszy ekran umożliwia zmianę obiektu bazowego, z którym jest powiązana wartość ObjectDataSource; pozostaw wartość ProductsBLL. Następny ekran zawiera listę mapowań z metod ObjectDataSource do obiektu bazowego. Mimo że jawnie wskazaliśmy, że Insert() metody i Delete() nie powinny być mapowane na żadne metody, jeśli przejdziesz do kart INSERT i DELETE, zobaczysz, że istnieje mapowanie. Dzieje się tak, ponieważ ProductsBLLmetody AddProduct i używają DeleteProduct atrybutu DataObjectMethodAttribute , aby wskazać, że są to metody domyślne odpowiednio dla Insert() i Delete(). W związku z tym kreator ObjectDataSource wybiera te elementy za każdym razem, gdy zostanie uruchomiony kreator, chyba że zostanie jawnie określona inna wartość.

Pozostaw metodę Insert() wskazującą metodę AddProduct , ale ponownie ustaw listę rozwijaną karty DELETE na wartość (Brak).

Ustaw listę rozwijaną karty INSERT na metodę AddProduct

Rysunek 14. Ustaw listę rozwijaną karty INSERT na metodę AddProduct (kliknij, aby wyświetlić obraz pełnowymiarowy)

Ustaw listę rozwijaną karty DELETE na wartość (Brak)

Rysunek 15. Ustaw listę rozwijaną karty DELETE na (Brak) (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Po wprowadzeniu tych zmian składnia deklaratywna obiektu ObjectDataSource zostanie rozszerzona w celu uwzględnienia InsertParameters kolekcji, jak pokazano poniżej:

<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>

Ponowne uruchomienie kreatora dodał ponownie OldValuesParameterFormatString właściwość . Pośmiń chwilę, aby wyczyścić tę właściwość, ustawiając ją na wartość domyślną ({0}) lub usuwając ją całkowicie ze składni deklaratywnej.

Gdy obiekt ObjectDataSource zapewnia możliwości wstawiania, tag inteligentny Kontrolka DetailsView będzie teraz zawierać pole wyboru Włącz wstawianie; wróć do projektanta i zaznacz tę opcję. Następnie przeanalizuj element DetailsView tak, aby miał tylko dwa pola BoundFields — ProductName i UnitPrice — i CommandField. W tym momencie składnia deklaratywna elementu DetailsView powinna wyglądać następująco:

<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>

Rysunek 16 przedstawia tę stronę po wyświetleniu w tej chwili przeglądarki. Jak widać, kontrolka DetailsView wyświetla nazwę i cenę pierwszego produktu (Chai). Chcemy jednak wstawić interfejs zapewniający użytkownikowi możliwość szybkiego dodania nowego produktu do bazy danych.

Element DetailsView jest obecnie renderowany w trybie tylko do odczytu

Rysunek 16. Widok Szczegółów jest obecnie renderowany w trybie tylko do odczytu (kliknij, aby wyświetlić obraz pełnowymiarowy)

Aby wyświetlić element DetailsView w trybie wstawiania, musimy ustawić DefaultMode właściwość na Insertingwartość . Spowoduje to renderowanie kontrolki DetailsView w trybie wstawiania po pierwszym odwiedzeniu i utrzymuje go po wstawieniu nowego rekordu. Jak pokazano na rysunku 17, taki element DetailsView zapewnia szybki interfejs dodawania nowego rekordu.

Element DetailsView udostępnia interfejs umożliwiający szybkie dodawanie nowego produktu

Rysunek 17. Widok Szczegółów zawiera interfejs umożliwiający szybkie dodawanie nowego produktu (kliknij, aby wyświetlić obraz pełnowymiarowy)

Gdy użytkownik wprowadzi nazwę i cenę produktu (np. "Acme Water" i 1,99, jak na rysunku 17), a następnie kliknie pozycję Wstaw, zostanie wyświetlony komunikat zwrotny i rozpocznie się wstawianie przepływu pracy, co kończy się na nowym rekordzie produktu dodawanym do bazy danych. Element DetailsView utrzymuje interfejs wstawiania, a element GridView jest automatycznie przywracany do źródła danych w celu uwzględnienia nowego produktu, jak pokazano na rysunku 18.

Produkt

Rysunek 18. Produkt "Acme Water" został dodany do bazy danych

Chociaż element GridView na rysunku 18 nie pokazuje go, pola produktu, których brakuje w interfejsie CategoryIDDetailsView , , SupplierIDQuantityPerUniti tak dalej, są przypisywane NULL wartości bazy danych. Można to zobaczyć, wykonując następujące kroki:

  1. Przejdź do Eksploratora serwera w programie Visual Studio
  2. Rozszerzanie węzła NORTHWND.MDF bazy danych
  3. Kliknij prawym przyciskiem myszy Products węzeł tabeli bazy danych
  4. Wybierz pozycję Pokaż dane tabeli

Spowoduje to wyświetlenie listy wszystkich rekordów w Products tabeli. Jak pokazano na rysunku 19, wszystkie kolumny naszego nowego produktu inne niż ProductID, ProductNamei UnitPrice mają NULL wartości.

Pola produktu, które nie zostały podane w widoku DetailsView, są przypisane wartości NULL

Rysunek 19. Pola produktu, które nie zostały podane w widoku DetailsView, są wartościami przypisanymi NULL (kliknij, aby wyświetlić obraz pełnowymiarowy)

Możemy podać wartość domyślną inną niż NULL dla jednej lub większej liczby tych wartości kolumn, ponieważ NULL nie jest to najlepsza opcja domyślna lub ponieważ sama kolumna bazy danych nie zezwala.NULL W tym celu możemy programowo ustawić wartości parametrów kolekcji DetailsView InputParameters . To przypisanie można wykonać w procedurze obsługi zdarzeń dla zdarzenia DetailsView ItemInserting lub zdarzenia ObjectDataSource Inserting . Ponieważ już przyjrzeliśmy się używaniu zdarzeń wstępnych i po poziomie na poziomie kontroli sieci Web danych, przyjrzyjmy się temu za pomocą zdarzeń objectDataSource.

Krok 4. Przypisywanie wartości do parametrówCategoryIDiSupplierID

W tym samouczku wyobraźmy sobie, że w przypadku naszej aplikacji podczas dodawania nowego produktu za pomocą tego interfejsu należy przypisać CategoryID wartość i SupplierID 1. Jak wspomniano wcześniej, obiekt ObjectDataSource zawiera parę zdarzeń wstępnych i po poziomie, które są uruchamiane podczas procesu modyfikacji danych. Po wywołaniu metody Insert() obiekt ObjectDataSource najpierw zgłasza zdarzenie Inserting , a następnie wywołuje metodę, do którego została zamapowana jego Insert() metoda, a na koniec zgłasza Inserted zdarzenie. Procedura Inserting obsługi zdarzeń daje nam jedną ostatnią okazję do dostosowania parametrów wejściowych lub anulowania operacji wprost.

Uwaga

W rzeczywistej aplikacji prawdopodobnie zechcesz pozwolić użytkownikowi określić kategorię i dostawcę lub wybrać tę wartość na podstawie niektórych kryteriów lub logiki biznesowej (zamiast ślepo wybierać identyfikator 1). Niezależnie od tego, w przykładzie pokazano, jak programowo ustawić wartość parametru wejściowego ze zdarzenia pre-level obiektu ObjectDataSource.

Pośmiń chwilę na utworzenie procedury obsługi zdarzeń dla zdarzenia ObjectDataSource Inserting . Zwróć uwagę, że drugi parametr wejściowy programu obsługi zdarzeń jest obiektem typu ObjectDataSourceMethodEventArgs, który ma właściwość dostępu do kolekcji parametrów (InputParameters) i właściwości, aby anulować operację (Cancel).

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

End Sub

W tym momencie InputParameters właściwość zawiera kolekcję ObjectDataSource InsertParameters z wartościami przypisanymi z kontrolki DetailsView. Aby zmienić wartość jednego z tych parametrów, po prostu użyj polecenia: e.InputParameters("paramName") = value. W związku z tym, aby ustawić CategoryID wartości i SupplierID na 1, dostosuj Inserting procedurę obsługi zdarzeń tak, aby wyglądała następująco:

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

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

Tym razem podczas dodawania nowego produktu (takiego jak Soda Acme) CategoryID kolumny i SupplierID nowego produktu są ustawione na 1 (patrz Rysunek 20).

Nowe produkty mają teraz wartości CategoryID i SupplierID ustawione na 1

Rysunek 20. Nowe produkty mają teraz wartości CategoryID i SupplierID ustawione na 1 (kliknij, aby wyświetlić obraz pełnowymiarowy)

Podsumowanie

Podczas edytowania, wstawiania i usuwania procesu zarówno kontrolka internetowa danych, jak i obiekt ObjectDataSource przechodzą przez wiele zdarzeń wstępnych i po poziomie. W tym samouczku zbadano zdarzenia na poziomie wstępnym i pokazano, jak za ich pomocą dostosować parametry wejściowe lub całkowicie anulować operację modyfikacji danych zarówno ze zdarzeń kontrolki sieci Web danych, jak i zdarzeń ObjectDataSource. W następnym samouczku przyjrzymy się tworzeniu i używaniu programów obsługi zdarzeń dla zdarzeń po poziomie.

Szczęśliwe programowanie!

Informacje o autorze

Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w 24 godzinach. Można go uzyskać pod adresem mitchell@4GuysFromRolla.com. lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została omówiona przez wielu przydatnych recenzentów. Recenzenci z tego samouczka to Jackie Goor i Liz Shulok. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.