Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här handledningen skapar vi ett mer omfattande redigeringsgränssnitt för DataList, ett gränssnitt som innehåller rullgardinsmenyer och en kryssruta.
Inledning
Markerings- och webbkontrollerna i DataList s EditItemTemplate definierar dess redigerbara gränssnitt. I alla redigerbara DataList-exempel som vi har undersökt hittills har det redigerbara gränssnittet består av TextBox-webbkontroller. I den föregående självstudien förbättrade vi användarupplevelsen vid redigering genom att lägga till valideringskontroller.
EditItemTemplate kan utökas ytterligare för att inkludera andra webbkontroller än textrutan, till exempel Listrutor, Radioknapplistor, Kalendrar och så vidare. Precis som med TextBoxes använder du följande steg när du anpassar redigeringsgränssnittet för att inkludera andra webbkontroller:
- Lägg till webbkontrollen i
EditItemTemplate. - Använd databindningssyntax för att tilldela motsvarande datafältvärde till lämplig egenskap.
-
UpdateCommandI händelsehanteraren får du programmatiskt åtkomst till webbkontrollvärdet och skickar det till lämplig BLL-metod.
I den här handledningen skapar vi ett mer omfattande redigeringsgränssnitt för DataList, ett gränssnitt som innehåller rullgardinsmenyer och en kryssruta. I synnerhet skapar vi en datalista som visar produktinformation och tillåter att produktens namn, leverantör, kategori och utgångna status uppdateras (se bild 1).
Bild 1: Redigeringsgränssnittet innehåller en textruta, två listrutor och en kryssruta (klicka om du vill visa en bild i full storlek)
Steg 1: Visa produktinformation
Innan vi kan skapa ett redigerbart gränssnitt för datalistan måste vi först skapa det läsbara gränssnittet. Börja med att öppna sidan från CustomizedUI.aspx och mappen EditDeleteDataList, och lägg till en DataList på sidan från Designern. Ange dess egenskap ID till Products. Skapa en ny ObjectDataSource från datalistans smarta tagg. Namnge den nya ObjectDataSource ProductsDataSource och konfigurera den så att den ProductsBLL hämtar data från klassens GetProducts -metod. Precis som med tidigare redigerbara DataList-handledningar uppdaterar vi den redigerade produktens information genom att gå direkt till affärslogiklagret. Ange därför listrutorna i flikarna UPDATE, INSERT och DELETE till (Ingen).
Bild 2: Ställ in flikarna UPDATE, INSERT och DELETE under Drop-Down till (Ingen) (Klicka för att visa bilden i full storlek)
När du har konfigurerat ObjectDataSource skapar Visual Studio ett standardvärde ItemTemplate för DataList som visar namnet och värdet för vart och ett av de datafält som returneras.
ItemTemplate Ändra så att mallen visar produktnamnet i ett <h4> element tillsammans med kategorinamnet, leverantörsnamnet, priset och den utgångna statusen. Lägg dessutom till knappen Redigera och se till att dess CommandName egenskap är inställd på Redigera. Den deklarativa markeringen för min ItemTemplate följer:
<ItemTemplate>
<h4>
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Eval("ProductName") %>' />
</h4>
<table border="0">
<tr>
<td class="ProductPropertyLabel">Category:</td>
<td class="ProductPropertyValue">
<asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Eval("CategoryName") %>' />
</td>
<td class="ProductPropertyLabel">Supplier:</td>
<td class="ProductPropertyValue">
<asp:Label ID="SupplierNameLabel" runat="server"
Text='<%# Eval("SupplierName") %>' />
</td>
</tr>
<tr>
<td class="ProductPropertyLabel">Discontinued:</td>
<td class="ProductPropertyValue">
<asp:Label ID="DiscontinuedLabel" runat="server"
Text='<%# Eval("Discontinued") %>' />
</td>
<td class="ProductPropertyLabel">Price:</td>
<td class="ProductPropertyValue">
<asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
</td>
</tr>
<tr>
<td colspan="4">
<asp:Button runat="Server" ID="EditButton"
Text="Edit" CommandName="Edit" />
</td>
</tr>
</table>
<br />
</ItemTemplate>
Ovanstående markering beskriver produktinformationen med hjälp av en <h4-rubrik> för produktens namn och en fyrakolumn <table> för de återstående fälten. CSS-klasserna ProductPropertyLabel och ProductPropertyValue , som definieras i Styles.css, har diskuterats i tidigare självstudier. Bild 3 visar våra framsteg när de ses genom en webbläsare.
Bild 3: Namn, Leverantör, Kategori, Utgången status och Pris för varje produkt visas (Klicka om du vill visa en bild i full storlek)
Steg 2: Lägga till webbkontrollerna i redigeringsgränssnittet
Det första steget i att skapa det anpassade redigeringsgränssnittet för DataList är att lägga till nödvändiga webbkontroller i EditItemTemplate. I synnerhet behöver vi en listruta för kategorin, en annan för leverantören och en kryssruta för utgånget tillstånd. Eftersom produktens pris inte kan redigeras i det här exemplet kan vi fortsätta att visa det med hjälp av en etikettwebbkontroll.
Om du vill anpassa redigeringsgränssnittet klickar du på länken Redigera mallar från den smarta taggen DataList och väljer EditItemTemplate alternativet i listrutan. Lägg till en listruta i EditItemTemplate och ange dess ID till Categories.
Bild 4: Lägg till en listruta för kategorierna (Klicka om du vill visa en bild i full storlek)
Välj sedan alternativet Välj datakälla i listrutans smarta tagg och skapa en ny ObjectDataSource med namnet CategoriesDataSource. Konfigurera den här ObjectDataSource för att använda CategoriesBLL klassens GetCategories() -metod (se bild 5). Därefter uppmanar guiden Konfiguration av datakälla i Listruta dig att välja de datafält som ska användas för varje egenskap hos ListItem s Text och Value. Låt listrutan visa CategoryName datafältet och använda CategoryID som värde, som visas i bild 6.
Bild 5: Skapa en ny ObjectDataSource med namnet CategoriesDataSource (Klicka om du vill visa en bild i full storlek)
Bild 6: Konfigurera listrutans visnings- och värdefält (Klicka om du vill visa en bild i full storlek)
Upprepa den här serien med steg för att skapa en listruta för leverantörerna. Ställ in ID för den här DropDownList till Suppliers och namnge dess ObjectDataSource som SuppliersDataSource.
När du har lagt till de två listrutorna, lägg till en kryssruta för att markera om produkten har utgått och en textruta för produktens namn.
ID Ange s för kryssrutan och textrutan till Discontinued respektive ProductName. Lägg till en RequiredFieldValidator för att säkerställa att användaren tillhandahåller ett värde för produktens namn.
Slutligen lägger du till knapparna Uppdatera och Avbryt. Kom ihåg att för dessa två knappar är det absolut nödvändigt att deras CommandName egenskaper är inställda på Uppdatera respektive Avbryt.
Lägg gärna fram redigeringsgränssnittet hur du vill. Jag har valt att använda samma layout med fyra kolumner <table> från det skrivskyddade gränssnittet, som följande deklarativa syntax och skärmbild illustrerar:
<EditItemTemplate>
<h4>
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Eval("ProductName") %>' />
</h4>
<table border="0">
<tr>
<td class="ProductPropertyLabel">Name:</td>
<td colspan="3" class="ProductPropertyValue">
<asp:TextBox runat="server" ID="ProductName" Width="90%" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="ProductName"
ErrorMessage="You must enter a name for the product."
runat="server">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td class="ProductPropertyLabel">Category:</td>
<td class="ProductPropertyValue">
<asp:DropDownList ID="Categories" runat="server"
DataSourceID="CategoriesDataSource"
DataTextField="CategoryName" DataValueField="CategoryID" />
</td>
<td class="ProductPropertyLabel">Supplier:</td>
<td class="ProductPropertyValue">
<asp:DropDownList ID="Suppliers"
DataSourceID="SuppliersDataSource" DataTextField="CompanyName"
DataValueField="SupplierID" runat="server" />
</td>
</tr>
<tr>
<td class="ProductPropertyLabel">Discontinued:</td>
<td class="ProductPropertyValue">
<asp:CheckBox runat="server" id="Discontinued" />
</td>
<td class="ProductPropertyLabel">Price:</td>
<td class="ProductPropertyValue">
<asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
</td>
</tr>
<tr>
<td colspan="4">
<asp:Button runat="Server" ID="UpdateButton" CommandName="Update"
Text="Update" />
<asp:Button runat="Server" ID="CancelButton" CommandName="Cancel"
Text="Cancel" CausesValidation="False" />
</td>
</tr>
</table>
<br />
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories"
TypeName="CategoriesBLL">
</asp:ObjectDataSource>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetSuppliers"
TypeName="SuppliersBLL">
</asp:ObjectDataSource>
</EditItemTemplate>
Bild 7: Redigeringsgränssnittet har lagts ut som Read-Only-gränssnittet (klicka om du vill visa en bild i full storlek)
Steg 3: Skapa Händelsehanterare för EditCommand och CancelCommand
För närvarande finns det ingen syntax för databindning i EditItemTemplate (förutom för UnitPriceLabel, som kopierades ordagrant från ItemTemplate). Vi lägger till syntaxen för databindning tillfälligt, men först skapar vi händelsehanterarna för DataList och EditCommandCancelCommand händelser. Kom ihåg att ansvaret EditCommand för händelsehanteraren är att återge redigeringsgränssnittet för det DataList-objekt vars redigeringsknapp klickades, medan CancelCommand s-jobbet är att returnera DataList till dess förredigeringstillstånd.
Skapa dessa två händelsehanterare och be dem använda följande kod:
Protected Sub Products_EditCommand(source As Object, e As DataListCommandEventArgs) _
Handles Products.EditCommand
' Set the DataList's EditItemIndex property to the
' index of the DataListItem that was clicked
Products.EditItemIndex = e.Item.ItemIndex
' Rebind the data to the DataList
Products.DataBind()
End Sub
Protected Sub Products_CancelCommand(source As Object, e As DataListCommandEventArgs) _
Handles Products.CancelCommand
' Set the DataList's EditItemIndex property to -1
Products.EditItemIndex = -1
' Rebind the data to the DataList
Products.DataBind()
End Sub
När dessa två händelsehanterare är på plats, visas redigeringsgränssnittet när du klickar på knappen Redigera, och när du klickar på knappen Avbryt, återgår objektet till sitt skrivskyddade läge. Bild 8 visar DataList när knappen Redigera har klickats för Chef Anton s Gumbo Mix. Eftersom vi ännu inte har lagt till någon databindningssyntax i redigeringsgränssnittet är ProductName-textrutan tom, Discontinued-kryssrutan avmarkerad och de första objekten valda från listrutorna Categories och Suppliers.
Bild 8: Om du klickar på knappen Redigera visas redigeringsgränssnittet (klicka om du vill visa en bild i full storlek)
Steg 4: Lägga till databindningssyntaxen i redigeringsgränssnittet
För att redigeringsgränssnittet ska visa aktuella produktvärden måste vi använda databindningssyntax för att tilldela datafältvärdena till lämpliga webbkontrollvärden. Databindningssyntaxen kan tillämpas via designern genom att gå till skärmen Redigera mallar och välja länken Redigera DataBindings från smarttaggar för webbkontroller. Du kan också lägga till databindningssyntaxen direkt i den deklarativa markeringen.
Tilldela ProductName datafältvärdet till ProductName TextBoxens Text egenskap, CategoryID och SupplierID datafältvärdena till Categories och Suppliers DropDownListsens SelectedValue egenskaper, och Discontinued datafältvärdet till Discontinued CheckBoxens Checked egenskap. När du har gjort dessa ändringar, antingen via designern eller direkt via deklarativ markering, går du tillbaka till sidan via en webbläsare och klickar på knappen Redigera för Chef Anton s Gumbo Mix. Som bild 9 visar har syntaxen för databindning lagt till de aktuella värdena i textrutan, listrutorna och kryssrutan.
Bild 9: Om du klickar på knappen Redigera visas redigeringsgränssnittet (klicka om du vill visa en bild i full storlek)
Steg 5: Spara användarens ändringar i UpdateCommand-händelsehanteraren
När användaren redigerar en produkt och klickar på knappen Uppdatera sker ett återanrop och DataLists UpdateCommand event utlöses. Vid händelsehantering måste vi läsa värdena från webbkontrollerna i EditItemTemplate samt samspelet med BLL för att kunna uppdatera produkten i databasen. Som vi har sett i tidigare handledningar är den uppdaterade ProductID-produkten tillgänglig via DataKeys-samlingen. De användarinmatningsfälten används genom att programmatiskt referera till webbkontrollerna med hjälp av FindControl("controlID"), som följande kod visar:
Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
Handles Products.UpdateCommand
If Not Page.IsValid Then
Exit Sub
End If
' Read in the ProductID from the DataKeys collection
Dim productID As Integer = Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
' Read in the product name and price values
Dim productName As TextBox = CType(e.Item.FindControl("ProductName"), TextBox)
Dim categories As DropDownList=CType(e.Item.FindControl("Categories"), DropDownList)
Dim suppliers As DropDownList = CType(e.Item.FindControl("Suppliers"), DropDownList)
Dim discontinued As CheckBox = CType(e.Item.FindControl("Discontinued"), CheckBox)
Dim productNameValue As String = Nothing
If productName.Text.Trim().Length > 0 Then
productNameValue = productName.Text.Trim()
End If
Dim categoryIDValue As Integer = Convert.ToInt32(categories.SelectedValue)
Dim supplierIDValue As Integer = Convert.ToInt32(suppliers.SelectedValue)
Dim discontinuedValue As Boolean = discontinued.Checked
' Call the ProductsBLL's UpdateProduct method...
Dim productsAPI As New ProductsBLL()
productsAPI.UpdateProduct(productNameValue, categoryIDValue, supplierIDValue, _
discontinuedValue, productID)
' Revert the DataList back to its pre-editing state
Products.EditItemIndex = -1
Products.DataBind()
End Sub
Koden börjar med att konsultera Page.IsValid egenskapen för att säkerställa att alla verifieringskontroller på sidan är giltiga. Om Page.IsValid är True, läss värdet för den redigerade produkten ProductID från DataKeys samlingen och webbkontrollerna för datainmatning i EditItemTemplate refereras programmatiskt. Därefter läss värdena från dessa webbkontroller in i variabler som sedan skickas till lämplig UpdateProduct överlagring. När data har uppdaterats återgår DataList till dess förredigeringstillstånd.
Anmärkning
Jag har utelämnat logiken för undantagshantering som lagts till i självstudien Hantera BLL- och DAL-Level-undantag för att hålla koden och det här exemplet fokuserat. Lägg till denna funktionalitet efter att ha avslutat denna självstudie.
Steg 6: Hantera NULL CategoryID- och SupplierID-värden
Northwind-databasen tillåter NULL värden för Products tabeller CategoryID och SupplierID kolumner. Men vårt redigeringsgränssnitt rymmer NULL för närvarande inte värden. Om vi försöker redigera en produkt som har ett NULL värde för antingen dess CategoryID eller SupplierID kolumner får vi ett ArgumentOutOfRangeException felmeddelande som liknar: "Kategorier" har en SelectedValue som är ogiltig eftersom den inte finns i listan med objekt. För närvarande finns det inte heller något sätt att ändra en produkts kategori eller leverantörsvärde från ett icke-värdeNULL till ett NULL värde.
För att stödja NULL värden för kategorin och leverantörslistor måste vi lägga till ListItem ytterligare. Jag har valt att använda (Ingen) som Text värde för detta ListItem, men du kan ändra det till något annat (till exempel en tom sträng) om du vill. Kom slutligen ihåg att ställa in DropDownList AppendDataBoundItems till True; om du glömmer att göra det, kommer kategorierna och leverantörerna som är bundna till Listrutan att skriva över den statiskt tillagda ListItem.
När du har gjort dessa ändringar bör DropDownLists-markupen i DataList EditItemTemplate se ut ungefär så här:
<asp:DropDownList ID="Categories" DataSourceID="CategoriesDataSource"
DataTextField="CategoryName" DataValueField="CategoryID" runat="server"
SelectedValue='<%# Eval("CategoryID") %>' AppendDataBoundItems="True">
<asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>
...
<asp:DropDownList ID="Suppliers" DataSourceID="SuppliersDataSource"
DataTextField="CompanyName" DataValueField="SupplierID" runat="server"
SelectedValue='<%# Eval("SupplierID") %>' AppendDataBoundItems="True">
<asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>
Anmärkning
Statiska ListItem s kan läggas till i en listruta via designern eller direkt via deklarativ syntax. När du lägger till ett DropDownList-objekt för att representera ett databasvärde NULL måste du lägga ListItem till via den deklarativa syntaxen. Om du använder ListItem samlingsredigeraren i designern utelämnar den genererade deklarativa syntaxen inställningen helt och hållet när den Value tilldelas en tom sträng, vilket skapar deklarativ markering som: <asp:ListItem>(None)</asp:ListItem>. Även om detta kan se ofarligt ut gör den saknade Value att DropDownList använder egenskapsvärdet Text i sin ställe. Det innebär att om detta NULLListItem väljs kommer värdet (Ingen) att försöka tilldelas till produktdatafältet (CategoryID eller SupplierID, i den här självstudien), vilket resulterar i ett undantag. Genom att uttryckligen ange Value=""tilldelas ett NULL värde till produktdatafältet när väljs NULLListItem .
Ta en stund att se våra framsteg via en webbläsare. När du redigerar en produkt bör du tänka på att både Categories och Suppliers-listrutorna har alternativet (Ingen) i början av listrutan.
Bild 10: Listrutorna Categories och Suppliers innehåller alternativet (Ingen) (Klicka om du vill visa en bild i full storlek)
För att spara alternativet (Ingen) som ett databasvärde NULL måste vi återgå till UpdateCommand händelsehanteraren. Ändra variablerna categoryIDValue och supplierIDValue till nullbara heltal och tilldela dem ett annat värde än Nothing bara om DropDownListens SelectedValue inte är en tom sträng.
Dim categoryIDValue As Nullable(Of Integer) = Nothing
If Not String.IsNullOrEmpty(categories.SelectedValue) Then
categoryIDValue = Convert.ToInt32(categories.SelectedValue)
End If
Dim supplierIDValue As Nullable(Of Integer) = Nothing
If Not String.IsNullOrEmpty(suppliers.SelectedValue) Then
supplierIDValue = Convert.ToInt32(suppliers.SelectedValue)
End If
Med denna ändring skickas ett värde Nothing till UpdateProduct BLL-metoden om användaren har valt alternativet (Ingen) från någon av rullgardinsmenyerna, vilket motsvarar ett NULL databasvärde.
Sammanfattning
I den här handledningen såg vi hur du skapar ett mer komplext redigeringsgränssnitt för DataList som innehåller tre olika indatawebbkontroller: en textruta, två listrutor och en kryssruta tillsammans med valideringskontroller. När du skapar redigeringsgränssnittet är stegen desamma oavsett vilka webbkontroller som används: börja med att lägga till webbkontrollerna i DataLists, använd databindningssyntax EditItemTemplateför att tilldela motsvarande datafältvärden med lämpliga egenskaper för webbkontroll och, i UpdateCommand händelsehanteraren, programmatiskt komma åt webbkontrollerna och deras lämpliga egenskaper. skickar sina värden till BLL.
När du skapar ett redigeringsgränssnitt, oavsett om det bara består av textrutor eller en samling med olika webbkontroller, bör du hantera databasvärden NULL korrekt. När du redovisar NULL s är det viktigt att du inte bara visar ett befintligt NULL värde i redigeringsgränssnittet korrekt, utan även att du erbjuder ett sätt att markera ett värde som NULL. För DropDownLists i DataLists innebär det vanligtvis att lägga till en statisk ListItem vars Value egenskap uttryckligen är inställd på en tom sträng (Value="") och att lägga till lite kod till UpdateCommand händelsehanteraren för att avgöra om den NULL``ListItem har valts eller inte.
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 Dennis Patterson, David Suru och Randy Schmidt. Vill du granska mina kommande MSDN-artiklar? Om så är fallet, hör av dig på mitchell@4GuysFromRolla.com.