Badanie zdarzeń powiązanych ze wstawianiem, aktualizowaniem i usuwaniem (C#)
Autor: Scott Mitchell
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:
- Obiekt GridView wypełnia obiekty ObjectDataSource
UpdateParameters
unikatowymi polami identyfikacji edytowanego rekordu (za pośrednictwemDataKeyNames
właściwości) oraz wartościami wprowadzonymi przez użytkownika - Obiekt GridView wywołuje metodę ObjectDataSource
Update()
, która z kolei wywołuje odpowiednią metodę w obiekcie bazowym (ProductsDAL.UpdateProduct
w poprzednim samouczku) - 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.
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 iUnitPrice
produktó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 null
wartość 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
, unitPrice
i productID
:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
if (products.Count == 0)
// no matching record found, return false
return false;
Northwind.ProductsRow product = products[0];
product.ProductName = productName;
if (unitPrice == null) product.SetUnitPriceNull();
else product.UnitPrice = unitPrice.Value;
// Update the product record
int rowsAffected = Adapter.Update(product);
// Return true if precisely one row was updated, otherwise false
return rowsAffected == 1;
}
Podobnie jak w przypadku oryginalnej UpdateProduct
metody, to przeciążenie rozpoczyna się od sprawdzenia, czy w bazie danych znajduje się produkt z określonym ProductID
elementem . Jeśli nie, zwraca false
wartość , 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 productName
parametry , unitPrice
i 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.
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.
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.
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.
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.
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 false
wartość , wystąpi ryzyko przypadkowego usunięcia lub edytowania rekordów przez współbieżnych użytkowników.
UlepszanieUnitPrice
formatowania
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
.
Rysunek 7. Ustawienie UnitPrice
wł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.
Rysunek 8. Wiersze, które nie można edytować, są teraz formatowane jako wartości walutowe (kliknij, aby wyświetlić obraz pełnowymiarowy)
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
.
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.
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ą decimal
przez 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 void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
if (e.NewValues["UnitPrice"] != null)
e.NewValues["UnitPrice"] =
decimal.Parse(e.NewValues["UnitPrice"].ToString(),
System.Globalization.NumberStyles.Currency);
}
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 UnitPrice
przez 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.
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 i wyświetlić true
komunikat wyjaśniający, dlaczego UnitPrice
wartość w NewValues
kolekcji to null
.
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.
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 void Page_Load(object sender, EventArgs e)
{
MustProvideUnitPriceMessage.Visible = false;
}
Jeśli użytkownik próbuje zaktualizować produkt bez określenia UnitPrice
elementu , 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 void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
if (e.NewValues["UnitPrice"] != null)
{
e.NewValues["UnitPrice"] =
decimal.Parse(e.NewValues["UnitPrice"].ToString(),
System.Globalization.NumberStyles.Currency);
}
else
{
// Show the Label
MustProvideUnitPriceMessage.Visible = true;
// Cancel the update
e.Cancel = true;
}
}
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.
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
, Updating
i 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
,UpdateParameters
lubDeleteParameters
, w zależności od tego, czy program obsługi zdarzeń jest dlaInserting
Updating
, , lubDeleting
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ż ProductsBLL
metody 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).
Rysunek 14. Ustaw listę rozwijaną karty INSERT na metodę AddProduct
(kliknij, aby wyświetlić obraz pełnowymiarowy)
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.
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 Inserting
wartość . 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.
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.
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 CategoryID
DetailsView , , SupplierID
QuantityPerUnit
i tak dalej, są przypisywane NULL
wartości bazy danych. Można to zobaczyć, wykonując następujące kroki:
- Przejdź do Eksploratora serwera w programie Visual Studio
- Rozszerzanie węzła
NORTHWND.MDF
bazy danych - Kliknij prawym przyciskiem myszy
Products
węzeł tabeli bazy danych - 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
, ProductName
i UnitPrice
mają NULL
wartości.
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ówCategoryID
iSupplierID
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 void ObjectDataSource1_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
}
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 void ObjectDataSource1_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
e.InputParameters["CategoryID"] = 1;
e.InputParameters["SupplierID"] = 1;
}
Tym razem podczas dodawania nowego produktu (takiego jak Soda Acme) CategoryID
kolumny i SupplierID
nowego produktu są ustawione na 1 (patrz Rysunek 20).
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.