Dela via


Undersöka händelser som är associerade med infogning, uppdatering och borttagning (VB)

av Scott Mitchell

Ladda ned PDF

I den här självstudien undersöker vi hur du använder de händelser som inträffar före, under och efter en infognings-, uppdaterings- eller borttagningsåtgärd för en ASP.NET datawebbkontroll. Vi kommer också att se hur du anpassar redigeringsgränssnittet för att endast uppdatera en delmängd av produktfälten.

Inledning

När du använder de inbyggda funktionerna för att infoga, redigera eller ta bort funktioner i kontrollerna GridView, DetailsView eller FormView visas en mängd olika steg när slutanvändaren slutför processen med att lägga till en ny post eller uppdatera eller ta bort en befintlig post. Som vi diskuterade i föregående självstudie, när en rad redigeras i GridView ersätts knappen Redigera med knapparna Uppdatera och Avbryt och BoundFields förvandlas till Textrutor. När slutanvändaren uppdaterar data och klickar på Uppdatera utförs följande steg vid efteråterställning:

  1. GridView fyller dess ObjectDataSource's UpdateParameters med den redigerade postens unika identifieringsfält (via DataKeyNames-egenskapen) tillsammans med de värden som angetts av användaren.
  2. GridView anropar metoden ObjectDataSource Update() , som i sin tur anropar lämplig metod i det underliggande objektet (ProductsDAL.UpdateProducti vår tidigare självstudie)
  3. Underliggande data, som nu innehåller de uppdaterade ändringarna, returneras till GridView

Under den här stegsekvensen utlöses ett antal händelser, vilket gör att vi kan skapa händelsehanterare för att lägga till anpassad logik där det behövs. Före steg 1 utlöses till exempel GridView-händelsen RowUpdating . Vi kan nu avbryta uppdateringsbegäran om det finns ett verifieringsfel. Update() När metoden anropas utlöses ObjectDataSource-händelsenUpdating, vilket ger en möjlighet att lägga till eller anpassa värdena för någon av UpdateParameters. När ObjectDataSources underliggande objekts metod har slutförts utlöses ObjectDataSource-händelsen Updated . En händelsehanterare för Updated händelsen kan granska informationen om uppdateringsåtgärden, till exempel hur många rader som påverkades och om ett undantag inträffade eller inte. Efter steg 2 utlöses slutligen GridView-händelsen. En händelsehanterare för den här händelsen kan undersöka ytterligare information om uppdateringsåtgärden som just utförts RowUpdated .

Bild 1 visar den här serien med händelser och steg när du uppdaterar en GridView. Händelsemönstret i bild 1 är inte unikt för uppdatering med en GridView. Infogning, uppdatering eller borttagning av data från GridView, DetailsView eller FormView påskyndar samma sekvens av händelser före och efter nivå för både datawebbkontrollen och ObjectDataSource.

En serie för- och efterhändelser utlöses när data uppdateras i en GridView

Bild 1: En serie för- och efterhändelser utlöses när data uppdateras i en GridView (Klicka om du vill visa en bild i full storlek)

I den här självstudien undersöker vi hur du använder dessa händelser för att utöka de inbyggda funktionerna för infogning, uppdatering och borttagning av ASP.NET datawebbkontroller. Vi kommer också att se hur du anpassar redigeringsgränssnittet för att endast uppdatera en delmängd av produktfälten.

Steg 1: Uppdatera fälten i en produktsProductNameochUnitPrice

I redigeringsgränssnitten från föregående handledning behövde alla produktfält som inte var skrivskyddade inkluderas. Om vi skulle ta bort ett fält från GridView – till exempel QuantityPerUnit – vid uppdatering av data skulle datawebbkontrollen inte ange Värdet för ObjectDataSource QuantityPerUnitUpdateParameters . ObjectDataSource skulle sedan skicka in ett värde Nothing till metoden UpdateProduct i Business Logic Layer (BLL), som skulle ändra kolumnens QuantityPerUnit värde till NULL. Om ett obligatoriskt fält, till exempel ProductName, tas bort från redigeringsgränssnittet, misslyckas uppdateringen på samma sätt med undantaget "Kolumnen ProductName tillåter inte nulls". Orsaken till det här beteendet var att ObjectDataSource konfigurerades för att anropa ProductsBLL klassens UpdateProduct metod, som förväntade sig en indataparameter för vart och ett av produktfälten. Därför innehöll ObjectDataSources UpdateParameters samling en parameter för var och en av metodens indataparametrar.

Om vi vill tillhandahålla en datawebbkontroll som gör att slutanvändaren endast kan uppdatera en delmängd av fälten måste vi antingen programmatiskt ange de saknade UpdateParameters värdena i ObjectDataSources Updating händelsehanterare eller skapa och anropa en BLL-metod som endast förväntar sig en delmängd av fälten. Nu ska vi utforska den här senare metoden.

Mer specifikt ska vi skapa en sida som bara visar fälten ProductName och UnitPrice i en redigerbar GridView. Det här GridView-redigeringsgränssnittet tillåter endast att användaren uppdaterar de två fälten som visas och ProductNameUnitPrice. Eftersom det här redigeringsgränssnittet endast tillhandahåller en delmängd av en produkts fält behöver vi antingen skapa en ObjectDataSource som använder den befintliga BLL-metoden UpdateProduct och har de saknade produktfältvärdena som angetts programmatiskt i händelsehanteraren Updating , eller så måste vi skapa en ny BLL-metod som endast förväntar sig den delmängd av fält som definierats i GridView. I den här självstudien ska vi använda det senare alternativet och skapa en överlagring av UpdateProduct metoden, en som bara tar in tre indataparametrar: productName, unitPriceoch productID:

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

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

    If products.Count = 0 Then
        Return False
    End If

    Dim product As Northwind.ProductsRow = products(0)

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

    Dim rowsAffected As Integer = Adapter.Update(product)

    Return rowsAffected = 1
End Function

Precis som den ursprungliga UpdateProduct metoden börjar den här överbelastningen med att kontrollera om det finns en produkt i databasen med angiven ProductID. Annars returneras False, vilket anger att begäran om att uppdatera produktinformationen misslyckades. Annars uppdateras den befintliga produktpostens ProductName och UnitPrice fälten i enlighet med detta och genomför uppdateringen genom att anropa TableAdapter-metoden Update() och skicka in instansen ProductsRow .

Med det här tillägget till vår ProductsBLL klass är vi redo att skapa det förenklade GridView-gränssnittet. DataModificationEvents.aspx Öppna i EditInsertDelete mappen och lägg till en GridView på sidan. Skapa ett nytt ObjectDataSource och konfigurera den att använda ProductsBLL klassen, där dess Select() metod mappas till GetProducts och dess Update() metod mappas till UpdateProduct överlagringen som endast accepterar indata parametrarna productName, unitPrice, och productID. Bild 2 visar guiden Skapa datakälla när ObjectDataSource-metoden Update() mappas till den nya ProductsBLL-metodöverlagringen i UpdateProduct-klassen.

Mappa metoden Update() för ObjectDataSource till den nya UpdateProduct-överlagring

Bild 2: Mappa ObjectDataSource-metoden Update() till den nya UpdateProduct överlagringen (klicka om du vill visa en bild i full storlek)

Eftersom vårt exempel först bara behöver möjligheten att redigera data, men inte infoga eller ta bort poster, kan du ta en stund att uttryckligen ange att ObjectDataSources Insert() och Delete() metoder inte ska mappas till någon av ProductsBLL klassens metoder genom att gå till flikarna INSERT och DELETE och välja (Ingen) från listrutan.

Välj (Ingen) i Drop-Down-listan för flikarna INSERT och DELETE

Bild 3: Välj (Ingen) Från Drop-Down-listan för flikarna INSERT och DELETE (Klicka om du vill visa en bild i full storlek)

När du har slutfört den här guiden markerar du kryssrutan Aktivera redigering från GridViews smarta tagg.

I och med slutförandet av guiden Skapa datakälla och bindning till GridView har Visual Studio skapat den deklarativa syntaxen för båda kontrollerna. Gå till källvyn för att inspektera ObjectDataSources deklarativa markering, som visas nedan:

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

Eftersom det inte finns några mappningar för ObjectDataSources Insert() och Delete() metoder finns det inga InsertParameters eller DeleteParameters avsnitt. Dessutom, eftersom Update() metoden mappas till den UpdateProduct metodöverbelastning som endast accepterar tre indataparametrar, så har UpdateParameters avsnittet bara tre Parameter instanser.

Observera att egenskapen ObjectDataSource är OldValuesParameterFormatString inställd på original_{0}. Den här egenskapen anges automatiskt av Visual Studio när du använder guiden Konfigurera datakälla. Men eftersom våra BLL-metoder inte förväntar sig att det ursprungliga ProductID värdet ska skickas, tar du bort den här egenskapstilldelningen helt från ObjectDataSources deklarativa syntax.

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 kommer att anges till en tom sträng. Ta antingen bort egenskapen helt från den deklarativa syntaxen eller från fönstret Egenskaper anger du värdet till standardvärdet . {0}

Medan ObjectDataSource bara har UpdateParameters för produktens namn, pris och ID, har Visual Studio lagt till ett BoundField- eller CheckBoxField i GridView för var och en av produktens fält.

GridView innehåller ett BoundField- eller CheckBoxField-fält för var och en av produktens fält

Bild 4: GridView innehåller ett BoundField- eller CheckBoxField-fält för var och en av produktens fält (Klicka om du vill visa en bild i full storlek)

När slutanvändaren redigerar en produkt och klickar på knappen Uppdatera räknar GridView upp de fält som inte var skrivskyddade. Sedan anges värdet för motsvarande parameter i ObjectDataSources UpdateParameters samling till det värde som användaren har angett. Om det inte finns någon motsvarande parameter lägger GridView till en i samlingen. Om vår GridView innehåller BoundFields och CheckBoxFields för alla produktens fält, kommer ObjectDataSource därför att anropa överbelastningen UpdateProduct som tar in alla dessa parametrar, trots att ObjectDataSources deklarativa markering endast anger tre indataparametrar (se bild 5). På samma sätt, om det finns en kombination av icke-skrivskyddade produktfält i GridView som inte motsvarar indataparametrarna för en UpdateProduct överlagring, utlöses ett undantag när du försöker uppdatera.

GridView lägger till parametrar i ObjectDataSources UpdateParameters-samling

Bild 5: GridView lägger till parametrar i ObjectDataSources UpdateParameters samling (Klicka om du vill visa en bild i full storlek)

För att säkerställa att ObjectDataSource anropar den UpdateProduct överlagring som bara tar in produktens namn, pris och ID måste vi begränsa GridView till att ha redigerbara fält för bara ProductName och UnitPrice. Detta kan åstadkommas genom att ta bort de andra BoundFields och CheckBoxFields genom att ange de andra fältens ReadOnly egenskap till True, eller genom någon kombination av de två. I den här självstudien tar vi helt enkelt bort alla GridView-fält utom ProductName BoundFields UnitPrice , varefter GridViews deklarativa markering ser ut så här:

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

Även om överbelastningen UpdateProduct förväntar sig tre indataparametrar, har vi bara två BoundFields i vår GridView. Det beror på att productID indataparametern är ett primärnyckelvärde och skickas genom värdet DataKeyNames för egenskapen för den redigerade raden.

Vår GridView, tillsammans med överlagringen UpdateProduct , gör det möjligt för en användare att redigera bara namnet och priset på en produkt utan att förlora något av de andra produktfälten.

Gränssnittet tillåter redigering av bara produktens namn och pris

Bild 6: Gränssnittet tillåter redigering bara produktens namn och pris (Klicka om du vill visa en bild i full storlek)

Anmärkning

Som vi gick igenom i den föregående självstudien är det mycket viktigt att rutnätsvyns visningstillstånd är aktiverat (standardbeteendet). Om du anger egenskapen GridView EnableViewState till falseriskerar du att samtidiga användare oavsiktligt tar bort eller redigerar poster.

UnitPriceFörbättra formateringen

Även om GridView-exemplet som visas i bild 6 fungerar formateras UnitPrice fältet inte alls, vilket resulterar i en prisvisning som saknar valutasymboler och har fyra decimaler. Om du vill använda en valutaformatering för de icke-redigerbara raderna, ställ in egenskapen UnitPrice för DataFormatString till {0:c} och dess egenskap HtmlEncode till False.

Ange egenskaper för UnitPrices DataFormatString och HtmlEncode i enlighet med detta

Bild 7: Ange UnitPrices DataFormatString och HtmlEncode därefter egenskaper (Klicka för att visa bilden i full storlek)

Med den här ändringen formaterar de icke-redigerbara raderna priset som en valuta. Den redigerade raden visar dock fortfarande värdet utan valutasymbolen och med fyra decimaler.

De icke-redigerbara raderna är nu formaterade som valutavärden

Bild 8: De icke-redigerbara raderna är nu formaterade som valutavärden (Klicka om du vill visa en bild i full storlek)

Formateringsinstruktionerna som specificeras i egenskapen DataFormatString kan tillämpas på redigeringsgränssnittet genom att sätta BoundField-egenskapen till ApplyFormatInEditMode (standardvärdet är True). Ta en stund att ange den här egenskapen till True.

Ange egenskapen ApplyFormatInEditMode för UnitPrice BoundField till True

Bild 9: Ange UnitPrice egenskapen BoundField ApplyFormatInEditMode till True (Klicka om du vill visa en bild i full storlek)

Med den här ändringen formateras även värdet för det UnitPrice som visas på den redigerade raden som valuta.

Skärmbild av GridView som visar den redigerade radens UnitPrice-värde formaterat som en valuta.

Bild 10: Den redigerade radens UnitPrice värde är nu formaterat som en valuta (Klicka om du vill visa en bild i full storlek)

Att uppdatera en produkt med valutasymbolen i textrutan, till exempel 19,00 USD, genererar dock en FormatException. När GridView försöker tilldela de användarinlevererade värdena till ObjectDataSources UpdateParameters samling kan den inte konvertera strängen UnitPrice "$19.00" till den Decimal som krävs av parametern (se bild 11). För att åtgärda detta kan vi skapa en händelsehanterare för GridView-händelsen RowUpdating och låta den tolka det användartillhandahållna UnitPrice som ett valutaformaterat Decimal.

Händelsen i GridView RowUpdating accepterar som den andra parametern ett objekt av typen GridViewUpdateEventArgs, som innehåller en NewValues ordlista som en av dess egenskaper som innehåller de användaringivna värdena som är redo att tilldelas till ObjectDataSources UpdateParameters samling. Vi kan skriva över det befintliga UnitPrice värdet i NewValues samlingen med ett decimalvärde parsat med hjälp av valutaformatet med följande kodrader i RowUpdating händelsehanteraren:

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

Om användaren har angett ett UnitPrice värde (till exempel "$19.00" skrivs det här värdet över med decimalvärdet som beräknas med Decimal.Parsa och parsar värdet som en valuta. Detta parsar decimaltecknet korrekt i händelse av valutasymboler, kommatecken, decimaltecken och så vidare, och använder NumberStyles-uppräkningen i namnområdet System.Globalization .

Bild 11 visar både problemet som orsakas av valutasymboler i den användaringivna UnitPrice, tillsammans med hur GridViews RowUpdating händelsehanterare kan användas för att parsa sådana indata korrekt.

Diagram som visar hur ObjectDataSource bearbetar fältet UnitPrice och hur RowUpdate-händelsehanteraren för GridView konverterar en sträng till en decimal.

Bild 11: Den redigerade radens UnitPrice värde är nu formaterat som en valuta (Klicka om du vill visa en bild i full storlek)

Steg 2: FörbudNULL UnitPrices

Databasen är konfigurerad för att tillåta NULL värden i Products tabellens UnitPrice kolumn, men vi kanske vill förhindra att användare som besöker den här sidan anger ett NULLUnitPrice värde. Om en användare inte kan ange ett UnitPrice värde vid redigering av en produktrad i stället för att spara resultatet i databasen vill vi visa ett meddelande som informerar användaren om att alla redigerade produkter måste ha ett angivet pris via den här sidan.

Objektet GridViewUpdateEventArgs som skickas till GridViews RowUpdating händelsehanterare innehåller en Cancel egenskap som, om det är inställt på True, avslutar uppdateringsprocessen. Nu ska vi utöka händelsehanteraren genom att sätta RowUpdating till e.Cancel och visa ett meddelande som förklarar varför om värdet på True i UnitPrice-kollektionen har värdet NewValues.

Börja med att lägga till en etikettwebbkontroll på sidan med namnet MustProvideUnitPriceMessage. Den här etikettkontrollen visas om användaren inte kan ange ett UnitPrice värde när en produkt uppdateras. Ange egenskapen Etikett Text till "Du måste ange ett pris för produkten". Jag har också skapat en ny CSS-klass med Styles.css namnet Warning med följande definition:

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

Slutligen, ställ in Label-ens CssClass-egenskap till Warning. Nu bör designern visa varningsmeddelandet i en röd, fet stil, kursiv, extra stor teckenstorlek ovanför GridView, enligt bild 12.

En etikett har lagts till ovanför GridView

Bild 12: En etikett har lagts till ovanför GridView (klicka om du vill visa en bild i full storlek)

Som standard bör den här etiketten vara dold, så ange dess Visible egenskap till False i Page_Load händelsehanteraren:

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

Om användaren försöker uppdatera en produkt utan att ange UnitPricevill vi avbryta uppdateringen och visa varningsetiketten. Utöka GridView-händelsehanteraren RowUpdating på följande sätt:

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

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

        e.Cancel = True
    End If
End Sub

Om en användare försöker spara en produkt utan att ange ett pris avbryts uppdateringen och ett användbart meddelande visas. Även om databasen (och affärslogik) tillåter NULLUnitPrice s, gör den här specifika ASP.NET sidan inte det.

En användare kan inte lämna UnitPrice tom

Bild 13: En användare kan inte lämna UnitPrice tom (Klicka om du vill visa en bild i full storlek)

Hittills har vi sett hur du använder GridView-händelsen RowUpdating för att programmatiskt ändra parametervärdena som tilldelats till ObjectDataSources UpdateParameters samling samt hur du avbryter uppdateringsprocessen helt och hållet. Dessa begrepp överförs till kontrollerna DetailsView och FormView och gäller även för infogning och borttagning.

Dessa uppgifter kan också utföras på ObjectDataSource-nivå via händelsehanterare för dess Inserting, Updatingoch Deleting händelser. Dessa händelser utlöses innan den associerade metoden för det underliggande objektet anropas och ger en möjlighet att ändra insamlingen av indataparametrar eller avbryta åtgärden direkt. Händelsehanterarna för dessa tre händelser skickas ett objekt av typen ObjectDataSourceMethodEventArgs som har två egenskaper av intresse:

  • Avbryt, vilket, om det är inställt på True, avbryter den åtgärd som utförs
  • InputParameters, som är samlingen av InsertParameters, UpdateParameters, eller DeleteParameters, beroende på om händelsehanteraren är för Inserting-händelsen, Updating-händelsen, eller Deleting-händelsen

För att illustrera hur du arbetar med parametervärdena på ObjectDataSource-nivån ska vi ta med en DetailsView på vår sida som gör att användarna kan lägga till en ny produkt. Den här DetailsView används för att tillhandahålla ett gränssnitt för att snabbt lägga till en ny produkt i databasen. Om du vill behålla ett konsekvent användargränssnitt när du lägger till en ny produkt tillåter vi att användaren endast anger värden för fälten ProductName och UnitPrice . Som standard anges de värden som inte anges i DetailsView-infogningsgränssnittet till ett NULL databasvärde. Vi kan dock använda händelsen ObjectDataSource Inserting för att mata in olika standardvärden, vilket vi snart kommer att se.

Steg 3: Tillhandahålla ett gränssnitt för att lägga till nya produkter

Dra en DetailsView från verktygslådan till designern ovanför GridView, rensa dess Height egenskaper och Width egenskaper och binda den till ObjectDataSource som redan finns på sidan. Detta lägger till ett BoundField- eller CheckBoxField-fält för var och en av produktens fält. Eftersom vi vill använda den här DetailsView för att lägga till nya produkter måste vi kontrollera alternativet Aktivera infogning från den smarta taggen. Det finns dock inget sådant alternativ eftersom Metoden ObjectDataSource inte mappas Insert() till en metod i ProductsBLL klassen (kom ihåg att vi anger den här mappningen till (Ingen) när du konfigurerar datakällan se bild 3).

Om du vill konfigurera ObjectDataSource väljer du länken Konfigurera datakälla från den smarta taggen och startar guiden. På den första skärmen kan du ändra det underliggande objektet som ObjectDataSource är bundet till. låt det vara inställt på ProductsBLL. Nästa skärm visar mappningarna från ObjectDataSources metoder till det underliggande objektets. Även om vi uttryckligen angav att Insert() metoderna och Delete() inte ska mappas till några metoder, ser du att en mappning finns där om du går till flikarna INSERT och DELETE. Det beror på att ProductsBLL's AddProduct och DeleteProduct metoderna använder DataObjectMethodAttribute attributet för att indikera att de är standardmetoderna för Insert() respektive Delete(). Därför väljer Guiden ObjectDataSource dessa varje gång du kör guiden om det inte finns något annat värde uttryckligen angivet.

Låt metoden Insert() peka på metoden AddProduct, men ställ återigen in listrutan i fliken DELETE till (Ingen).

Ange INSERT-flikens Drop-Down lista till AddProduct-metoden

Bild 14: Ange insert-flikens Drop-Down lista till AddProduct metoden (Klicka om du vill visa en bild i full storlek)

Sätt TA BORT-flikens Drop-Down-lista till (Ingen)

Bild 15: Ange TA BORT-flikens Drop-Down lista till (Ingen) (Klicka om du vill visa en bild i full storlek)

När du har gjort dessa ändringar expanderas ObjectDataSources deklarativa syntax så att den innehåller en InsertParameters samling, enligt nedan:

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

Genom att köra guiden igen har egenskapen OldValuesParameterFormatString lagts tillbaka. Ta en stund att rensa den här egenskapen genom att ange standardvärdet ({0}) eller ta bort den helt från den deklarativa syntaxen.

Med ObjectDataSource som tillhandahåller infogningsfunktioner kommer DetailsViews smarta tagg nu att innehålla kryssrutan Aktivera infogning. gå tillbaka till designern och kontrollera det här alternativet. Parera sedan DetailsView så att den bara har två BoundFields - ProductName och UnitPrice - och CommandField. I det här läget bör DetailsViews deklarativa syntax se ut så här:

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

Bild 16 visar den här sidan när den visas via en webbläsare i det här läget. Som du ser visar DetailsView namnet och priset på den första produkten (Chai). Det vi vill ha är dock ett infogande gränssnitt som ger ett sätt för användaren att snabbt lägga till en ny produkt i databasen.

DetailsView återges för närvarande i Read-Only läge

Bild 16: DetailsView återges för närvarande i Read-Only läge (Klicka om du vill visa en bild i full storlek)

För att visa DetailsView i infogningsläget måste vi ange DefaultMode egenskapen till Inserting. Detta gör att DetailsView visas i infogningsläge när det först besöks och förblir i det läget efter att en ny post har infogats. En sådan DetailsView erbjuder ett snabbt gränssnitt för att lägga till en ny post, vilket visas i bild 17.

DetailsView tillhandahåller ett gränssnitt för att snabbt lägga till en ny produkt

Bild 17: DetailsView tillhandahåller ett gränssnitt för att snabbt lägga till en ny produkt (klicka om du vill visa en bild i full storlek)

När användaren anger ett produktnamn och pris (till exempel "Acme Water" och 1,99, som i bild 17) och klickar på Infoga, utlöses en postback och infogningsarbetsflödet påbörjas, vilket kulminerar i att en ny produktpost läggs till i databasen. DetailsView underhåller sitt infogningsgränssnitt och GridView återställs automatiskt till sin datakälla för att inkludera den nya produkten, som visas i bild 18.

Produkten

Bild 18: Produkten "Acme Water" har lagts till i databasen

Även om GridView i bild 18 inte visar det, tilldelas CategoryID de produktfält som saknas från DetailsView-gränssnittet SupplierID, QuantityPerUnit, NULLoch så vidare databasvärden. Du kan se detta genom att utföra följande steg:

  1. Gå till Server Explorer i Visual Studio
  2. Expandera databasnoden NORTHWND.MDF
  3. Högerklicka på databastabellnoden Products
  4. Välj Visa tabelldata

Då visas alla poster i Products tabellen. Som figur 19 visar har alla kolumner för våra nya produkter, förutom ProductID, ProductName och UnitPrice, NULL värden.

Produktfälten som inte anges i DetailsView tilldelas NULL-värden

Bild 19: Produktfälten som inte anges i DetailsView är tilldelade NULL värden (Klicka om du vill visa en bild i full storlek)

Vi kanske vill ange ett annat standardvärde än NULL för ett eller flera av dessa kolumnvärden, antingen för att NULL det inte är det bästa standardalternativet eller för att själva databaskolumnen inte tillåter NULL s. För att åstadkomma detta kan vi programmatiskt ange värdena för parametrarna i DetailsView-samlingen InputParameters . Den här tilldelningen kan göras antingen i händelsehanteraren för DetailsView-händelsen ItemInserting eller ObjectDataSource-händelsen Inserting . Eftersom vi redan har tittat på att använda för- och efterhändelser på datawebbkontrollnivå, ska vi den här gången utforska att utnyttja ObjectDataSources händelser.

Steg 4: Tilldela värden till parametrarnaCategoryIDochSupplierID

I den här självstudien kan vi tänka oss att när en ny produkt läggs till via det här gränssnittet i vårt program, bör den tilldelas värdena CategoryID och SupplierID till 1. Som tidigare nämnts har ObjectDataSource ett par händelser på för- och efternivå som utlöses under dataändringsprocessen. När dess Insert() metod anropas genererar ObjectDataSource först händelsen Inserting och anropar sedan den metod som metoden Insert() har mappats till och genererar Inserted slutligen händelsen. Händelsehanteraren Inserting ger oss en sista möjlighet att justera indataparametrarna eller avbryta åtgärden direkt.

Anmärkning

I ett verkligt program vill du förmodligen antingen låta användaren ange kategorin och leverantören eller välja det här värdet för dem baserat på vissa kriterier eller affärslogik (i stället för att blint välja ett ID på 1). Oavsett visar exemplet hur du programmatiskt anger värdet för en indataparameter från ObjectDataSources förnivåhändelse.

Ta en stund att skapa en händelsehanterare för ObjectDataSource-händelsen Inserting . Observera att händelsehanterarens andra indataparameter är ett objekt av typen ObjectDataSourceMethodEventArgs, som har en egenskap för åtkomst till parametersamlingen (InputParameters) och en egenskap för att avbryta åtgärden (Cancel).

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

End Sub

I det här läget InputParameters innehåller egenskapen ObjectDataSources samling med de värden som tilldelats InsertParameters från DetailsView. Om du vill ändra värdet för en av dessa parametrar använder du bara: e.InputParameters("paramName") = value. För att ange CategoryID och SupplierID till värden för 1 justerar du Inserting därför händelsehanteraren så att den ser ut så här:

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

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

Den här gången när du lägger till en ny produkt (till exempel Acme Soda) är kolumnerna CategoryID och SupplierID kolumnerna för den nya produkten inställda på 1 (se bild 20).

Nya produkter har nu sina CategoryID- och SupplierID-värden inställda på 1

Bild 20: Nya produkter har nu sina CategoryID och SupplierID värden inställda på 1 (Klicka om du vill visa en bild i full storlek)

Sammanfattning

Under redigerings-, infognings- och borttagningsprocessen fortsätter både datawebbkontrollen och ObjectDataSource genom ett antal händelser på för- och efternivå. I den här självstudien undersökte vi händelserna på förnivå och såg hur du använder dessa för att anpassa indataparametrarna eller avbryta dataändringsåtgärden helt och hållet både från datawebbkontrollen och ObjectDataSources händelser. I nästa självstudie tittar vi på hur du skapar och använder händelsehanterare för händelser på efternivå.

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.

Särskilt tack till

Den här självstudieserien granskades av många användbara granskare. Huvudgranskare för den här handledningen var Jackie Goor och Liz Shulok. Vill du granska mina kommande MSDN-artiklar? Om så är fallet, hör av dig på mitchell@4GuysFromRolla.com.