Udostępnij za pośrednictwem


Omówienie wstawiania, aktualizowania i usuwania danych (VB)

Autor: Scott Mitchell

Pobierz plik PDF

W tym samouczku zobaczymy, jak mapować metody Insert(), Update() i Delete() obiektu ObjectDataSource na metody klas BLL, a także jak skonfigurować kontrolki GridView, DetailsView i FormView w celu zapewnienia możliwości modyfikacji danych.

Wprowadzenie

W ciągu ostatnich kilku samouczków omówiliśmy sposób wyświetlania danych na stronie ASP.NET przy użyciu kontrolek GridView, DetailsView i FormView. Te kontrolki po prostu współpracują z danymi dostarczonymi do nich. Często te kontrolki kontrolują dostęp do danych za pomocą kontroli źródła danych, takiej jak ObjectDataSource. Zobaczyliśmy, jak obiekt ObjectDataSource działa jako serwer proxy między stroną ASP.NET a podstawowymi danymi. Gdy obiekt GridView musi wyświetlać dane, wywołuje metodę ObjectDataSource Select() , która z kolei wywołuje metodę z warstwy logiki biznesowej (BLL), która wywołuje metodę w tabeli TableAdapter odpowiedniej warstwy dostępu do danych (DAL), która z kolei wysyła SELECT zapytanie do bazy danych Northwind.

Pamiętaj, że podczas tworzenia tabel TableAdapters w języku DAL w pierwszym samouczku program Visual Studio automatycznie dodał metody wstawiania, aktualizowania i usuwania danych z bazowej tabeli bazy danych. Ponadto w artykule Creating a Business Logic Layer (Tworzenie warstwy logiki biznesowej) zaprojektowaliśmy metody w usłudze BLL, które zostały wywołane do tych metod modyfikacji danych DAL.

Oprócz jej Select() metody obiekt ObjectDataSource ma Insert()również metody , Update()i Delete() . Select() Podobnie jak metoda, te trzy metody można mapować na metody w obiekcie bazowym. Po skonfigurowaniu do wstawiania, aktualizowania lub usuwania danych kontrolki GridView, DetailsView i FormView udostępniają interfejs użytkownika do modyfikowania danych bazowych. Ten interfejs użytkownika wywołuje Insert()metody , Update()i Delete() objectDataSource, które następnie wywołują skojarzone metody obiektu bazowego (zobacz Rysunek 1).

Metody Insert(), Update() i Delete() obiektu ObjectDataSource służą jako serwer proxy do BLL

Rysunek 1. Metody , i Delete() ObjectDataSource Insert()Update()służą jako serwer proxy do BLL (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

W tym samouczku zobaczymy, jak mapować metody , i Delete() objectDataSource Insert()Update()na metody klas w usłudze BLL, a także jak skonfigurować kontrolki GridView, DetailsView i FormView w celu zapewnienia możliwości modyfikacji danych.

Krok 1. Tworzenie stron sieci Web wstawiania, aktualizowania i usuwania

Zanim zaczniemy badać, jak wstawiać, aktualizować i usuwać dane, najpierw zajmijmy się chwilą, aby utworzyć strony ASP.NET w naszym projekcie witryny internetowej, które będą potrzebne w tym samouczku i kilku następnych. Zacznij od dodania nowego folderu o nazwie EditInsertDelete. Następnie dodaj następujące strony ASP.NET do tego folderu, aby skojarzyć każdą stronę ze stroną wzorcową Site.master :

  • Default.aspx
  • Basics.aspx
  • DataModificationEvents.aspx
  • ErrorHandling.aspx
  • UIValidation.aspx
  • CustomizedUI.aspx
  • OptimisticConcurrency.aspx
  • ConfirmationOnDelete.aspx
  • UserLevelAccess.aspx

Dodawanie stron ASP.NET dla samouczków dotyczących modyfikacji danych

Rysunek 2. Dodawanie stron ASP.NET dla samouczków dotyczących modyfikacji danych

Podobnie jak w innych folderach, Default.aspx w EditInsertDelete folderze zostanie wyświetlona lista samouczków w jego sekcji. Pamiętaj, że kontrolka SectionLevelTutorialListing.ascx użytkownika udostępnia tę funkcję. W związku z tym dodaj tę kontrolkę Default.aspx użytkownika, przeciągając ją z Eksplorator rozwiązań do widoku projektu strony.

Dodaj kontrolkę Użytkownika SectionLevelTutorialListing.ascx, aby Default.aspx

Rysunek 3. Dodawanie kontrolki SectionLevelTutorialListing.ascx użytkownika do Default.aspx (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Na koniec dodaj strony jako wpisy do Web.sitemap pliku. W szczególności dodaj następujący znacznik po niestandardowym formatowaniu <siteMapNode>:

<siteMapNode title="Editing, Inserting, and Deleting" url="~/EditInsertDelete/Default.aspx" description="Samples of Reports that Provide Editing, Inserting, and Deleting Capabilities"> <siteMapNode url="~/EditInsertDelete/Basics.aspx" title="Basics" description="Examines the basics of data modification with the GridView, DetailsView, and FormView controls." /> <siteMapNode url="~/EditInsertDelete/DataModificationEvents.aspx" title="Data Modification Events" description="Explores the events raised by the ObjectDataSource pertinent to data modification." /> <siteMapNode url="~/EditInsertDelete/ErrorHandling.aspx" title="Error Handling" description="Learn how to gracefully handle exceptions raised during the data modification workflow." /> <siteMapNode url="~/EditInsertDelete/UIValidation.aspx" title="Adding Data Entry Validation" description="Help prevent data entry errors by providing validation." /> <siteMapNode url="~/EditInsertDelete/CustomizedUI.aspx" title="Customize the User Interface" description="Customize the editing and inserting user interfaces." /> <siteMapNode url="~/EditInsertDelete/OptimisticConcurrency.aspx" title="Optimistic Concurrency" description="Learn how to help prevent simultaneous users from overwritting one another s changes." /> <siteMapNode url="~/EditInsertDelete/ConfirmationOnDelete.aspx" title="Confirm On Delete" description="Prompt a user for confirmation when deleting a record." /> <siteMapNode url="~/EditInsertDelete/UserLevelAccess.aspx" title="Limit Capabilities Based on User" description="Learn how to limit the data modification functionality based on the user role or permissions." /> </siteMapNode>

Po zaktualizowaniu Web.sitemapprogramu pośmiń chwilę, aby wyświetlić witrynę internetową samouczków za pośrednictwem przeglądarki. Menu po lewej stronie zawiera teraz elementy do edycji, wstawiania i usuwania samouczków.

Mapa witryny zawiera teraz wpisy do edycji, wstawiania i usuwania samouczków

Rysunek 4. Mapa witryny zawiera teraz wpisy do edycji, wstawiania i usuwania samouczków

Krok 2. Dodawanie i konfigurowanie kontrolki ObjectDataSource

Ponieważ kontrolki GridView, DetailsView i FormView różnią się w zależności od możliwości modyfikacji danych i układu, przyjrzyjmy się każdemu z nich indywidualnie. Zamiast mieć każdą kontrolkę przy użyciu własnego obiektu ObjectDataSource, po prostu utwórzmy pojedynczy obiekt ObjectDataSource, który może współużytkować wszystkie trzy przykłady kontrolek.

Basics.aspx Otwórz stronę, przeciągnij element ObjectDataSource z przybornika do Projektanta, a następnie kliknij link Konfiguruj źródło danych z tagu inteligentnego. ProductsBLL Ponieważ jest jedyną klasą BLL, która udostępnia metody edytowania, wstawiania i usuwania, skonfiguruj obiekt ObjectDataSource do używania tej klasy.

Konfigurowanie obiektu ObjectDataSource do używania klasy ProductsBLL

Rysunek 5. Konfigurowanie obiektu ObjectDataSource do używania ProductsBLL klasy (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Na następnym ekranie możemy określić, jakie metody klasy są mapowane na obiekty ProductsBLL ObjectDataSource Select(), Insert(), Update()i Delete() wybierając odpowiednią kartę i wybierając metodę z listy rozwijanej. Rysunek 6, który powinien teraz wyglądać znajomo, mapuje metodę ObjectDataSource Select() na ProductsBLL metodę klasy GetProducts() . Metody Insert(), Update()i Delete() można skonfigurować, wybierając odpowiednią kartę z listy u góry.

Czy obiekt ObjectDataSource zwraca wszystkie produkty

Rysunek 6. ObiektDataSource zwraca wszystkie produkty (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Na rysunkach 7, 8 i 9 są wyświetlane karty UPDATE, INSERT i DELETE obiektu ObjectDataSource. Skonfiguruj te karty, aby Insert()metody , Update()i Delete() wywoływać UpdateProductProductsBLL odpowiednio metody klasy , AddProducti DeleteProduct .

Mapuj metodę Update() objectDataSource na metodę UpdateProduct klasy ProductBLL

Rysunek 7. Mapowanie metody ObjectDataSource Update() na ProductBLL metodę klasy UpdateProduct (kliknij, aby wyświetlić obraz pełnowymiarowy)

Mapuj metodę Insert() objectDataSource na metodę AddProduct klasy ProductBLL

Rysunek 8. Mapowanie metody ObjectDataSource Insert() na ProductBLL metodę Add Product Klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Mapuj metodę Delete() objectDataSource na metodę DeleteProduct klasy ProductBLL

Rysunek 9. Mapowanie metody ObjectDataSource Delete() na ProductBLL metodę klasy DeleteProduct (kliknij, aby wyświetlić obraz pełnowymiarowy)

Być może zauważysz, że listy rozwijane na kartach UPDATE, INSERT i DELETE zostały już wybrane. Jest to dzięki naszemu użyciu DataObjectMethodAttribute , który dekoruje metody ProductsBLL. Na przykład metoda DeleteProduct ma następujący podpis:

<System.ComponentModel.DataObjectMethodAttribute _ (System.ComponentModel.DataObjectMethodType.Delete, True)> _ Public Function DeleteProduct(ByVal productID As Integer) As Boolean End Function

Atrybut DataObjectMethodAttribute wskazuje przeznaczenie każdej metody, niezależnie od tego, czy jest on przeznaczony do wybierania, wstawiania, aktualizowania lub usuwania oraz czy jest to wartość domyślna. Jeśli pominięto te atrybuty podczas tworzenia klas BLL, należy ręcznie wybrać metody z kart UPDATE, INSERT i DELETE.

Po upewnieniu się, że odpowiednie ProductsBLL metody są mapowane na metody , Update()i Delete() objectDataSourceInsert(), kliknij przycisk Zakończ, aby ukończyć pracę kreatora.

Badanie znaczników objectDataSource

Po skonfigurowaniu obiektu ObjectDataSource za pomocą kreatora przejdź do widoku Źródło, aby sprawdzić wygenerowany znacznik deklaratywny. Tag <asp:ObjectDataSource> określa obiekt bazowy i metody do wywołania. Ponadto istnieją DeleteParameterswartości , UpdateParametersi , które InsertParameters są mapowane na parametry wejściowe dla ProductsBLL klas AddProduct, UpdateProducti DeleteProduct metod:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DeleteMethod="DeleteProduct" InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts" TypeName="ProductsBLL" UpdateMethod="UpdateProduct"> <DeleteParameters> <asp:Parameter Name="productID" Type="Int32" /> </DeleteParameters> <UpdateParameters> <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" /> <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>

Obiekt ObjectDataSource zawiera parametr dla każdego z parametrów wejściowych dla skojarzonych metod, podobnie jak lista SelectParameter s jest obecna, gdy obiekt ObjectDataSource jest skonfigurowany do wywoływania metody select, która oczekuje parametru wejściowego (na przykład GetProductsByCategoryID(categoryID)). Jak zobaczymy wkrótce, wartości dla tych DeleteParameters, UpdateParametersi InsertParameters są ustawiane automatycznie przez GridView, DetailsView i FormView przed wywołaniem metody , Update()lub Delete() ObjectDataSourceInsert(). Te wartości można również ustawić programowo zgodnie z potrzebami, ponieważ omówimy je w przyszłym samouczku.

Jednym z efektów ubocznych użycia kreatora do skonfigurowania elementu ObjectDataSource jest to, że program Visual Studio ustawia właściwość OldValuesParameterFormatString na original_{0}wartość . Ta wartość właściwości służy do uwzględnienia oryginalnych wartości edytowanych danych i jest przydatna w dwóch scenariuszach:

  • Jeśli podczas edytowania rekordu użytkownicy będą mogli zmienić wartość klucza podstawowego. W takim przypadku należy podać zarówno nową wartość klucza podstawowego, jak i oryginalną wartość klucza podstawowego, aby można było znaleźć rekord z oryginalną wartością klucza podstawowego i odpowiednio zaktualizować jego wartość.
  • W przypadku korzystania z optymistycznej współbieżności. Optymistyczna współbieżność to technika zapewniająca, że dwóch równoczesnych użytkowników nie zastępuje zmian nawzajem i jest tematem na potrzeby przyszłego samouczka.

Właściwość OldValuesParameterFormatString wskazuje nazwę parametrów wejściowych w metodach aktualizacji i usuwania obiektu bazowego dla oryginalnych wartości. Omówimy tę właściwość i jej przeznaczenie bardziej szczegółowo podczas eksplorowania optymistycznej współbieżności. Wychowuję to teraz, jednak, ponieważ nasze metody BLL nie oczekują oryginalnych wartości i dlatego ważne jest, aby usunąć tę właściwość. Pozostawienie właściwości ustawionej OldValuesParameterFormatString na wartość inną niż domyślna ({0}) spowoduje błąd, gdy kontrolka sieci Web danych próbuje wywołać metody lub Delete() objectDataSourceUpdate(), ponieważ źródło ObjectDataSource spróbuje przekazać zarówno UpdateParameters parametry wartości lubDeleteParameters, jak i oryginalne.

Jeśli nie jest to strasznie jasne w tym momencie, nie martw się, zbadamy tę właściwość i jej narzędzie w przyszłym samouczku. Na razie wystarczy tylko usunąć tę deklarację właściwości całkowicie ze składni deklaratywnej lub ustawić wartość na wartość domyślną ({0}).

Uwaga

Jeśli po prostu wyczyścisz OldValuesParameterFormatString wartość właściwości z okno Właściwości w widoku Projektu, właściwość nadal będzie istnieć w składni deklaratywnej, ale zostanie ustawiona na pusty ciąg. To, niestety, nadal spowoduje to ten sam problem omówiony powyżej. W związku z tym należy całkowicie usunąć właściwość ze składni deklaratywnej lub z okno Właściwości ustawić wartość domyślną {0}na .

Krok 3. Dodawanie kontrolki sieci Web danych i konfigurowanie jej pod kątem modyfikacji danych

Po dodaniu obiektu ObjectDataSource do strony i skonfigurowaniu możemy dodać kontrolki sieci Web danych do strony, aby wyświetlić dane i udostępnić użytkownikowi końcowemu środki do ich zmodyfikowania. Przyjrzymy się oddzielnie kontrolkom GridView, DetailsView i FormView, ponieważ te kontrolki sieci Web danych różnią się w zależności od możliwości modyfikacji danych i konfiguracji.

Jak zobaczymy w pozostałej części tego artykułu, dodanie bardzo podstawowej edycji, wstawiania i usuwania obsługi za pomocą kontrolek GridView, DetailsView i FormView jest naprawdę proste, jak sprawdzanie kilku pól wyboru. Istnieje wiele subtelności i przypadków krawędzi w świecie rzeczywistym, które sprawiają, że zapewnienie takich funkcji bardziej zaangażowanych niż tylko punkt i kliknięcie. Ten samouczek koncentruje się jednak wyłącznie na udowodnieniu uproszczonych możliwości modyfikacji danych. Przyszłe samouczki przeanalizują obawy, które bez wątpienia pojawią się w rzeczywistym środowisku.

Usuwanie danych z kontrolki GridView

Zacznij od przeciągnięcia kontrolki GridView z przybornika do projektanta. Następnie powiąż obiekt ObjectDataSource z kontrolką GridView, wybierając ją z listy rozwijanej w tagu inteligentnym GridView. W tym momencie znacznik deklaratywnej kontrolki GridView będzie następujący:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1"> <Columns> <asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False" ReadOnly="True" SortExpression="ProductID" /> <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" /> <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" /> <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" /> <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" /> <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" /> <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" /> <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" /> <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel" SortExpression="ReorderLevel" /> <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" /> <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" ReadOnly="True" SortExpression="CategoryName" /> <asp:BoundField DataField="SupplierName" HeaderText="SupplierName" ReadOnly="True" SortExpression="SupplierName" /> </Columns> </asp:GridView>

Powiązanie kontrolki GridView z obiektem ObjectDataSource za pomocą tagu inteligentnego ma dwie korzyści:

  • Pola BoundFields i CheckBoxFields są tworzone automatycznie dla każdego pola zwracanego przez obiekt ObjectDataSource. Ponadto właściwości BoundField i CheckBoxField są ustawiane na podstawie metadanych pola bazowego. Na przykład ProductIDpola , CategoryNamei SupplierName są oznaczone jako tylko do odczytu w ProductsDataTable obiekcie i dlatego nie powinny być aktualizowalne podczas edytowania. Aby to uwzględnić, właściwości ReadOnly obiektów BoundFields są ustawione na Truewartość .
  • Właściwość DataKeyNames jest przypisywana do pól klucza podstawowego obiektu bazowego. Jest to niezbędne w przypadku używania kontrolki GridView do edytowania lub usuwania danych, ponieważ ta właściwość wskazuje pole (lub zestaw pól), które unikatowo identyfikuje każdy rekord. Aby uzyskać więcej informacji na DataKeyNames temat właściwości, zapoznaj się z samouczkiem Master/Detail Using a Selectable Master GridView with a Details DetailView (Wzorzec/szczegóły przy użyciu kontrolki Selectable Master GridView ).

Element GridView może być powiązany z obiektem ObjectDataSource za pomocą okno Właściwości lub składni deklaratywnej, dlatego wymaga ręcznego dodania odpowiedniego pola BoundField i DataKeyNames znaczników.

Kontrolka GridView zapewnia wbudowaną obsługę edytowania i usuwania na poziomie wiersza. Konfigurowanie kontrolki GridView w celu obsługi usuwania dodaje kolumnę przycisków Usuń. Gdy użytkownik końcowy kliknie przycisk Usuń dla określonego wiersza, zostanie wyświetlony komunikat zwrotny, a element GridView wykonuje następujące kroki:

  1. Wartości obiektu ObjectDataSource DeleteParameters są przypisane
  2. Wywoływana Delete() jest metoda ObjectDataSource, usuwając określony rekord
  3. Element GridView ponownie połączy się z obiektem ObjectDataSource, wywołując jego Select() metodę

Wartości przypisane do elementu DeleteParameters to wartości DataKeyNames pól dla wiersza, którego przycisk Usuń został kliknięty. Dlatego ważne jest, aby właściwość GridView była poprawnie ustawiona DataKeyNames . Jeśli jej brakuje, DeleteParameters zostanie przypisana wartość Nothing w kroku 1, co z kolei nie spowoduje usunięcia rekordów w kroku 2.

Uwaga

Kolekcja DataKeys jest przechowywana w stanie sterowania kontrolki GridView, co oznacza, że DataKeys wartości będą zapamiętowywane po wyświetleniu, nawet jeśli stan widoku kontrolki GridView został wyłączony. Jednak bardzo ważne jest, aby stan widoku pozostał włączony dla obiektów GridView obsługujących edytowanie lub usuwanie (zachowanie domyślne). Jeśli ustawisz właściwość GridView na false, zachowanie edytowania EnableViewState i usuwania będzie działać prawidłowo dla pojedynczego użytkownika, ale jeśli istnieją współbieżni użytkownicy usuwający dane, istnieje możliwość przypadkowego usunięcia lub edytowania rekordów, których nie zamierzali.

To samo ostrzeżenie dotyczy również elementów DetailsView i FormView.

Aby dodać możliwości usuwania do kontrolki GridView, po prostu przejdź do tagu inteligentnego i zaznacz pole wyboru Włącz usuwanie.

Zaznacz pole wyboru Włącz usuwanie

Rysunek 10. Zaznacz pole wyboru Włącz usuwanie

Zaznacz pole wyboru Włącz usuwanie z tagu inteligentnego dodaje pole CommandField do kontrolki GridView. Pole CommandField renderuje kolumnę w elementy GridView z przyciskami służącymi do wykonywania co najmniej jednego z następujących zadań: wybierania rekordu, edytowania rekordu i usuwania rekordu. Wcześniej widzieliśmy pole commandField w akcji z wybieraniem rekordów w master/detail using a Selectable Master GridView with a Details DetailView tutorial (Wybieranie elementu Master GridView z elementem DetailsView ).

Pole CommandField zawiera wiele ShowXButton właściwości, które wskazują serię przycisków wyświetlanych w pole polecenia. Zaznaczając pole wyboru Włącz usuwanie pole polecenia, którego ShowDeleteButton właściwość została True dodana do kolekcji Kolumny kontrolki GridView.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1"> <Columns> <asp:CommandField ShowDeleteButton="True" /> ... BoundFields removed for brevity ... </Columns> </asp:GridView>

W tym momencie wierzymy w to, czy nie, możemy dodać obsługę usuwania do kontrolki GridView! Jak pokazano na rysunku 11, podczas odwiedzania tej strony za pośrednictwem przeglądarki jest wyświetlana kolumna przycisków Usuń.

Pole polecenia dodaje kolumnę przycisków usuwania

Rysunek 11. Pole polecenia dodaje kolumnę przycisków usuwania (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Jeśli tworzysz ten samouczek od podstaw samodzielnie, podczas testowania tej strony kliknięcie przycisku Usuń spowoduje wystąpienie wyjątku. Kontynuuj czytanie, aby dowiedzieć się, dlaczego te wyjątki zostały zgłoszone i jak je naprawić.

Uwaga

Jeśli korzystasz z pobierania towarzyszącego temu samouczkowi, te problemy zostały już uwzględnione. Zachęcam jednak do zapoznania się ze szczegółowymi informacjami wymienionymi poniżej, aby pomóc zidentyfikować problemy, które mogą wystąpić i odpowiednie obejścia.

Jeśli podczas próby usunięcia produktu otrzymasz wyjątek podobny do komunikatu "ObjectDataSource 'ObjectDataSource1' nie można odnaleźć metody innej niż ogólna "DeleteProduct", która ma parametry: productID, original_ProductID", prawdopodobnie nie pamiętasz usunięcia OldValuesParameterFormatString właściwości z obiektu ObjectDataSource. Po określeniu OldValuesParameterFormatString właściwości obiekt ObjectDataSource próbuje przekazać zarówno parametry wejściowe, jak productID i original_ProductID do DeleteProduct metody . DeleteProductjednak akceptuje tylko jeden parametr wejściowy, dlatego wyjątek. OldValuesParameterFormatString Usunięcie właściwości (lub ustawienie jej na {0}wartość ) powoduje, że właściwość ObjectDataSource nie próbuje przekazać oryginalnego parametru wejściowego.

Upewnij się, że właściwość OldValuesParameterFormatString została wyczyszczone

Rysunek 12. Upewnij się, że OldValuesParameterFormatString właściwość została wyczyszczone (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Nawet jeśli właściwość została usunięta OldValuesParameterFormatString , nadal otrzymasz wyjątek podczas próby usunięcia produktu z komunikatem: "Instrukcja DELETE powoduje konflikt z ograniczeniem REFERENCE "FK_Order_Details_Products". Baza danych Northwind zawiera ograniczenie klucza obcego między Order Details tabelą i Products , co oznacza, że nie można usunąć produktu z systemu, jeśli w Order Details tabeli znajduje się co najmniej jeden rekord. Ponieważ każdy produkt w bazie danych Northwind ma co najmniej jeden rekord w Order Detailssystemie , nie możemy usunąć żadnych produktów, dopóki nie usuniemy rekordów szczegółów zamówienia skojarzonego z produktem.

Ograniczenie klucza obcego uniemożliwia usunięcie produktów

Rysunek 13. Ograniczenie klucza obcego uniemożliwia usunięcie produktów (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

W naszym samouczku po prostu usuńmy wszystkie rekordy z Order Details tabeli. W rzeczywistej aplikacji musimy wykonać jedną z następujących czynności:

  • Inny ekran umożliwiający zarządzanie informacjami o szczegółach zamówienia
  • Rozszerzanie DeleteProduct metody w celu uwzględnienia logiki w celu usunięcia szczegółów zamówienia określonego produktu
  • Modyfikowanie zapytania SQL używanego przez narzędzie TableAdapter w celu uwzględnienia usunięcia szczegółów zamówienia określonego produktu

Po prostu usuńmy wszystkie rekordy z tabeli, Order Details aby obejść ograniczenie klucza obcego. Przejdź do Eksploratora serwera w programie Visual Studio, kliknij prawym przyciskiem myszy NORTHWND.MDF węzeł i wybierz pozycję Nowe zapytanie. Następnie w oknie zapytania uruchom następującą instrukcję SQL: DELETE FROM [Order Details]

Usuń wszystkie rekordy z tabeli Szczegółów zamówienia

Rysunek 14. Usuwanie wszystkich rekordów z Order Details tabeli (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po wyczyszczeniu Order Details tabeli kliknięcie przycisku Usuń spowoduje usunięcie produktu bez błędu. Jeśli kliknięcie przycisku Usuń nie spowoduje usunięcia produktu, sprawdź, czy właściwość GridView DataKeyNames jest ustawiona na pole klucza podstawowego (ProductID).

Uwaga

Po kliknięciu przycisku Usuń następuje wycofanie i usunięcie rekordu. Może to być niebezpieczne, ponieważ można łatwo przypadkowo kliknąć przycisk Usuń niewłaściwego wiersza. W przyszłym samouczku zobaczymy, jak dodać potwierdzenie po stronie klienta podczas usuwania rekordu.

Edytowanie danych za pomocą kontrolki GridView

Oprócz usuwania kontrolka GridView zapewnia również wbudowaną obsługę edycji na poziomie wiersza. Konfigurowanie kontrolki GridView w celu obsługi edycji powoduje dodanie kolumny przycisków Edytuj. Z perspektywy użytkownika końcowego kliknięcie przycisku Edytuj wiersza powoduje, że wiersz staje się edytowalny, zamieniając komórki w pola tekstowe zawierające istniejące wartości i zastępując przycisk Edytuj przyciskami Aktualizuj i Anuluj. Po wprowadzeniu żądanych zmian użytkownik końcowy może kliknąć przycisk Aktualizuj, aby zatwierdzić zmiany lub przycisk Anuluj, aby je odrzucić. W obu przypadkach po kliknięciu przycisku Aktualizuj lub Anuluj widok GridView powróci do stanu wstępnego edytowania.

Z naszej perspektywy jako deweloper strony, gdy użytkownik końcowy kliknie przycisk Edytuj dla określonego wiersza, zostanie wyświetlony komunikat zwrotny, a element GridView wykonuje następujące kroki:

  1. Właściwość GridView jest przypisywana EditItemIndex do indeksu wiersza, którego przycisk Edytuj został kliknięty
  2. Element GridView ponownie połączy się z obiektem ObjectDataSource, wywołując jego Select() metodę
  3. Indeks wierszy zgodny z elementem EditItemIndex jest renderowany w trybie edycji. W tym trybie przycisk Edytuj jest zastępowany przez przyciski Aktualizuj i Anuluj i BoundFields, których ReadOnly właściwości to False (wartość domyślna) są renderowane jako kontrolki sieci Web TextBox, których Text właściwości są przypisane do wartości pól danych.

Na tym etapie znaczniki są zwracane do przeglądarki, co umożliwia użytkownikowi końcowemu wprowadzanie jakichkolwiek zmian w danych wiersza. Gdy użytkownik kliknie przycisk Aktualizuj, nastąpi wycofanie, a element GridView wykonuje następujące kroki:

  1. Wartości obiektu ObjectDataSource UpdateParameters są przypisywane wartości wprowadzone przez użytkownika końcowego do interfejsu edycji obiektu GridView
  2. Wywoływana Update() jest metoda ObjectDataSource, aktualizując określony rekord
  3. Element GridView ponownie połączy się z obiektem ObjectDataSource, wywołując jego Select() metodę

Wartości klucza podstawowego UpdateParameters przypisane do tabeli w kroku 1 pochodzą z wartości określonych we DataKeyNames właściwości, natomiast wartości klucza innego niż podstawowy pochodzą z tekstu w kontrolkach sieci Web TextBox dla edytowanego wiersza. Podobnie jak w przypadku usuwania, ważne jest, aby właściwość GridView była poprawnie ustawiona DataKeyNames . Jeśli jej brakuje, UpdateParameters wartość klucza podstawowego zostanie przypisana w Nothing kroku 1, co z kolei nie spowoduje żadnych zaktualizowanych rekordów w kroku 2.

Funkcję edycji można aktywować, zaznaczając pole wyboru Włącz edytowanie w tagu inteligentnym GridView.

Zaznacz pole wyboru Włącz edytowanie

Rysunek 15. Zaznacz pole wyboru Włącz edytowanie

Zaznaczenie pola wyboru Włącz edycję spowoduje dodanie pola CommandField (w razie potrzeby) i ustawienie jej ShowEditButton właściwości na True. Jak pokazano wcześniej, pole CommandField zawiera wiele ShowXButton właściwości, które wskazują serię przycisków wyświetlanych w pole polecenia. Zaznaczenie pola wyboru Włącz edycję ShowEditButton powoduje dodanie właściwości do istniejącego pola polecenia:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1"> <Columns> <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" /> ... BoundFields removed for brevity ... </Columns> </asp:GridView>

To wszystko, co jest do dodawania podstawowego wsparcia do edycji. Jak pokazano na rysunku16, interfejs edycji jest raczej surowy dla każdego obiektu BoundField, którego ReadOnly właściwość jest ustawiona na False (wartość domyślna) jest renderowana jako pole tekstowe. Obejmuje to pola takie jak CategoryID i SupplierID, które są kluczami do innych tabel.

Kliknięcie przycisku Edytuj Chai powoduje wyświetlenie wiersza w trybie edycji

Rysunek 16. Kliknięcie przycisku Edytuj Chai powoduje wyświetlenie wiersza w trybie edycji (kliknij, aby wyświetlić obraz pełnowymiarowy)

Oprócz bezpośredniego edytowania wartości klucza obcego przez użytkowników interfejs edycji nie jest zgodny z następującymi sposobami:

  • Jeśli użytkownik wprowadzi element CategoryID lub SupplierID , który nie istnieje w bazie danych, UPDATE będzie naruszać ograniczenie klucza obcego, co powoduje zgłaszanie wyjątku.
  • Interfejs edycji nie zawiera żadnej weryfikacji. Jeśli nie podasz wymaganej wartości (takiej jak ProductName), lub wprowadź wartość ciągu, w której oczekiwana jest wartość liczbowa (na przykład wprowadzenie wartości "Zbyt wiele!" w UnitPrice polu tekstowym), zostanie zgłoszony wyjątek. W przyszłym samouczku dowiesz się, jak dodać kontrolki walidacji do interfejsu użytkownika edycji.
  • Obecnie wszystkie pola produktów, które nie są tylko do odczytu, muszą być uwzględnione w elementy GridView. Gdybyśmy usunęli pole z kontrolki GridView, powiedzmy UnitPrice, podczas aktualizowania danych kontrolka GridView nie ustawiłaby UnitPrice UpdateParameters wartości, co spowoduje zmianę NULL wartości rekordu UnitPrice bazy danych na wartość. Podobnie, jeśli wymagane pole, takie jak ProductName, zostanie usunięte z kontrolki GridView, aktualizacja zakończy się niepowodzeniem z tym samym wyjątkiem "ProductName" kolumny "ProductName" nie zezwala na wyjątki null wymienione powyżej.
  • Formatowanie interfejsu edycji pozostawia wiele do życzenia. Element UnitPrice jest wyświetlany z czterema punktami dziesiętnymi. Najlepiej, aby wartości CategoryID i SupplierID zawierały listy DropDownLists, które zawierają kategorie i dostawców w systemie.

Są to wszystkie braki, z którymi będziemy musieli żyć na razie, ale zostaną one rozwiązane w przyszłych samouczkach.

Wstawianie, edytowanie i usuwanie danych za pomocą kontrolki DetailsView

Jak pokazano we wcześniejszych samouczkach, kontrolka DetailsView wyświetla jeden rekord naraz i, podobnie jak GridView, umożliwia edytowanie i usuwanie aktualnie wyświetlanego rekordu. Zarówno środowisko użytkownika końcowego podczas edytowania i usuwania elementów z widoku DetailsView, jak i przepływu pracy po stronie ASP.NET jest identyczne z elementem GridView. Element DetailsView różni się od kontrolki GridView, ponieważ zapewnia również wbudowaną obsługę wstawiania.

Aby zademonstrować możliwości modyfikacji danych elementu GridView, zacznij od dodania kontrolki DetailsView do Basics.aspx strony powyżej istniejącej kontrolki GridView i powiązania jej z istniejącym obiektem ObjectDataSource za pomocą tagu inteligentnego Kontrolka DetailsView. Następnie wyczyść właściwości kontrolki DetailsView Height i Width zaznacz opcję Włącz stronicowanie z tagu inteligentnego. Aby włączyć edytowanie, wstawianie i usuwanie obsługi, po prostu zaznacz pola wyboru Włącz edytowanie, Włącz wstawianie i Włącz usuwanie w tagu inteligentnym.

Zrzut ekranu przedstawiający okno DetailsView Tasks z zaznaczonymi polami wyboru Włącz wstawianie, Włącz edytowanie i Włącz usuwanie.

Rysunek 17. Konfigurowanie kontrolki DetailsView w celu obsługi edycji, wstawiania i usuwania

Podobnie jak w przypadku kontrolki GridView, dodawanie edycji, wstawiania lub usuwania obsługi powoduje dodanie pola commandfield do kontrolki DetailsView, jak pokazuje następująca składnia deklaratywna:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"> <Fields> <asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False" ReadOnly="True" SortExpression="ProductID" /> <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" /> <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" /> <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" /> <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" /> <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" /> <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" /> <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" /> <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel" SortExpression="ReorderLevel" /> <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" /> <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" ReadOnly="True" SortExpression="CategoryName" /> <asp:BoundField DataField="SupplierName" HeaderText="SupplierName" ReadOnly="True" SortExpression="SupplierName" /> <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" ShowInsertButton="True" /> </Fields> </asp:DetailsView>

Pamiętaj, że dla kontrolki DetailsView pole polecenia jest domyślnie wyświetlane na końcu kolekcji Columns. Ponieważ pola kontrolki DetailsView są renderowane jako wiersze, pole polecenia jest wyświetlane jako wiersz z przyciskami Wstaw, Edytuj i Usuń w dolnej części widoku Szczegółów.

Zrzut ekranu przedstawiający element DetailsView z polem poleceń wyświetlanym jako dolny wiersz z przyciskami Wstaw, Edytuj i Usuń.

Rysunek 18. Konfigurowanie kontrolki DetailsView do obsługi edycji, wstawiania i usuwania (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Kliknięcie przycisku Usuń powoduje uruchomienie tej samej sekwencji zdarzeń, co w przypadku elementu GridView: postback; następnie element DetailsView wypełnia jego obiekt ObjectDataSource na DataKeyNames podstawie wartości i zakończył wywołanie metody ObjectDataSource DeleteParameters Delete(), która rzeczywiście usuwa produkt z bazy danych. Edytowanie w widoku DetailsView działa również w sposób identyczny z funkcją GridView.

W przypadku wstawiania użytkownik końcowy jest wyświetlany z przyciskiem Nowy, który po kliknięciu renderuje element DetailsView w trybie wstawiania. W przypadku opcji "tryb wstawiania" przycisk Nowy jest zastępowany przyciskami Wstaw i Anuluj, a wyświetlane są tylko pola powiązane, których InsertVisible właściwość jest ustawiona na True (wartość domyślna). Te pola danych zidentyfikowane jako pola automatycznego zwiększania, takie jak ProductID, mają ustawioną właściwość InsertVisible na False wartość podczas powiązania kontrolki DetailsView ze źródłem danych za pomocą tagu inteligentnego.

Po powiązaniu źródła danych z kontrolką DetailsView za pomocą tagu inteligentnego program Visual Studio ustawia InsertVisible właściwość na False wartość tylko dla pól automatycznego zwiększania. Pola tylko do odczytu, takie jak CategoryName i SupplierName, będą wyświetlane w interfejsie użytkownika "tryb wstawiania", chyba że ich InsertVisible właściwość jest jawnie ustawiona na False. Pośmiń chwilę, aby ustawić właściwości tych dwóch pól InsertVisible na Falsewartość , za pomocą składni deklaratywnej kontrolki DetailsView lub linku Edytuj pola w tagu inteligentnym. Rysunek 19 przedstawia ustawienie InsertVisible właściwości False , klikając link Edytuj pola.

Zrzut ekranu przedstawiający okno Pola z właściwością InsertVisible ustawioną na wartość False.

Rysunek 19. Firma Northwind Traders oferuje teraz herbatę Acme (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ustawieniu InsertVisible właściwości wyświetl Basics.aspx stronę w przeglądarce i kliknij przycisk Nowy. Rysunek 20 przedstawia element DetailsView podczas dodawania nowego napoju Acme Tea do naszej linii produktu.

Zrzut ekranu przedstawiający widok DetailsView strony Basics.aspx w przeglądarce internetowej.

Rysunek 20. Firma Northwind Traders oferuje teraz herbatę Acme (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po wprowadzeniu szczegółów aplikacji Acme Tea i kliknięciu przycisku Wstaw następuje powrót i dodanie nowego rekordu Products do tabeli bazy danych. Ponieważ ten element DetailsView wyświetla listę produktów w kolejności, w której istnieją w tabeli bazy danych, musimy stronicować ostatni produkt, aby zobaczyć nowy produkt.

Szczegóły herbaty Acme

Rysunek 21. Szczegóły herbaty Acme (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Właściwość CurrentMode elementu DetailsView wskazuje wyświetlany interfejs i może być jedną z następujących wartości: Edit, lub InsertReadOnly. Właściwość DefaultMode wskazuje tryb, do którego funkcja DetailsView powraca po zakończeniu edycji lub wstawiania i jest przydatna do wyświetlania elementu DetailsView, który jest trwale w trybie edycji lub wstawiania.

Punkt i kliknięcie przycisku wstawiania i edytowania możliwości kontrolki DetailsView nie ma takich samych ograniczeń jak kontrolka GridView: użytkownik musi wprowadzić istniejące CategoryID wartości i SupplierID za pośrednictwem pola tekstowego; interfejs nie ma żadnej logiki walidacji; wszystkie pola produktu, które nie zezwalają na NULL wartości lub nie mają wartości domyślnej określonej na poziomie bazy danych, muszą zostać uwzględnione w interfejsie wstawiania, i tak dalej.

Techniki, które przeanalizujemy pod kątem rozszerzania i ulepszania interfejsu edytowania kontrolki GridView w przyszłych artykułach, można również zastosować do edycji i wstawiania interfejsów kontrolki DetailsView.

Używanie widoku FormView do bardziej elastycznego interfejsu użytkownika modyfikacji danych

Obiekt FormView oferuje wbudowaną obsługę wstawiania, edytowania i usuwania danych, ale ponieważ używa szablonów zamiast pól, nie ma miejsca do dodawania pól BoundFields ani CommandField używanych przez kontrolki GridView i DetailsView w celu udostępnienia interfejsu modyfikacji danych. Zamiast tego ten interfejs umożliwia kontrolkom sieci Web zbieranie danych wejściowych użytkownika podczas dodawania nowego elementu lub edytowania istniejącego elementu wraz z przyciskami Nowy, Edytuj, Usuń, Wstaw, Aktualizuj i Anuluj należy dodać ręcznie do odpowiednich szablonów. Na szczęście program Visual Studio automatycznie utworzy wymagany interfejs podczas wiązania widoku FormView ze źródłem danych za pomocą listy rozwijanej w tagu inteligentnym.

Aby zilustrować te techniki, zacznij od dodania widoku FormView do Basics.aspx strony i z tagu inteligentnego kontrolki FormView powiąż ją z już utworzonym obiektem ObjectDataSource. Spowoduje to wygenerowanie kontrolek , InsertItemTemplatei ItemTemplate dla kontrolki EditItemTemplateFormView z kontrolkami sieci Web TextBox w celu zbierania kontrolek wejściowych i kontrolek sieci Web przycisku użytkownika dla przycisków Nowy, Edytuj, Usuń, Wstaw, Aktualizuj i Anuluj. Ponadto właściwość FormView DataKeyNames jest ustawiona na pole klucza podstawowego (ProductID) obiektu zwróconego przez obiekt ObjectDataSource. Na koniec zaznacz opcję Włącz stronicowanie w tagu inteligentnym kontrolki FormView.

Poniżej przedstawiono znaczniki deklaratywne dla elementu FormView po powiązaniu elementu FormView ItemTemplate z obiektem ObjectDataSource. Domyślnie każde pole produktu innej niż wartość logiczna jest powiązane z właściwością kontrolki Sieci Web Etykieta, podczas gdy każde pole wartości logicznej (Discontinued) jest powiązane Text z Checked właściwością wyłączonej kontrolki checkbox sieci Web. Aby przyciski Nowy, Edytuj i Usuń wyzwalały pewne zachowanie kontrolki FormView po kliknięciu, konieczne jest ustawienie ich CommandName wartości odpowiednio na New, Editi Delete.

<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"> <EditItemTemplate> ... </EditItemTemplate> <InsertItemTemplate> ... </InsertItemTemplate> <ItemTemplate> ProductID: <asp:Label ID="ProductIDLabel" runat="server" Text='<%# Eval("ProductID") %>'></asp:Label><br /> ProductName: <asp:Label ID="ProductNameLabel" runat="server" Text='<%# Bind("ProductName") %>'> </asp:Label><br /> SupplierID: <asp:Label ID="SupplierIDLabel" runat="server" Text='<%# Bind("SupplierID") %>'> </asp:Label><br /> CategoryID: <asp:Label ID="CategoryIDLabel" runat="server" Text='<%# Bind("CategoryID") %>'> </asp:Label><br /> QuantityPerUnit: <asp:Label ID="QuantityPerUnitLabel" runat="server" Text='<%# Bind("QuantityPerUnit") %>'> </asp:Label><br /> UnitPrice: <asp:Label ID="UnitPriceLabel" runat="server" Text='<%# Bind("UnitPrice") %>'></asp:Label><br /> UnitsInStock: <asp:Label ID="UnitsInStockLabel" runat="server" Text='<%# Bind("UnitsInStock") %>'> </asp:Label><br /> UnitsOnOrder: <asp:Label ID="UnitsOnOrderLabel" runat="server" Text='<%# Bind("UnitsOnOrder") %>'> </asp:Label><br /> ReorderLevel: <asp:Label ID="ReorderLevelLabel" runat="server" Text='<%# Bind("ReorderLevel") %>'> </asp:Label><br /> Discontinued: <asp:CheckBox ID="DiscontinuedCheckBox" runat="server" Checked='<%# Bind("Discontinued") %>' Enabled="false" /><br /> CategoryName: <asp:Label ID="CategoryNameLabel" runat="server" Text='<%# Bind("CategoryName") %>'> </asp:Label><br /> SupplierName: <asp:Label ID="SupplierNameLabel" runat="server" Text='<%# Bind("SupplierName") %>'> </asp:Label><br /> <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"> </asp:LinkButton> <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete"> </asp:LinkButton> <asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" CommandName="New" Text="New"> </asp:LinkButton> </ItemTemplate> </asp:FormView>

Rysunek 22 przedstawia widok FormView ItemTemplate podczas przeglądania za pośrednictwem przeglądarki. Każde pole produktu znajduje się na liście z przyciskami Nowy, Edytuj i Usuń u dołu.

Element Defaut FormView ItemTemplate wyświetla listę każdego pola produktu wraz z przyciskami Nowe, Edytuj i Usuń

Rysunek 22. Kontrolka Defaut FormView ItemTemplate wyświetla listę każdego pola produktu wraz z przyciskami Nowy, Edytuj i Usuń (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Podobnie jak w przypadku kontrolki GridView i DetailsView, kliknięcie przycisku Usuń lub dowolnego przycisku, elementu LinkButton lub elementu ImageButton, którego CommandName właściwość jest ustawiona na wartość Delete powoduje, że element ObjectDataSource jest wypełniany na podstawie wartości kontrolki FormView DataKeyNames i wywołuje metodę ObjectDataSource DeleteParameters Delete().

Po kliknięciu przycisku Edytuj zostanie wyświetlony komunikat zwrotny, a dane są odtwarzane do EditItemTemplateelementu , który jest odpowiedzialny za renderowanie interfejsu edycji. Ten interfejs zawiera kontrolki sieci Web do edytowania danych wraz z przyciskami Aktualizuj i Anuluj. Wartość domyślna EditItemTemplate wygenerowana przez program Visual Studio zawiera etykietę dla wszystkich pól automatycznego przyrostu (ProductID), pole TextBox dla każdego pola wartości innej niż wartość logiczna i pole CheckBox dla każdego pola wartości logicznej. To zachowanie jest bardzo podobne do automatycznie generowanych pól BoundFields w kontrolkach GridView i DetailsView.

Uwaga

Jednym z małych problemów z automatycznym generowaniem kontrolki EditItemTemplate FormView jest to, że renderuje kontrolki Web TextBox dla tych pól, które są tylko do odczytu, takich jak CategoryName i SupplierName. Wkrótce zobaczymy, jak to uwzględnić.

Kontrolki TextBox w obiekcie EditItemTemplate mają właściwość Text powiązaną z wartością odpowiedniego pola danych przy użyciu dwukierunkowego powiązania danych. Dwukierunkowe powiązanie danych, oznaczone przez <%# Bind("dataField") %>element , wykonuje powiązanie danych zarówno podczas wiązania danych z szablonem, jak i podczas wypełniania parametrów objectDataSource do wstawiania lub edytowania rekordów. Oznacza to, że gdy użytkownik kliknie przycisk Edytuj z ItemTemplatemetody , Bind() metoda zwraca określoną wartość pola danych. Po wprowadzeniu zmian przez użytkownika i kliknięciu przycisku Aktualizuj wartości opublikowane z powrotem odpowiadające polam danych określonym przy użyciu Bind() są stosowane do obiektu ObjectDataSource UpdateParameters. Alternatywnie jednokierunkowe powiązanie danych, oznaczone przez <%# Eval("dataField") %>element , pobiera tylko wartości pól danych podczas wiązania danych z szablonem i nie zwraca wartości wprowadzonych przez użytkownika do parametrów źródła danych podczas ogłaszania zwrotnego.

Poniższy znacznik deklaratywny pokazuje element FormView .EditItemTemplate Należy pamiętać, że Bind() metoda jest używana w składni powiązania danych w tym miejscu i że kontrolki Sieci Web aktualizuj i anuluj przycisk mają odpowiednio ustawione właściwości CommandName .

<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"> <EditItemTemplate> ProductID: <asp:Label ID="ProductIDLabel1" runat="server" Text="<%# Eval("ProductID") %>"></asp:Label><br /> ProductName: <asp:TextBox ID="ProductNameTextBox" runat="server" Text="<%# Bind("ProductName") %>"> </asp:TextBox><br /> SupplierID: <asp:TextBox ID="SupplierIDTextBox" runat="server" Text="<%# Bind("SupplierID") %>"> </asp:TextBox><br /> CategoryID: <asp:TextBox ID="CategoryIDTextBox" runat="server" Text="<%# Bind("CategoryID") %>"> </asp:TextBox><br /> QuantityPerUnit: <asp:TextBox ID="QuantityPerUnitTextBox" runat="server" Text="<%# Bind("QuantityPerUnit") %>"> </asp:TextBox><br /> UnitPrice: <asp:TextBox ID="UnitPriceTextBox" runat="server" Text="<%# Bind("UnitPrice") %>"> </asp:TextBox><br /> UnitsInStock: <asp:TextBox ID="UnitsInStockTextBox" runat="server" Text="<%# Bind("UnitsInStock") %>"> </asp:TextBox><br /> UnitsOnOrder: <asp:TextBox ID="UnitsOnOrderTextBox" runat="server" Text="<%# Bind("UnitsOnOrder") %>"> </asp:TextBox><br /> ReorderLevel: <asp:TextBox ID="ReorderLevelTextBox" runat="server" Text="<%# Bind("ReorderLevel") %>"> </asp:TextBox><br /> Discontinued: <asp:CheckBox ID="DiscontinuedCheckBox" runat="server" Checked="<%# Bind("Discontinued") %>" /><br /> CategoryName: <asp:TextBox ID="CategoryNameTextBox" runat="server" Text="<%# Bind("CategoryName") %>"> </asp:TextBox><br /> SupplierName: <asp:TextBox ID="SupplierNameTextBox" runat="server" Text="<%# Bind("SupplierName") %>"> </asp:TextBox><br /> <asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update" Text="Update"> </asp:LinkButton> <asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"> </asp:LinkButton> </EditItemTemplate> <InsertItemTemplate> ... </InsertItemTemplate> <ItemTemplate> ... </ItemTemplate> </asp:FormView>

Nasz EditItemTemplateelement , w tym momencie spowoduje zgłoszenie wyjątku, jeśli spróbujemy go użyć. Problem polega na tym, że CategoryName pola i SupplierName są renderowane jako kontrolki sieci Web TextBox w elem.EditItemTemplate Musimy zmienić te pola tekstowe na Etykiety lub całkowicie je usunąć. Po prostu usuńmy je całkowicie z obiektu EditItemTemplate.

Rysunek 23 przedstawia widok FormView w przeglądarce po kliknięciu przycisku Edytuj dla pozycji Chai. Zwróć uwagę, że SupplierName pola i CategoryName wyświetlane w obiekcie ItemTemplate nie są już obecne, ponieważ po prostu usunęliśmy je z obiektu EditItemTemplate. Po kliknięciu przycisku Aktualizuj widok FormView przechodzi przez tę samą sekwencję kroków co kontrolki GridView i DetailsView.

Domyślnie pole EditItemTemplate wyświetla każde edytowalne pole produktu jako pole tekstowe lub pole wyboru

Rysunek 23. Domyślnie pole EditItemTemplate Pokaż każde edytowalne pole produktu jako pole tekstowe lub pole wyboru (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po kliknięciu przycisku Wstaw element FormView ItemTemplate zostanie wyświetlony komunikat zwrotny. Jednak żadne dane nie są powiązane z elementem FormView, ponieważ jest dodawany nowy rekord. Interfejs InsertItemTemplate zawiera kontrolki sieci Web służące do dodawania nowego rekordu wraz z przyciskami Wstaw i Anuluj. Wartość domyślna InsertItemTemplate wygenerowana przez program Visual Studio zawiera pole TextBox dla każdego pola wartości innej niż wartość logiczna i pole wyboru dla każdego pola wartości logicznej, podobnie jak w przypadku interfejsu wygenerowanego EditItemTemplateautomatycznie. Kontrolki TextBox mają swoją Text właściwość powiązaną z wartością odpowiedniego pola danych przy użyciu dwukierunkowego powiązania danych.

Poniższy znacznik deklaratywny pokazuje element FormView .InsertItemTemplate Należy pamiętać, że Bind() metoda jest używana w składni powiązania danych w tym miejscu i że kontrolki Wstaw i Anuluj przycisk w sieci Web mają odpowiednio ustawione właściwości CommandName .

<asp:FormView ID="FormView1" runat="server" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"> <EditItemTemplate> ... </EditItemTemplate> <InsertItemTemplate> ProductName: <asp:TextBox ID="ProductNameTextBox" runat="server" Text="<%# Bind("ProductName") %>"> </asp:TextBox><br /> SupplierID: <asp:TextBox ID="SupplierIDTextBox" runat="server" Text="<%# Bind("SupplierID") %>"> </asp:TextBox><br /> CategoryID: <asp:TextBox ID="CategoryIDTextBox" runat="server" Text="<%# Bind("CategoryID") %>"> </asp:TextBox><br /> QuantityPerUnit: <asp:TextBox ID="QuantityPerUnitTextBox" runat="server" Text="<%# Bind("QuantityPerUnit") %>"> </asp:TextBox><br /> UnitPrice: <asp:TextBox ID="UnitPriceTextBox" runat="server" Text="<%# Bind("UnitPrice") %>"> </asp:TextBox><br /> UnitsInStock: <asp:TextBox ID="UnitsInStockTextBox" runat="server" Text="<%# Bind("UnitsInStock") %>"> </asp:TextBox><br /> UnitsOnOrder: <asp:TextBox ID="UnitsOnOrderTextBox" runat="server" Text="<%# Bind("UnitsOnOrder") %>"> </asp:TextBox><br /> ReorderLevel: <asp:TextBox ID="ReorderLevelTextBox" runat="server" Text="<%# Bind("ReorderLevel") %>"> </asp:TextBox><br /> Discontinued: <asp:CheckBox ID="DiscontinuedCheckBox" runat="server" Checked="<%# Bind("Discontinued") %>" /><br /> CategoryName: <asp:TextBox ID="CategoryNameTextBox" runat="server" Text="<%# Bind("CategoryName") %>"> </asp:TextBox><br /> SupplierName: <asp:TextBox ID="SupplierNameTextBox" runat="server" Text="<%# Bind("SupplierName") %>"> </asp:TextBox><br /> <asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert" Text="Insert"> </asp:LinkButton> <asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"> </asp:LinkButton> </InsertItemTemplate> <ItemTemplate> ... </ItemTemplate> </asp:FormView>

Istnieje subtelność funkcji automatycznego generowania elementu FormView dla elementu InsertItemTemplate. W szczególności kontrolki sieci Web TextBox są tworzone nawet dla tych pól, które są tylko do odczytu, takie jak CategoryName i SupplierName. Podobnie jak w przypadku elementu EditItemTemplate, musimy usunąć te pola TextBoxes z elementu InsertItemTemplate.

Rysunek 24 przedstawia element FormView w przeglądarce podczas dodawania nowego produktu Acme Coffee. Zwróć uwagę, że SupplierName pola i CategoryName wyświetlane w elemecie ItemTemplate nie są już obecne, ponieważ zostały usunięte. Po kliknięciu przycisku Wstaw widok FormView przechodzi przez tę samą sekwencję kroków co kontrolka DetailsView, dodając nowy rekord do Products tabeli. Rysunek 25 przedstawia szczegóły produktu Acme Coffee w widoku FormView po jego wstawieniu.

Element InsertItemTemplate określa interfejs wstawiania kontrolki FormView

Rysunek 24. InsertItemTemplate Dyktowanie interfejsu wstawiania kontrolki FormView (kliknij, aby wyświetlić obraz pełnowymiarowy)

Szczegóły nowego produktu, Acme Coffee, są wyświetlane w widoku FormView

Rysunek 25. Szczegóły nowego produktu, Acme Coffee są wyświetlane w widoku FormView (kliknij, aby wyświetlić obraz pełnowymiarowy)

Oddzielając interfejsy tylko do odczytu, edycji i wstawiania do trzech oddzielnych szablonów, kontrolka FormView umożliwia dokładniejszy stopień kontroli nad tymi interfejsami niż Kontrolka DetailsView i GridView.

Uwaga

Podobnie jak w przypadku kontrolki DetailsView, właściwość Kontrolka CurrentMode FormView wskazuje wyświetlany interfejs, a jego DefaultMode właściwość wskazuje tryb, do których widok FormView powraca po zakończeniu edycji lub wstawiania.

Podsumowanie

W tym samouczku omówiliśmy podstawy wstawiania, edytowania i usuwania danych przy użyciu kontrolki GridView, DetailsView i FormView. Wszystkie trzy z tych kontrolek zapewniają pewien poziom wbudowanych możliwości modyfikacji danych, które można wykorzystać bez konieczności pisania pojedynczego wiersza kodu na stronie ASP.NET dzięki kontrolkom sieci Web danych i obiektowi ObjectDataSource. Jednak proste techniki punktów i kliknięć sprawiają, że interfejs użytkownika modyfikacji danych jest dość słaby i naiwny. Aby zapewnić walidację, wstrzyknąć wartości programowe, bezpiecznie obsługiwać wyjątki, dostosowywać interfejs użytkownika itd., musimy polegać na bevy technik, które zostaną omówione w kolejnych kilku samouczkach.

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.