Dela via


En översikt över hur du infogar, uppdaterar och tar bort data (C#)

av Scott Mitchell

Ladda ned PDF

I den här självstudien får vi se hur du mappar metoderna Insert(), Update() och Delete() för en ObjectDataSource till metoderna för BLL-klasser, samt hur du konfigurerar kontrollerna GridView, DetailsView och FormView för att tillhandahålla funktioner för dataändring.

Inledning

Under de senaste självstudierna har vi undersökt hur du visar data på en ASP.NET sida med hjälp av kontrollerna GridView, DetailsView och FormView. Dessa kontroller fungerar helt enkelt med data som skickas till dem. Dessa styr vanligtvis åtkomst till data med hjälp av en datakällkontroll, till exempel ObjectDataSource. Vi har sett hur ObjectDataSource fungerar som en proxy mellan ASP.NET-sidan och underliggande data. När en GridView behöver visa data anropar den sin ObjectDataSource-metod Select() , som i sin tur anropar en metod från vårt BLL (Business Logic Layer), som anropar en metod i lämpligt Data Access Layer-tabell (DAL) TableAdapter, som i sin tur skickar en SELECT fråga till Northwind-databasen.

Kom ihåg att när vi skapade TableAdapters i DAL i vår första självstudie lade Visual Studio automatiskt till metoder för att infoga, uppdatera och ta bort data från den underliggande databastabellen. Dessutom, i Skapa ett affärslogiklager, har vi utformat metoder i BLL som anropade dessa DAL-metoder för dataändring.

Förutom metoden Select() har Insert()ObjectDataSource även metoderna , Update()och Delete() . Precis som Select() metoden kan dessa tre metoder mappas till metoder i ett underliggande objekt. När kontrollerna GridView, DetailsView och FormView är konfigurerade för att infoga, uppdatera eller ta bort data får du ett användargränssnitt för att ändra underliggande data. Det här användargränssnittet anropar Insert(), Update() och Delete() metoderna av ObjectDataSource, som sedan anropar det underliggande objektets associerade metoder (se Figur 1).

Metoderna ObjectDataSource's Insert(), Update() och Delete() fungerar som en proxy i BLL

Bild 1: ObjectDataSources Insert(), Update()och Delete() metoder fungerar som en proxy i BLL-filen (Klicka om du vill visa en bild i full storlek)

I den här självstudien får vi se hur du mappar ObjectDataSources Insert(), Update()och Delete() -metoder till metoder för klasser i BLL, samt hur du konfigurerar kontrollerna GridView, DetailsView och FormView för att tillhandahålla funktioner för dataändring.

Steg 1: Skapa webbsidorna Infoga, Uppdatera och Ta bort

Innan vi börjar utforska hur du infogar, uppdaterar och tar bort data ska vi först ta en stund att skapa de ASP.NET sidor i vårt webbplatsprojekt som vi behöver för den här självstudien och de kommande flera. Börja med att lägga till en ny mapp med namnet EditInsertDelete. Lägg sedan till följande ASP.NET sidor i mappen och se till att associera varje sida med Site.master huvudsidan:

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

Lägg till ASP.NET-sidorna för Data Modification-Related självstudierna

Bild 2: Lägg till ASP.NET-sidorna för Data Modification-Related-självstudierna

Precis som i de andra mapparna kommer Default.aspx i EditInsertDelete-mappen att lista självstudierna i dess avsnitt. Kom ihåg att SectionLevelTutorialListing.ascx användarkontrollen innehåller den här funktionen. Lägg därför till den här användarkontrollen genom att Default.aspx dra den från Solution Explorer till sidans designvy.

Lägg till sectionLevelTutorialListing.ascx-användarkontrollen i Default.aspx

Bild 3: Lägg till SectionLevelTutorialListing.ascx användarkontrollen Default.aspx i (Klicka om du vill visa en bild i full storlek)

Slutligen lägger du till sidorna som poster i Web.sitemap-filen. Mer specifikt lägger du till följande markering efter den anpassade formateringen <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>

Efter att du har uppdaterat Web.sitemap, ta en stund att besöka självstudiewebbplatsen via en webbläsare. Menyn till vänster innehåller nu alternativ för redigering, infogning och borttagning av handledningar.

Webbplatskartan innehåller nu poster för redigering, infogning och borttagning av självstudier

Bild 4: Webbplatsöversikten innehåller nu entréer för handledningarna Infoga, Redigera och Ta bort

Steg 2: Lägga till och konfigurera ObjectDataSource-kontrollen

Eftersom GridView, DetailsView och FormView skiljer sig åt i sina funktioner för datamodifiering och layout ska vi undersöka var och en individuellt. I stället för att ha varje kontroll med hjälp av sin egen ObjectDataSource ska vi dock bara skapa en enda ObjectDataSource som alla tre kontrollexemplen kan dela.

Öppna sidan Basics.aspx, dra en ObjectDataSource från verktygslådan till designern och klicka på länken för att konfigurera datakällan från dess smarta tagg. ProductsBLL Eftersom är den enda BLL-klassen som tillhandahåller redigerings-, infognings- och borttagningsmetoder konfigurerar du ObjectDataSource för att använda den här klassen.

Konfigurera ObjectDataSource för att använda klassen ProductsBLL

Bild 5: Konfigurera ObjectDataSource att använda ProductsBLL klassen (Klicka om du vill visa en bild i full storlek)

På nästa skärm kan vi ange vilka metoder i ProductsBLL klassen som mappas till ObjectDataSources Select(), Insert(), Update()och Delete() genom att välja lämplig flik och välja metoden i listrutan. Bild 6, som bör se bekant ut vid det här laget, mappar ObjectDataSource-metoden Select() till ProductsBLL klassens GetProducts() -metod. Metoderna Insert(), Update()och Delete() kan konfigureras genom att välja lämplig flik i listan längst upp.

Låt ObjectDataSource returnera alla produkter

Bild 6: Låt ObjectDataSource returnera alla produkter (klicka om du vill visa en bild i full storlek)

Figurerna 7, 8 och 9 visar flikarna UPDATE, INSERT och DELETE för ObjectDataSource. Konfigurera dessa flikar så att Insert()metoderna , Update(), och Delete() anropar ProductsBLL klassens UpdateProduct, AddProductrespektive DeleteProduct metoder.

Mappa Metoden Update() för ObjectDataSource till ProductBLL-klassens UpdateProduct-metod

Bild 7: Mappa ObjectDataSource-metoden Update() till ProductBLL klassens UpdateProduct metod (Klicka om du vill visa en bild i full storlek)

Mappa Metoden ObjectDataSources Insert() till ProductBLL-klassens AddProduct-metod

Bild 8: Mappa ObjectDataSource-metoden Insert() till klassens lägg till-metod ProductBLLProduct (Klicka om du vill visa en bild i full storlek)

Mappa Metoden Delete() för ObjectDataSource till ProductBLL-klassens DeleteProduct-metod

Bild 9: Mappa ObjectDataSource-metoden Delete() till ProductBLL klassens DeleteProduct metod (Klicka om du vill visa en bild i full storlek)

Du kanske har märkt att listrutorna på flikarna UPDATE, INSERT och DELETE redan hade valt dessa metoder. Detta är tack vare vår användning av DataObjectMethodAttribute som dekorerar metoderna för ProductsBLL. Metoden DeleteProduct har till exempel följande signatur:

[System.ComponentModel.DataObjectMethodAttribute
    (System.ComponentModel.DataObjectMethodType.Delete, true)]
public bool DeleteProduct(int productID)
{
    ...
}

Attributet DataObjectMethodAttribute anger syftet med varje metod oavsett om det är för att välja, infoga, uppdatera eller ta bort och om det är standardvärdet eller inte. Om du utelämnade dessa attribut när du skapade dina BLL-klasser måste du manuellt välja metoderna från flikarna UPDATE, INSERT och DELETE.

När du har kontrollerat att lämpliga ProductsBLL metoder har mappats till ObjectDataSources Insert()metoder , Update()och Delete() klickar du på Slutför för att slutföra guiden.

Undersöka ObjectDataSources markup

När du har konfigurerat ObjectDataSource via guiden går du till källvyn för att undersöka den genererade deklarativa markeringen. Taggen <asp:ObjectDataSource> anger det underliggande objektet och de metoder som ska anropas. Dessutom finns DeleteParameters, UpdateParameters och InsertParameters som mappas till indataparametrarna för ProductsBLL-klassens AddProduct, UpdateProduct och DeleteProduct metoder.

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

ObjectDataSource innehåller en parameter för var och en av indataparametrarna för dess associerade metoder, precis som en lista med SelectParameter s finns när ObjectDataSource har konfigurerats för att anropa en select-metod som förväntar sig en indataparameter (till exempel GetProductsByCategoryID(categoryID)). Som vi snart kommer att se anges värdena för dessa DeleteParameters, UpdateParametersoch InsertParameters automatiskt av GridView, DetailsView och FormView innan du anropar ObjectDataSources Insert(), Update()eller Delete() -metod. Dessa värden kan också anges programmatiskt vid behov, som vi kommer att diskutera i en framtida handledning.

En bieffekt av att använda guiden för att konfigurera till ObjectDataSource är att Visual Studio anger egenskapen OldValuesParameterFormatString till original_{0}. Det här egenskapsvärdet används för att inkludera de ursprungliga värdena för de data som redigeras och är användbart i två scenarier:

  • Om användarna kan ändra primärnyckelvärdet när de redigerar en post. I det här fallet måste både det nya primärnyckelvärdet och det ursprungliga primärnyckelvärdet anges så att posten med det ursprungliga primärnyckelvärdet kan hittas och dess värde uppdateras i enlighet med detta.
  • När du använder optimistisk samtidighet. Optimistisk samtidighet är en teknik som säkerställer att två samtidiga användare inte skriver över varandras ändringar och är ämnet för en framtida självstudie.

Egenskapen OldValuesParameterFormatString anger namnet på indataparametrarna i det underliggande objektets uppdaterings- och borttagningsmetoder för de ursprungliga värdena. Vi diskuterar den här egenskapen och dess syfte i detalj när vi utforskar optimistisk samtidighet. Jag tar dock upp det nu, eftersom våra BLL-metoder inte förväntar sig de ursprungliga värdena och därför är det viktigt att vi tar bort den här egenskapen. OldValuesParameterFormatString Om egenskapen är inställd på något annat än standardvärdet ({0}) uppstår ett fel när en datawebbkontroll försöker anropa ObjectDataSources Update() eller Delete() -metoder eftersom ObjectDataSource försöker skicka både eller UpdateParametersDeleteParameters angivna samt ursprungliga värdeparametrar.

Om detta inte är särskilt tydligt i det här läget, oroa dig inte, vi kommer att undersöka den här egenskapen och dess nytta i en framtida handledning. För tillfället är du bara säker på att antingen ta bort den här egenskapsdeklarationen helt från den deklarativa syntaxen eller ange värdet till standardvärdet ({0}).

Anmärkning

Om du helt enkelt avmarkerar egenskapsvärdet OldValuesParameterFormatString från fönstret Egenskaper i designvyn finns egenskapen fortfarande i den deklarativa syntaxen, men anges till en tom sträng. Detta kommer tyvärr fortfarande att leda till samma problem som diskuterats ovan. Ta därför bort egenskapen helt och hållet från den deklarativa syntaxen eller ange värdet till standardvärdet från {0}fönstret Egenskaper.

Steg 3: Lägga till en datawebbkontroll och konfigurera den för dataändring

När ObjectDataSource har lagts till på sidan och konfigurerats är vi redo att lägga till datawebbkontroller på sidan för att både visa data och tillhandahålla ett sätt för slutanvändaren att ändra dem. Vi tittar separat på GridView, DetailsView och FormView eftersom dessa datawebbkontroller skiljer sig åt i deras funktioner och konfiguration av dataändringar.

Som vi ser i resten av den här artikeln är det verkligen lika enkelt att lägga till mycket grundläggande redigering, infoga och ta bort stöd via kontrollerna GridView, DetailsView och FormView som att kontrollera ett par kryssrutor. Det finns många subtiliteter och gränsfall i verkligheten som gör att tillhandahålla sådana funktioner mer involverade än att bara peka och klicka. Den här självstudien fokuserar dock enbart på att demonstrera enkla datamodifieringsmöjligheter. Framtida handledningar kommer att undersöka problem som utan tvekan kommer att uppstå i en verklig miljö.

Ta bort data från GridView

Börja med att dra en GridView från verktygslådan till designern. Sedan binder du ObjectDataSource till GridView genom att välja den i listrutan i GridViews smarta tagg. Vid denna punkt kommer GridViews deklarativa markup-kod att vara:

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

Att binda GridView till ObjectDataSource via den smarta taggen har två fördelar:

  • BoundFields och CheckBoxFields skapas automatiskt för vart och ett av fälten som returneras av ObjectDataSource. Dessutom anges egenskaperna för BoundField och CheckBoxField baserat på det underliggande fältets metadata. Fälten ProductID, CategoryNameoch SupplierName markeras till exempel som skrivskyddade i ProductsDataTable och bör därför inte vara uppdaterade när du redigerar. För att hantera detta är dessa BoundFields ReadOnly-egenskaper inställda på true.
  • Egenskapen DataKeyNames tilldelas det underliggande objektets primära nyckelfält. Detta är viktigt när du använder GridView för att redigera eller ta bort data, eftersom den här egenskapen anger det fält (eller en uppsättning fält) som unikt identifierar varje post. Mer information om egenskapen, gå tillbaka till handledningen DataKeyNames.

Även om GridView kan bindas till ObjectDataSource via fönstret Egenskaper eller deklarativ syntax, måste du manuellt lägga till rätt BoundField och DataKeyNames-markering.

GridView-kontrollen ger inbyggt stöd för redigering och borttagning på radnivå. När du konfigurerar en GridView för att stödja borttagning läggs en kolumn med ta bort knappar. När slutanvändaren klickar på knappen Ta bort för en viss rad, följer en postback och GridView utför följande steg:

  1. ObjectDataSources värde(n) tilldelas DeleteParameters
  2. ObjectDataSource-metoden anropas Delete() och tar bort den angivna posten
  3. GridView binds om till ObjectDataSource genom att anropa dess Select() metod

De värden som tilldelats DeleteParameters är de värden som finns i fältet/fälten DataKeyNames för raden vars borttagningsknapp har klickats på. Därför är det viktigt att en GridView-egenskap DataKeyNames är korrekt inställd. Om den saknas kommer den DeleteParameters att tilldelas ett null värde i steg 1, vilket i sin tur inte kommer att resultera i några raderade poster i steg 2.

Anmärkning

Samlingen DataKeys lagras i GridView-kontrolltillståndet DataKeys , vilket innebär att värdena kommer att kommas ihåg över postback även om GridView-vytillståndet har inaktiverats. Det är dock mycket viktigt att visningstillståndet fortfarande är aktiverat för GridViews som stöder redigering eller borttagning (standardbeteendet). Om du anger egenskapen GridView till EnableViewStatefungerar redigerings- och borttagningsbeteendet false bra för en enskild användare, men om det finns samtidiga användare som tar bort data finns det en möjlighet att dessa samtidiga användare oavsiktligt kan ta bort eller redigera poster som de inte har för avsikt.

Samma varning gäller även för DetailsViews och FormViews.

Om du vill lägga till borttagningsfunktioner i en GridView går du helt enkelt till den smarta taggen och markerar kryssrutan Aktivera borttagning.

Markera kryssrutan Aktivera borttagning

Bild 10: Markera kryssrutan Aktivera borttagning

Om du markerar kryssrutan Aktivera borttagning från den smarta taggen läggs ett Kommandofält till i GridView. CommandField renderar en kolumn i GridView med knappar för att utföra en eller flera av följande uppgifter: välja en post, redigera en post och ta bort en post. Vi såg tidigare att CommandField var i aktion med att välja poster i huvud-/detaljguiden med hjälp av en valbar huvudrutnätvy med en details DetailView-självstudie .

Kommandofältet innehåller ett antal ShowXButton egenskaper som anger vilken serie knappar som visas i Kommandofältet. Genom att markera kryssrutan Aktivera borttagning har en CommandField med egenskapen ShowDeleteButton och true lagts till i GridViews kolumnsamling.

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

Tro det eller ej nu, vi är klara med att lägga till stöd för borttagning i GridView! Som bild 11 visar visas en kolumn med Ta bort knappar när du besöker den här sidan via en webbläsare.

Kommandofältet lägger till en kolumn med borttagningsknappar

Bild 11: Kommandofältet lägger till en kolumn med borttagningsknappar (Klicka om du vill visa en bild i full storlek)

Om du har byggt den här självstudien från grunden på egen hand kommer ett undantag att resultera när du testar denna sida genom att klicka på knappen Ta bort. Fortsätt läsa för att lära dig varför dessa undantag har genererats och hur du åtgärdar dem.

Anmärkning

Om du använder nedladdningen som medföljer den här handledningen har dessa problem redan tagits hand om. Jag rekommenderar dock att du läser igenom informationen nedan för att identifiera problem som kan uppstå och lämpliga lösningar.

Om du när du försöker ta bort en produkt får ett undantag vars meddelande liknar "ObjectDataSource 'ObjectDataSource1' inte kunde hitta en icke-generisk metod 'DeleteProduct' som har parametrar: productID, original_ProductID", har du förmodligen glömt att ta bort OldValuesParameterFormatString egenskapen från ObjectDataSource. Med den OldValuesParameterFormatString angivna egenskapen försöker ObjectDataSource skicka in båda productID parametrarna och original_ProductID indataparametrarna till DeleteProduct metoden. DeleteProductaccepterar dock bara en enda indataparameter, därav undantaget. Om du OldValuesParameterFormatString tar bort egenskapen (eller anger den till {0}) instrueras ObjectDataSource att inte försöka skicka den ursprungliga indataparametern.

Kontrollera att egenskapen OldValuesParameterFormatString har rensats

Bild 12: Kontrollera att egenskapen OldValuesParameterFormatString har rensats (klicka om du vill visa en bild i full storlek)

Även om du hade tagit bort OldValuesParameterFormatString egenskapen får du fortfarande ett undantag när du försöker ta bort en produkt med meddelandet : "DELETE-instruktionen stod i konflikt med REFERENS-villkoret "FK_Order_Details_Products". Northwind-databasen innehåller en sekundärnyckelbegränsning mellan Order Details tabellen och Products , vilket innebär att en produkt inte kan tas bort från systemet om det finns en eller flera poster för den Order Details i tabellen. Eftersom varje produkt i Northwind-databasen har minst en post i Order Detailskan vi inte ta bort några produkter förrän vi först tar bort produktens associerade orderinformationsposter.

En främmande nyckelbegränsning hindrar borttagningen av produkter

Bild 13: En begränsning för främmande nyckel förbjuder borttagning av produkter (klicka för att visa bilden i full storlek)

I vår handledning tar vi bort alla poster från tabellen Order Details. I ett verkligt program behöver vi antingen:

  • Ha en annan skärm för att hantera beställningsinformation.
  • Utöka metoden så att den DeleteProduct innehåller logik för att ta bort den angivna produktens orderinformation
  • Ändra SQL-frågan som används av TableAdapter så att den innehåller borttagning av den angivna produktens orderinformation

Nu ska vi ta bort alla poster från Order Details tabellen för att kringgå villkoret för sekundärnyckeln. Gå till Server Explorer i Visual Studio, högerklicka på NORTHWND.MDF noden och välj Ny fråga. Kör sedan följande SQL-instruktion i frågefönstret: DELETE FROM [Order Details]

Ta bort alla poster från tabellen Orderdetaljer

Bild 14: Ta bort alla poster från Order Details tabellen (Klicka för att visa bilden i full storlek)

Efter att du har rensat tabellen och klickat på knappen Ta bort tas produkten bort utan problem. Om klickandet på knappen Ta bort inte resulterar i att produkten tas bort, kontrollera att GridView-egenskapen DataKeyNames är inställd på primärnyckelfältet (ProductID).

Anmärkning

När du klickar på knappen Ta bort sker en återkoppling och posten tas bort. Detta kan vara farligt eftersom det är lätt att oavsiktligt klicka på fel rads Ta bort-knapp. I en framtida handledning kommer vi att se hur vi lägger till en bekräftelse på klientsidan när vi tar bort en post.

Redigera data med GridView

Förutom att ta bort ger GridView-kontrollen även inbyggt redigeringsstöd på radnivå. När du konfigurerar en GridView som stöd för redigering läggs en kolumn med Redigera knappar till. Om du klickar på knappen Redigera på en rad från slutanvändarens perspektiv blir raden redigerbar, cellerna omvandlas till textrutor som innehåller de befintliga värdena och ersätter knappen Redigera med knapparna Uppdatera och Avbryt. När de har gjort önskade ändringar kan slutanvändaren klicka på knappen Uppdatera för att checka in ändringarna eller knappen Avbryt för att ta bort dem. När du har klickat på Uppdatera eller Avbryt återgår GridView till dess förredigeringstillstånd.

Från vårt perspektiv som sidutvecklare, när slutanvändaren klickar på knappen Redigera för en viss rad, följer en postback och GridView utför följande steg:

  1. GridView:ens EditItemIndex-egenskap tilldelas indexet för raden vars redigeringsknapp har klickats
  2. GridView binds om till ObjectDataSource genom att anropa dess Select() metod
  3. Radindexet som motsvarar EditItemIndex återges i "redigerarläge". I detta läge ersätts knappen Redigera med knapparna Uppdatera och Avbryt, och BoundFields vars ReadOnly egenskaper är False (standard) visas som TextBox Web-kontroller där Text egenskaper är tilldelade datafältens värden.

Nu returneras markup till webbläsaren, som möjliggör för slutanvändaren att göra ändringar i radens data. När användaren klickar på knappen Uppdatera sker ett återanrop och GridView utför följande steg:

  1. Värdena från ObjectDataSource tilldelas de värden som anges av slutanvändaren i GridViews redigeringsgränssnitt
  2. ObjectDataSource-metoden anropas Update() och uppdaterar den angivna posten
  3. GridView binds om till ObjectDataSource genom att anropa dess Select() metod

De primära nyckelvärden som tilldelats UpdateParameters i steg 1 kommer från de värden som anges i DataKeyNames egenskapen, medan de icke-primära nyckelvärdena kommer från texten i TextBox Web-kontrollerna för den redigerade raden. Precis som vid borttagning är det viktigt att en GridView-egenskap DataKeyNames är korrekt inställd. Om det saknas kommer primärnyckelvärdet UpdateParameters att tilldelas ett null värde i steg 1, vilket i sin tur inte resulterar i några uppdaterade poster i steg 2.

Redigeringsfunktioner kan aktiveras genom att bara markera kryssrutan Aktivera redigering i GridViews smarta tagg.

Markera kryssrutan Aktivera redigering

Bild 15: Markera kryssrutan Aktivera redigering

Om du markerar kryssrutan Aktivera redigering läggs ett Kommandofält (om det behövs) och dess ShowEditButton egenskap anges till true. Som vi såg tidigare innehåller CommandField ett antal ShowXButton egenskaper som anger vilken serie knappar som visas i Kommandofältet. Om du markerar kryssrutan Aktivera redigering läggs ShowEditButton egenskapen till i det befintliga Kommandofältet:

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

Det är allt som krävs för att lägga till rudimentärt redigeringsstöd. Som bild 16 visar, är redigeringsgränssnittet ganska primitivt. Varje BoundField vars ReadOnly-egenskap är inställd på false (standardvärdet) återges som en textruta. Detta inkluderar fält som CategoryID och SupplierID, som är nycklar till andra tabeller.

Om du klickar på knappen Redigera i Chai visas raden i redigeringsläge

Bild 16: Om du klickar på knappen Redigera i Chai visas raden i redigeringsläge (Klicka om du vill visa en bild i full storlek)

Förutom att be användarna redigera främmande nyckelvärden direkt, saknas redigeringsgränssnittet på följande sätt:

  • Om användaren anger en CategoryID eller SupplierID som inte finns i databasen UPDATE bryter den mot en begränsning för sekundärnyckel, vilket gör att ett undantag utlöses.
  • Redigeringsgränssnittet innehåller ingen verifiering. Om du inte anger ett obligatoriskt värde (till exempel ProductName), eller anger ett strängvärde där ett numeriskt värde förväntas (till exempel att ange "För mycket!" i UnitPrice textrutan), genereras ett undantag. En framtida handledning kommer att undersöka hur du lägger till valideringskontroller i användargränssnittet för redigering.
  • För närvarande måste alla produktfält som inte är skrivskyddade ingå i GridView. Om vi skulle ta bort ett fält från GridView, till exempel UnitPrice, när vi uppdaterar data skulle GridView inte ange UnitPriceUpdateParameters värdet, vilket skulle ändra databaspostens UnitPrice till ett NULL värde. Om ett obligatoriskt fält, till exempel ProductName, tas bort från GridView, misslyckas uppdateringen på samma sätt med samma "Kolumn "ProductName" tillåter inte null-undantag som nämns ovan.
  • Formateringen för redigeringsgränssnittet lämnar mycket att önska. UnitPrice Visas med fyra decimaler. Helst skulle CategoryID- och SupplierID-värdena innehålla listrutor som listar kategorierna och leverantörerna i systemet.

Det här är alla brister som vi måste leva med för tillfället, men som kommer att åtgärdas i framtida självstudier.

Infoga, redigera och ta bort data med DetailsView

Som vi har sett i tidigare självstudier visar DetailsView-kontrollen en post i taget och tillåter, precis som GridView, redigering och borttagning av den post som visas för närvarande. Både slutanvändarens erfarenhet av att redigera och ta bort objekt från en DetailsView och arbetsflödet från ASP.NET sidan är identisk med GridView. Där DetailsView skiljer sig från GridView är att den även ger inbyggt infogningsstöd.

Om du vill demonstrera funktionerna för dataändring i GridView börjar du med att lägga till en DetailsView på Basics.aspx sidan ovanför det befintliga GridView och binda den till den befintliga ObjectDataSource via DetailsViews smarta tagg. Rensa sedan DetailsView-egenskaperna Height och Width och markera alternativet Aktivera paginering från den smarta taggen. Om du vill aktivera redigering, infogning och borttagning av stöd markerar du kryssrutan Aktivera redigering, Aktivera infogning och Aktivera borttagning i den smarta taggen.

Skärmbild som visar fönstret DetailsView Tasks med kryssrutan Aktivera infogning, Aktivera redigering och Aktivera borttagning markerad.

Bild 17: Konfigurera DetailsView så att den stöder redigering, infogning och borttagning

Precis som med GridView lägger du till stöd för redigering, infogning eller borttagning av ett CommandField i DetailsView, som följande deklarativa syntax visar:

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

Observera att för DetailsView visas CommandField i slutet av samlingen Kolumner som standard. Eftersom DetailsView-fälten återges som rader visas Kommandofältet som en rad med knapparna Infoga, Redigera och Ta bort längst ned i DetailsView.

Skärmbild av DetailsView med Kommandofältet som visas som en nedre rad med knapparna Infoga, Redigera och Ta bort.

Bild 18: Konfigurera DetailsView så att den stöder redigering, infogning och borttagning (Klicka om du vill visa en bild i full storlek)

Om du klickar på knappen Ta bort startas samma sekvens av händelser som med GridView: en postback, följt av att DetailsView fyller sin ObjectDataSource baserat på DeleteParameters och DataKeyNames värdena, och avslutas med ett anrop av sin ObjectDataSource Delete() metod, som faktiskt tar bort produkten från databasen. Redigering i DetailsView fungerar också på ett sätt som är identiskt med GridView.

För infogning visas slutanvändaren med en ny knapp som, när den klickas, återger DetailsView i "infogningsläge". Med "infogningsläge" ersätts knappen Ny med knapparna Infoga och Avbryt och endast de BoundFields vars InsertVisible egenskap är inställd på true (standard) visas. De datafält som identifieras som automatiskt inkrementella fält, exempel ProductID, har sin egenskap InsertVisible inställd på false vid bindning av DetailsView till datakällan via smarta taggen.

När du binder en datakälla till en DetailsView via den smarta taggen anger InsertVisible Visual Studio egenskapen till false endast för automatiskt inkrementella fält. Skrivskyddade fält, som CategoryName och SupplierName, visas i användargränssnittet i "infogningsläge" såvida inte deras InsertVisible-egenskap uttryckligen är inställd på false. Ta en stund att ange de här två fältens InsertVisible egenskaper till false, antingen via DetailsViews deklarativa syntax eller via länken Redigera fält i den smarta taggen. Bild 19 visar hur du ställer in InsertVisible-egenskaperna till false genom att klicka på länken Redigera fält.

Skärmbild som visar fönstret Fält med egenskapen InsertVisible inställd på False.

Bild 19: Northwind Traders erbjuder nu Acme Tea (klicka för att visa bild i full storlek)

När du har angett InsertVisible egenskaperna visar du sidan Basics.aspx i en webbläsare och klickar på knappen Nytt. Bild 20 visar DetailsView när du lägger till en ny dryck, Acme Tea, till vår produktlinje.

Skärmbild som visar DetailsView för sidan Basics.aspx i en webbläsare.

Bild 20: Northwind Traders erbjuder nu Acme Tea (klicka för att visa bild i full storlek)

När du har angett informationen för Acme Tea och klickat på knappen Infoga, sker en postback och den nya posten läggs till i databastabellen Products. Eftersom den här DetailsView listar produkterna i den ordning de finns i databastabellen måste vi gå till den sista produkten för att kunna se den nya produkten.

Information om Acme Tea

Bild 21: Information om Acme Tea (Klicka om du vill visa en bild i full storlek)

Anmärkning

Egenskapen CurrentMode i DetailsView anger vilket gränssnitt som visas och kan vara något av följande värden: Edit, Inserteller ReadOnly. Egenskapen DefaultMode anger läget som DetailsView återgår till när en redigering eller infogning har slutförts och är användbar för att visa en DetailsView som är permanent i redigerings- eller infogningsläge.

Peka och klicka på infognings- och redigeringsfunktionerna i DetailsView har samma begränsningar som GridView: användaren måste ange befintliga CategoryID värden och SupplierID värden via en textruta. Gränssnittet saknar valideringslogik. Alla produktfält som inte tillåter NULL värden eller som inte har något standardvärde som anges på databasnivå måste ingå i infogningsgränssnittet. och så vidare.

De tekniker som vi kommer att undersöka för att utöka och förbättra GridViews redigeringsgränssnitt i framtida artiklar kan även tillämpas på DetailsView-kontrollens redigerings- och infogningsgränssnitt.

Använda FormView för ett mer flexibelt användargränssnitt för datamodifiering

FormView har inbyggt stöd för infogning, redigering och borttagning av data, men eftersom den använder mallar i stället för fält finns det ingen plats att lägga till BoundFields- eller CommandField-kontrollerna som används av kontrollerna GridView och DetailsView för att tillhandahålla datamodifieringsgränssnittet. I stället måste webbkontrollerna för att samla in användarindata när du lägger till ett nytt objekt eller redigerar ett befintligt objekt tillsammans med knapparna Nytt, Redigera, Ta bort, Infoga, Uppdatera och Avbryt läggas till manuellt i lämpliga mallar. Lyckligtvis skapar Visual Studio automatiskt det gränssnitt som behövs när du binder FormView till en datakälla via listrutan i den smarta taggen.

För att illustrera dessa tekniker börjar du med att lägga till en FormView på Basics.aspx sidan och från Den smarta taggen i FormView binder du den till ObjectDataSource som redan har skapats. Detta genererar kontrollerna EditItemTemplate, InsertItemTemplateoch ItemTemplate för FormView med TextBox Web för att samla in användarens indata- och knappwebbkontroller för knapparna Ny, Redigera, Ta bort, Infoga, Uppdatera och Avbryt. Dessutom är egenskapen FormView DataKeyNames inställd på primärnyckelfältet (ProductID) för objektet som returneras av ObjectDataSource. Kontrollera slutligen alternativet Aktivera sidindelning i FormViews smarta tagg.

Följande visar deklarativ markup för FormView's ItemTemplate efter att FormView har bundits till ObjectDataSource. Som standard är varje icke-booleskt värdeproduktfält bundet Text till egenskapen för en etikettwebbkontroll medan varje booleskt värdefält (Discontinued) är bundet Checked till egenskapen för en inaktiverad CheckBox-webbkontroll. För att knapparna Ny, Redigera och Ta bort ska utlösa ett visst FormView-beteende när du klickar är det absolut nödvändigt att deras CommandName värden anges till New, EditDeleterespektive .

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

Bild 22 visar FormView ItemTemplate när den visas via en webbläsare. Varje produktfält visas med knapparna Ny, Redigera och Ta bort längst ned.

Defaut FormView ItemTemplate listar varje produktfält tillsammans med knapparna Ny, Redigera och Ta bort

Bild 22: Defaut FormView ItemTemplate visar varje produktfält tillsammans med knapparna Ny, Redigera och Ta bort (Klicka om du vill visa en bild i full storlek)

Precis som med GridView och DetailsView, klickar du på knappen Ta bort eller någon knapp, LinkButton eller ImageButton vars CommandName egenskap är inställd på Ta bort orsakar en postback, fyller i ObjectDataSources DeleteParameters baserat på FormView-värdet DataKeyNames och anropar ObjectDataSource-metoden Delete() .

När Redigera-knappen klickas, sker ett postback-återanrop och data binds igen till EditItemTemplate, som ansvarar för att rendera redigeringsgränssnittet. Det här gränssnittet innehåller webbkontroller för redigering av data tillsammans med knapparna Uppdatera och Avbryt. Standardvärdet EditItemTemplate som genereras av Visual Studio innehåller en etikett för alla automatiskt inkrementella fält (ProductID), en textruta för varje icke-booleskt värdefält och en kryssruta för varje booleskt värdefält. Det här beteendet liknar de automatiskt genererade BoundFields i kontrollerna GridView och DetailsView.

Anmärkning

Ett litet problem med den automatiska genereringen av EditItemTemplate i FormView är att den renderar TextBox webbkontroller för fält som är skrivskyddade, till exempel CategoryName och SupplierName. Vi får se hur du tar hänsyn till detta inom kort.

TextBox-kontrollerna i EditItemTemplate har sin Text-egenskap bunden till värdet för motsvarande datafält genom dubbelriktad databindning. Dubbelriktad databindning, som anges av <%# Bind("dataField") %>, utför databindning både när du binder data till mallen och när du fyller i ObjectDataSources parametrar för att infoga eller redigera poster. När användaren klickar på knappen Redigera från ItemTemplateBind() returnerar metoden det angivna datafältvärdet. När användaren har gjort sina ändringar och klickar på uppdatera, tillämpas de värden som skickas tillbaka och som motsvarar de datafält som anges med Bind() på ObjectDataSource's UpdateParameters. Alternativt hämtar enkelriktad databindning, som anges av <%# Eval("dataField") %>, endast datafältvärdena när data binds till mallen och returnerar inte de användarinmatningsvärdena till datakällans parametrar vid postback.

Här är den deklarativa markeringen som visar FormViews EditItemTemplate. Observera att Bind() metoden används i syntaxen för databindning här och att webbkontrollerna Uppdatera och Avbryt knapp har sina CommandName egenskaper angivna.

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

I det här läget kommer vårt EditItemTemplate att kasta ett undantagsfel om vi försöker använda det. Problemet är att fälten CategoryName och SupplierName återges som TextBox Web-kontroller i EditItemTemplate. Vi behöver antingen ändra textrutorna till Etiketter eller ta bort dem helt och hållet. Vi tar helt enkelt bort dem helt från EditItemTemplate.

Bild 23 visar FormView i en webbläsare när knappen Redigera har klickats för Chai. Observera att fälten SupplierName och som visas i CategoryName inte längre finns, eftersom vi just har tagit bort dem från ItemTemplateEditItemTemplate . När du klickar på knappen Uppdatera fortsätter FormView genom samma stegsekvens som kontrollerna GridView och DetailsView.

Som standard visar EditItemTemplate varje redigerbart produktfält som en textruta eller kryssruta

Bild 23: Som standard EditItemTemplate visar varje redigerbart produktfält som en textruta eller kryssruta (Klicka om du vill visa en bild i full storlek)

När knappen Infoga har klickats på följer formvyns ItemTemplate ett återanrop. Det finns dock inga data kopplade till FormView eftersom en ny post läggs till. Gränssnittet InsertItemTemplate innehåller webbkontrollerna för att lägga till en ny post tillsammans med knapparna Infoga och Avbryt. Standardvärdet InsertItemTemplate som genereras av Visual Studio innehåller en textruta för varje icke-booleskt värdefält och en kryssruta för varje booleskt värdefält, ungefär som det automatiskt genererade EditItemTemplategränssnittet. TextBox-kontrollerna har sin Text egenskap bunden till värdet för motsvarande datafält med hjälp av dubbelriktad databindning.

Här är den deklarativa markeringen som visar FormViews InsertItemTemplate. Observera att Bind() metoden används i syntaxen för databindning här och att webbkontrollerna Infoga och Avbryt knapp har sina CommandName egenskaper angivna.

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

Det finns en subtilitet i FormViews automatiska generering av InsertItemTemplate. Mer specifikt skapas TextBox Web-kontrollerna även för de fält som är skrivskyddade, till exempel CategoryName och SupplierName. Precis som med EditItemTemplatemåste vi ta bort dessa textrutor från InsertItemTemplate.

Bild 24 visar FormView i en webbläsare när du lägger till en ny produkt, Acme Coffee. Observera att fälten SupplierName och CategoryName som visas i ItemTemplate inte längre finns, eftersom vi just har tagit bort dem. När knappen Infoga klickas fortsätter FormView genom samma stegsekvens som DetailsView-kontrollen och lägger till en ny post i Products tabellen. Bild 25 visar Acme Coffee-produktens information i FormView efter att den har infogats.

InsertItemTemplate dikterar FormView-infogningsgränssnittet

Bild 24: InsertItemTemplate Dikterar FormView-införandegränssnittet (Klicka för att visa bilden i full storlek)

Information om ny produkt, Acme Coffee, visas i FormView

Bild 25: Information om ny produkt, Acme Coffee, visas i FormView (Klicka om du vill visa en bild i full storlek)

Genom att avgränsa gränssnitt för endast läsning, redigering och infogning i tre separata mallar, ger FormView en finare grad av kontroll över dessa gränssnitt än DetailsView och GridView.

Anmärkning

Liksom DetailsView anger egenskapen FormView CurrentMode gränssnittet som visas och dess DefaultMode egenskap anger läget som FormView återgår till när en redigering eller infogning har slutförts.

Sammanfattning

I den här självstudien har vi gått igenom grunderna för att infoga, redigera och ta bort data med hjälp av GridView, DetailsView och FormView. Alla tre av dessa kontroller ger en viss nivå av inbyggda datamodifieringsfunktioner som kan användas utan att skriva en enda kodrad på ASP.NET-sidan tack vare datawebbkontrollerna och ObjectDataSource. De enkla peka och klicka-teknikerna renderar dock ett ganska skört och naivt användargränssnitt för datamodifiering. För att tillhandahålla validering, mata in programmatiska värden, hantera undantag på ett korrekt sätt, anpassa användargränssnittet och så vidare måste vi förlita oss på en mängd tekniker som kommer att diskuteras under de kommande självstudierna.

Lycka till med programmerandet!

Om författaren

Scott Mitchell, författare till sju ASP/ASP.NET-böcker och grundare av 4GuysFromRolla.com, har arbetat med Microsofts webbtekniker sedan 1998. Scott arbetar som oberoende konsult, tränare och författare. Hans senaste bok är Sams Teach Yourself ASP.NET 2.0 på 24 timmar. Han kan nås på mitchell@4GuysFromRolla.com.