Dela via


Använda TemplateFields i DetailsView Control (VB)

av Scott Mitchell

Ladda ned PDF

Samma TemplateFields-funktioner som är tillgängliga med GridView är också tillgängliga med DetailsView-kontrollen. I den här självstudien visar vi en produkt i taget med hjälp av en DetailsView som innehåller TemplateFields.

Inledning

TemplateField ger en högre grad av flexibilitet när det gäller att återge data än kontrollerna BoundField, CheckBoxField, HyperLinkField och andra datafält. I den föregående självstudien tittade vi på hur du använder TemplateField i ett GridView för att:

  • Visa flera datafältvärden i en kolumn. Mer specifikt kombinerades både fälten FirstName och LastName till en GridView-kolumn.
  • Använd en alternativ webbkontroll för att uttrycka ett datafältvärde. Vi såg hur du visar HiredDate värdet med hjälp av en kalenderkontroll.
  • Visa statusinformation baserat på underliggande data. Employees Även om tabellen inte innehåller en kolumn som returnerar antalet dagar som en anställd har varit på jobbet, kunde vi visa sådan information i GridView-exemplet i föregående självstudiekurs med hjälp av en TemplateField- och formateringsmetod.

Samma TemplateFields-funktioner som är tillgängliga med GridView är också tillgängliga med DetailsView-kontrollen. I den här självstudien visar vi en produkt i taget med hjälp av en DetailsView som innehåller två TemplateFields. Det första TemplateField kombinerar datafälten UnitPrice, UnitsInStockoch UnitsOnOrder till en DetailsView-rad. Det andra TemplateField visar värdet för Discontinued fältet, men använder en formateringsmetod för att visa "JA" om Discontinued är True, och "NEJ" annars.

Två TemplateFields används för att anpassa visningen

Bild 1: Två TemplateFields används för att anpassa visningen (klicka om du vill visa en bild i full storlek)

Nu ska vi komma igång!

Steg 1: Binda data till DetailsView

Som beskrivs i föregående självstudie, när du arbetar med TemplateFields är det ofta enklast att börja med att skapa DetailsView-kontrollen som bara innehåller BoundFields och sedan lägga till nya TemplateFields eller konvertera befintliga BoundFields till TemplateFields efter behov. Starta därför den här självstudien genom att lägga till en DetailsView på sidan via designern och binda den till en ObjectDataSource som returnerar listan över produkter. De här stegen skapar en DetailsView med BoundFields för var och en av produktens icke-booleska värdefält och ett CheckBoxField för det enda booleska värdefältet (Upphört).

Öppna sidan DetailsViewTemplateField.aspx och dra en "DetailsView" från verktygslådan till designern. Från DetailsViews smarta tagg väljer du att lägga till en ny ObjectDataSource-kontroll som anropar ProductsBLL klassens GetProducts() -metod.

Lägg till en ny ObjectDataSource-kontroll som anropar metoden GetProducts()

Bild 2: Lägg till en ny ObjectDataSource-kontroll som anropar GetProducts() metoden (Klicka om du vill visa en bild i full storlek)

För den här rapporten tar du bort ProductID, SupplierID, CategoryIDoch ReorderLevel BoundFields. Ändra sedan ordning på BoundFields så att CategoryName BoundFields och SupplierName BoundFields visas omedelbart efter ProductName BoundField. Du kan gärna justera egenskaperna och formateringsegenskaperna för BoundFields som du tycker är lämpligt. Precis som med GridView kan dessa BoundField-nivåredigeringar utföras via dialogrutan Fält (nås genom att klicka på länken Redigera fält i DetailsViews smarta tagg) eller via deklarativ syntax. Slutligen rensar du DetailsView- och Height-egenskapsvärdena Width för att tillåta att kontrollen DetailsView expanderar baserat på de data som visas och markerar kryssrutan Aktivera sidindelning i den smarta taggen.

När du har gjort dessa ändringar bör detailsView-kontrollens deklarativa markering se ut ungefär så här:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
    EnableViewState="False">
    <Fields>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
          SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category"
          ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier"
          ReadOnly="True" SortExpression="SupplierName" />
        <asp:BoundField DataField="QuantityPerUnit"
          HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
          SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock"
          HeaderText="Units In Stock" SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder"
          HeaderText="Units On Order" SortExpression="UnitsOnOrder" />
        <asp:CheckBoxField DataField="Discontinued"
          HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

Ta en stund att visa sidan via en webbläsare. Nu bör du se en enskild produkt listad (Chai) med rader som visar produktens namn, kategori, leverantör, pris, enheter i lager, enheter på beställning och dess utgångna status.

Produktens information visas med hjälp av en serie BoundFields

Bild 3: Produktens information visas med hjälp av en serie BoundFields (Klicka om du vill visa en bild i full storlek)

Steg 2: Kombinera pris, enheter i lager och enheter på beställning till en rad

DetailsView har en rad för fälten UnitPrice, UnitsInStockoch UnitsOnOrder . Vi kan kombinera dessa datafält till en enda rad med ett TemplateField antingen genom att lägga till ett nytt TemplateField eller genom att konvertera ett av de befintliga UnitPrice, UnitsInStockoch UnitsOnOrder BoundFields till ett TemplateField. Även om jag personligen föredrar att konvertera befintliga BoundFields, låt oss öva genom att lägga till en ny TemplateField.

Börja med att klicka på länken Redigera fält i DetailsViews smarta tagg för att öppna dialogrutan Fält. Lägg sedan till ett nytt TemplateField och ange dess HeaderText egenskap till "Pris och inventering" och flytta det nya TemplateField så att det placeras ovanför UnitPrice BoundField.

Lägg till ett nytt mallfält i DetailsView-kontrollen

Bild 4: Lägg till ett nytt mallfält i DetailsView-kontrollen (klicka om du vill visa en bild i full storlek)

Eftersom det nya TemplateField kommer att innehålla de värden som för närvarande visas i UnitPrice, UnitsInStockoch UnitsOnOrder BoundFields, tar vi bort dem.

Den sista uppgiften för det här steget är att definiera pålägget ItemTemplate för Price and Inventory TemplateField, som kan utföras antingen via DetailsViews mallredigeringsgränssnitt i designern eller för hand via kontrollens deklarativa syntax. Precis som med GridView kan du komma åt DetailsViews mallredigeringsgränssnitt genom att klicka på länken Redigera mallar i den smarta taggen. Härifrån kan du välja mallen som ska redigeras från listrutan och sedan lägga till webbkontroller från verktygslådan.

I den här instruktionen börjar du med att lägga till etikettkontrollen i Price and Inventory TemplateField:s ItemTemplate. Klicka sedan på länken Redigera DataBindings från etikett-webbkontrollens smarta tagg och koppla Text-egenskapen till fältet UnitPrice.

Binda etikettens textegenskap till datafältet UnitPrice

Bild 5: Binda etikettens Text egenskap till UnitPrice datafältet (klicka om du vill visa en bild i full storlek)

Formatera priset som en valuta

Med det här tillägget visar etikettwebbkontrollen Pris- och inventeringsmallFält nu bara priset för den valda produkten. Bild 6 visar en skärmdump av våra framsteg hittills när vi ses via en webbläsare.

Mallfältet Pris och inventering visar priset

Bild 6: Mallfältet Pris och lager visar priset (klicka om du vill visa en bild i full storlek)

Observera att produktens pris inte är formaterat som en valuta. Med boundfield är formatering möjlig genom att ange HtmlEncode egenskapen till False och egenskapen DataFormatString till {0:formatSpecifier}. För ett TemplateField måste dock alla formateringsinstruktioner anges i syntaxen för databindning eller med hjälp av en formateringsmetod som definierats någonstans i programmets kod (till exempel i ASP.NET-sidans kod bakom-klass).

Om du vill ange formatering för databindningssyntaxen som används i kontrollen Etikettwebb går du tillbaka till dialogrutan DataBindings genom att klicka på länken Redigera databindningar från etikettens smarta tagg. Du kan skriva formateringsinstruktionerna direkt i listrutan Format eller välja en av de definierade formatsträngarna. Precis som med egenskapen BoundField DataFormatString anges formateringen med hjälp av {0:formatSpecifier}.

För fältet UnitPrice använder du den valutaformatering som anges antingen genom att välja lämpligt listrutevärde eller genom att skriva in {0:C} för hand.

Formatera priset som en valuta

Bild 7: Formatera priset som en valuta (Klicka om du vill visa en bild i full storlek)

Deklarativt anges formateringsspecifikationen som en andra parameter i Bind metoderna eller Eval . Inställningarna som just har gjorts via designern resulterar i följande databindningsuttryck i den deklarativa markering:

<asp:Label ID="Label1" runat="server" Text='<%# Eval("UnitPrice", "{0:C}") %>'/>

Lägga till återstående datafält i TemplateField

Nu har vi visat och formaterat UnitPrice datafältet i mallfältet Pris och inventering, men måste fortfarande visa fälten UnitsInStock och UnitsOnOrder . Nu ska vi visa dessa på en rad under priset och inom parenteser. Från mallredigeringsgränssnittet i designern kan du lägga till en sådan markering genom att placera markören i mallen och helt enkelt skriva in texten som ska visas. Du kan också ange denna markering direkt i den deklarativa syntaksen.

Lägg till den statiska markeringen, etikettwebbkontrollerna och databindningssyntaxen så att pris- och lagermallfältet visar pris- och inventeringsinformationen så här:

Enhetspris
(I lager/på beställning:UnitsInStock / UnitsOnOrder)

När du har utfört den här uppgiften bör DetailsViews deklarativa markering se ut ungefär så här:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
    EnableViewState="False">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="Product" SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category"
          ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName"
          HeaderText="Supplier" ReadOnly="True"
          SortExpression="SupplierName" />
        <asp:BoundField DataField="QuantityPerUnit"
          HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:TemplateField HeaderText="Price and Inventory">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server"
                  Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:Label>
                <br />
                <strong>
                (In Stock / On Order: </strong>
                <asp:Label ID="Label2" runat="server"
                  Text='<%# Eval("UnitsInStock") %>'></asp:Label>
                <strong>/</strong>
                <asp:Label ID="Label3" runat="server"
                  Text='<%# Eval("UnitsOnOrder") %>'>
                </asp:Label><strong>)</strong>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:CheckBoxField DataField="Discontinued"
           HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

Med dessa ändringar har vi konsoliderat pris- och inventeringsinformationen till en enda DetailsView-rad.

Pris- och inventeringsinformationen visas på en enskild rad

Bild 8: Pris- och inventeringsinformationen visas på en enskild rad (klicka om du vill visa en bild i full storlek)

Steg 3: Anpassa fältinformationen som upphört

Tabellens ProductsDiscontinued kolumn är ett bitvärde som anger om produkten har upphört. När du binder en DetailsView (eller GridView) till en datakällkontroll implementeras de booleska värdefälten, till exempel Discontinued, som CheckBoxFields, medan icke-booleska värdefält, som ProductID, ProductNameoch så vidare, implementeras som BoundFields. Kryssrutan CheckBoxField visas som en inaktiverad kryssruta som blir markerad om datafältets värde är Sant och avmarkerad annars.

I stället för att visa CheckBoxField kanske vi i stället vill visa text som anger om produkten har upphört eller inte. För att åstadkomma detta kan vi ta bort CheckBoxField från DetailsView och sedan lägga till en BoundField vars egenskap har angetts DataField till Discontinued. Ta en stund att göra det här. Efter den här ändringen visar DetailsView texten "True" för utgångna produkter och "False" för produkter som fortfarande är aktiva.

Strängarna True och False används för att visa det utgångna tillståndet

Bild 9: Strängarna True och False används för att visa tillståndet Avbrutet (klicka om du vill visa en bild i full storlek)

Anta att vi inte ville att strängarna "True" eller "False" skulle användas, utan "YES" och "NO" i stället. En sådan anpassning kan utföras med hjälp av en TemplateField och en formateringsmetod. En formateringsmetod kan ta in valfritt antal indataparametrar, men måste returnera HTML (som en sträng) för att mata in i mallen.

Lägg till en formateringsmetod i DetailsViewTemplateField.aspx sidans kod bakom-klass med namnet DisplayDiscontinuedAsYESorNO som accepterar ett Northwind.ProductsRow objekt som en indataparameter och returnerar en sträng. Enligt beskrivningen i föregående självstudie måste den här metoden markeras som Protected eller Public för att kunna nås från mallen.

Protected Function DisplayDiscontinuedAsYESorNO(discontinued As Boolean) As String
    If discontinued Then
        Return "YES"
    Else
        Return "NO"
    End If
End Function

Den här metoden kontrollerar indataparametern (discontinued) och returnerar "YES" om det är True, "NEJ" annars.

Anmärkning

I formateringsmetoden som undersöktes i föregående handledning påmindes vi om att vi skickade in ett datafält som kunde innehålla NULL och därför behövde vi kontrollera om medarbetarens HiredDate egenskaps värde hade ett databasvärde NULL innan vi fick åtkomst till EmployeesRows HiredDate egenskap. En sådan kontroll behövs inte här eftersom Discontinued kolumnen aldrig kan tilldelas databasvärden NULL . Dessutom kan metoden acceptera en boolesk indataparameter i stället för att behöva acceptera en ProductsRow instans eller en parameter av typen Object.

När formateringsmetoden är klar är allt som återstår att anropa den från TemplateFields ItemTemplate. Om du vill skapa TemplateField tar du antingen bort Discontinued BoundField och lägger till ett nytt TemplateField eller konverterar Discontinued BoundField till ett TemplateField. Från vyn deklarativ markering redigerar du sedan TemplateField så att den bara innehåller ett ItemTemplate som anropar DisplayDiscontinuedAsYESorNO metoden och skickar in värdet för den aktuella ProductRow instansens Discontinued egenskap. Detta kan nås via Eval -metoden. Mer specifikt bör TemplateFields markering se ut så här:

<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
    <ItemTemplate>
        <%#DisplayDiscontinuedAsYESorNO(Convert.ToBoolean(Eval("Discontinued")))%> 
    </ItemTemplate>
</asp:TemplateField>

Detta kommer att orsaka att DisplayDiscontinuedAsYESorNO-metoden anropas när DetailsView återges, och den ProductRow instansens Discontinued värde överförs. Eval Eftersom metoden returnerar ett värde av typen Object, men DisplayDiscontinuedAsYESorNO metoden förväntar sig en indataparameter av typen Boolean, omvandlar Eval vi metodernas returvärde till Boolean. Metoden DisplayDiscontinuedAsYESorNO returnerar sedan "YES" eller "NO" beroende på vilket värde den tar emot. Det returnerade värdet är det som visas på den här DetailsView-raden (se bild 10).

JA- eller NEJ-värden visas nu på raden Avslutad

Bild 10: JA- eller NEJ-värden visas nu på raden Avbruten (Klicka för att visa en bild i full storlek)

Sammanfattning

TemplateField i DetailsView-kontrollen ger en högre grad av flexibilitet när det gäller att visa data än vad som är tillgängligt med de andra fältkontrollerna och är idealiska för situationer där:

  • Flera datafält måste visas i en GridView-kolumn
  • Data uttrycks bäst med hjälp av en webbkontroll i stället för oformaterad text
  • Utdata beror på underliggande data, till exempel att visa metadata eller formatera om data

Även om TemplateFields ger större flexibilitet vid återgivningen av DetailsViews underliggande data, känns DetailsView-utdata fortfarande lite boxiga eftersom varje fält återges som en rad i en HTML.<table>

FormView-kontrollen ger en större flexibilitet när det gäller att konfigurera de renderade utdata. FormView innehåller inte fält utan bara en serie mallar (ItemTemplate, EditItemTemplate, HeaderTemplateoch så vidare). Vi får se hur du använder FormView för att få ännu mer kontroll över den renderade layouten i nästa självstudie.

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. Ansvarig granskare för handledningen var Dan Jagers. Vill du granska mina kommande MSDN-artiklar? Om så är fallet, hör av dig på mitchell@4GuysFromRolla.com.