Dela via


Formatera DataList och Repeater utifrån data (C#)

av Scott Mitchell

Ladda ned PDF

I den här självstudien går vi igenom exempel på hur vi formaterar utseendet på kontrollerna DataList och Repeater, antingen genom att använda formateringsfunktioner i mallar eller genom att hantera DataBound-händelsen.

Inledning

Som vi såg i föregående självstudiekurs erbjuder DataList ett antal stilrelaterade egenskaper som påverkar dess utseende. I synnerhet såg vi hur du tilldelar standard-CSS-klasser till egenskaperna DataList s HeaderStyle, ItemStyle, AlternatingItemStyleoch SelectedItemStyle . Förutom dessa fyra egenskaper innehåller DataList ett antal andra stilrelaterade egenskaper, till exempel Font, ForeColor, BackColoroch BorderWidth, för att nämna några. Repeater-kontrollen innehåller inga formatrelaterade egenskaper. Alla sådana formatinställningar måste göras direkt inom markeringen i Repeater s-mallarna.

Hur data ska formateras beror dock ofta på själva data. När vi till exempel listar produkter kanske vi vill visa produktinformationen i en ljusgrå teckenfärg om den upphör, eller så kanske vi vill markera UnitsInStock värdet om det är noll. Som vi såg i tidigare självstudier erbjuder GridView, DetailsView och FormView två olika sätt att formatera deras utseende baserat på deras data:

  • Händelsen DataBound skapar en händelsehanterare för lämplig DataBound händelse som utlöses efter att data har bundits till varje objekt (för GridView var RowDataBound det händelsen, för DataList och Repeater är ItemDataBound det händelsen). I den händelsehanteraren kan data som nyss har bundits undersökas och beslut om formatering fattas. Vi har granskat den här tekniken i självstudiekursen Anpassad formatering baserad på data .
  • Formateringsfunktioner i mallar när du använder TemplateFields i kontrollerna DetailsView eller GridView, eller en mall i FormView-kontrollen, kan vi lägga till en formateringsfunktion i ASP.NET sidans kod bakom-klass, Business Logic Layer eller något annat klassbibliotek som är tillgängligt från webbprogrammet. Den här formateringsfunktionen kan acceptera ett godtyckligt antal indataparametrar, men måste returnera HTML-koden för att återges i mallen. Formateringsfunktioner undersöktes först i självstudiekursen Använda mallfält i GridView Control .

Båda dessa formateringstekniker är tillgängliga med kontrollerna DataList och Repeater. I den här handledningen kommer vi att gå igenom exempel med både teknikerna för båda kontrollerna.

ItemDataBoundAnvända händelsehanteraren

När data är bundna till en DataList, antingen från en datakällkontroll eller genom att programmatiskt tilldela data till kontrollens DataSource-egenskap och anropa dess DataBind()-metod, utlöses DataList-händelsen DataBinding, datakällan räknas upp, och varje datapost binds till DataList. För varje post i datakällan skapar DataList ett DataListItem objekt som sedan är bundet till den aktuella posten. Under den här processen genererar DataList två händelser:

  • ItemCreated aktiveras efter att DataListItem har skapats
  • ItemDataBound utlöses efter att den aktuella posten har bundits till DataListItem

Följande steg beskriver databindningsprocessen för DataList-kontrollen.

  1. Händelsen DataList s DataBinding utlöses

  2. Data är bundna till DataList

    För varje post i datakällan

    1. Skapa ett DataListItem objekt
    2. ItemCreated Utlös händelsen
    3. Bind ihop posten med DataListItem
    4. ItemDataBound Utlös händelsen
    5. Lägg till DataListItem i Items-samlingen

När data binds till Repeater-kontrollen fortsätter de genom exakt samma stegsekvens. Den enda skillnaden är att istället för DataListItem-instanser som skapas använder Repeater RepeaterItem.

Anmärkning

Den skarpsinniga läsaren kan ha märkt en liten avvikelse mellan sekvensen med steg som inträffar när DataList och Repeater är bundna till data jämfört med när GridView är bundet till data. I slutet av databindningsprocessen genererar DataBound GridView händelsen, men varken DataList- eller Repeater-kontrollen har en sådan händelse. Det beror på att kontrollerna DataList och Repeater skapades i ASP.NET version 1.x innan händelsehanteringsmönstret med föregående och efterföljande nivå hade blivit vanligt.

Precis som med GridView är ett alternativ för formatering baserat på data att skapa en händelsehanterare för ItemDataBound händelsen. Den här händelsehanteraren skulle inspektera de data som just hade bundits till DataListItem eller RepeaterItem och påverka kontrollens formatering efter behov.

För DataList-kontrollen kan formateringsändringar för hela objektet implementeras med hjälp av DataListItem s-stilrelaterade egenskaper, som inkluderar standarden Font, ForeColor, BackColor, CssClassoch så vidare. För att påverka formateringen av vissa webbkontroller i DataList s-mallen måste vi programmatiskt komma åt och ändra formatet för dessa webbkontroller. Vi såg hur man gjorde detta i handledningen Anpassad formatering baserat på data. Precis som Repeater-kontrollen RepeaterItem har klassen inga stilrelaterade egenskaper. Därför måste alla formatrelaterade ändringar som görs i en RepeaterItem i ItemDataBound händelsehanteraren göras genom programmatisk åtkomst till och uppdatering av webbkontroller i mallen.

ItemDataBound Eftersom formateringstekniken för DataList och Repeater är praktiskt taget identiska fokuserar vårt exempel på att använda DataList.

Steg 1: Visa produktinformation i datalistan

Innan vi oroar oss för formateringen ska vi först skapa en sida som använder en DataList för att visa produktinformation. I den föregående självstudien skapade vi en DataList vars ItemTemplate produktnamn, kategori, leverantör, kvantitet per enhet och pris visas. Låt oss upprepa denna funktion i den här handledningen. För att åstadkomma detta kan du antingen återskapa DataList och dess ObjectDataSource från grunden, eller så kan du kopiera över kontrollerna från sidan som skapades i föregående självstudie (Basics.aspx) och klistra in dem på sidan för den här självstudien (Formatting.aspx).

När du har replikerat funktionerna DataList och ObjectDataSource från Basics.aspx till Formatting.aspx, ta en stund för att ändra DataLists egenskap från ID till en mer beskrivande DataList1. Visa sedan DataList i en webbläsare. Som bild 1 visar är den enda formateringsskillnaden mellan varje produkt att bakgrundsfärgen växlar.

Produkterna visas i datalistekontrollen

Bild 1: Produkterna visas i datalistekontrollen (klicka om du vill visa en bild i full storlek)

I den här självstudien ska vi formatera DataList så att alla produkter med ett pris som är mindre än 20,00 USD har både namnet och enhetspriset markerat gult.

Steg 2: Programmatiskt bestämma värdet för data i ItemDataBound-händelsehanteraren

Eftersom endast de produkter med ett pris under $20.00 kommer att ha den anpassade formateringen tillämpad, måste vi kunna fastställa varje produkts pris. När data binds till en DataList räknar DataList upp posterna i datakällan och skapar för varje post en DataListItem instans som binder datakällposten till DataListItem. När den specifika postens data har bundits till det aktuella DataListItem-objektet utlöses DataListens ItemDataBound-händelse. Vi kan skapa en händelsehanterare för den här händelsen för att inspektera datavärdena för den aktuella DataListItem och, baserat på dessa värden, göra nödvändiga formateringsändringar.

Skapa en ItemDataBound händelse för DataList och lägg till följande kod:

protected void ItemDataBoundFormattingExample_ItemDataBound
    (object sender, DataListItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
    {
        // Programmatically reference the ProductsRow instance bound
        // to this DataListItem
        Northwind.ProductsRow product =
            (Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
        // See if the UnitPrice is not NULL and less than $20.00
        if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
        {
            // TODO: Highlight the product's name and price
        }
    }
}

Även om begreppet och semantiken bakom DataLists ItemDataBound händelsehanterare är desamma som de som används av GridViews RowDataBound händelsehanterare i självstudien Anpassad formatering baserad på data , skiljer sig syntaxen något åt. När händelsen ItemDataBound utlöses skickas DataListItem, som just har bundits till data, till den motsvarande händelsehanteraren via e.Item (istället för e.Row, som med GridViews RowDataBound händelsehanterare). DataLists ItemDataBound händelsehanterare utlöses för varje rad som läggs till i DataList, inklusive sidhuvudrader, sidfotsrader och avgränsarrader. Produktinformationen är dock endast bunden till dataraderna. När vi använder ItemDataBound händelsen för att inspektera data som är bundna till DataList måste vi därför först se till att vi arbetar med ett dataobjekt. Detta kan du göra genom att kontrollera DataListItem egenskapen sItemType, som kan ha något av följande åtta värden:

  • AlternatingItem
  • EditItem
  • Footer
  • Header
  • Item
  • Pager
  • SelectedItem
  • Separator

Både Item och AlternatingItem``DataListItem utgör DataLists dataenheter. Förutsatt att vi arbetar med en Item eller AlternatingItem, kommer vi åt den faktiska ProductsRow-instansen som var bunden till den aktuella DataListItem. Egenskapen DataListItem s DataItem innehåller en referens till DataRowView objektet, vars Row egenskap ger en referens till det faktiska ProductsRow objektet.

Därefter kontrollerar vi instansens ProductsRowUnitPrice egenskap. Eftersom fältet Products table s UnitPrice tillåter NULL värden bör vi först kontrollera om den har ett UnitPrice värde med hjälp av NULL metoden innan du försöker komma åt IsUnitPriceNull() egenskapen. Om värdet UnitPrice inte NULLär kontrollerar vi om det är mindre än 20,00 USD. Om den verkligen är under 20,00 USD måste vi tillämpa den anpassade formateringen.

Steg 3: Markera produktens namn och pris

När vi vet att en produkts pris är mindre än $ 20,00, allt som återstår är att markera dess namn och pris. För att åstadkomma detta måste vi först programmatiskt referera till etikettkontrollerna i ItemTemplate som visar produktens namn och pris. Därefter måste de visa en gul bakgrund. Den här formateringsinformationen kan användas genom att direkt ändra egenskaperna Etiketter BackColor (LabelID.BackColor = Color.Yellow), men helst bör alla visningsrelaterade frågor uttryckas via sammanhängande formatmallar. Faktum är att vi redan har en formatmall som ger önskad formatering definierad i Styles.css - AffordablePriceEmphasis, som skapades och diskuterades i självstudien Anpassad formatering baserat på data .

Om du vill använda formateringen anger du bara de två egenskaperna för Etikettwebbkontroller CssClass till AffordablePriceEmphasis, som du ser i följande kod:

// Highlight the product name and unit price Labels
// First, get a reference to the two Label Web controls
Label ProductNameLabel = (Label)e.Item.FindControl("ProductNameLabel");
Label UnitPriceLabel = (Label)e.Item.FindControl("UnitPriceLabel");
// Next, set their CssClass properties
if (ProductNameLabel != null)
    ProductNameLabel.CssClass = "AffordablePriceEmphasis";
if (UnitPriceLabel != null)
    UnitPriceLabel.CssClass = "AffordablePriceEmphasis";

ItemDataBound När händelsehanteraren är klar går du tillbaka till Formatting.aspx sidan i en webbläsare. Som bild 2 visar har dessa produkter med ett pris under $20,00 både sitt namn och pris markerat.

Dessa produkter som är mindre än 20,00 USD är markerade

Bild 2: Dessa produkter som är mindre än 20,00 USD är markerade (klicka om du vill visa en bild i full storlek)

Anmärkning

Eftersom DataList återges som en HTML <table>har dess DataListItem instanser stilrelaterade egenskaper som kan anges för att tillämpa ett visst format på hela objektet. Om vi till exempel vill markera hela objektet gult när priset var mindre än 20,00 USD kunde vi ha ersatt koden som refererade till etiketterna och ställt in deras CssClass egenskaper med följande kodrad: e.Item.CssClass = "AffordablePriceEmphasis" (se bild 3).

De RepeaterItem som utgör Repeater-kontrollen erbjuder dock inte sådana egenskaper på formatnivå. För att tillämpa anpassad formatering på Repeater krävs därför att formategenskaper tillämpas på webbkontrollerna i Repeater-mallarna, precis som vi gjorde i bild 2.

Hela produktartikeln är markerad för produkter under 20,00 USD

Bild 3: Hela produktobjektet är markerat för produkter under 20,00 USD (klicka om du vill visa en bild i full storlek)

Använda formateringsfunktioner från mallen

I handledningen Att använda mallfält i GridView-kontrollen såg vi hur man använder en formateringsfunktion i ett GridView-mallfält för att tillämpa anpassad formatering baserat på data som är bundna till GridView-raderna. En formateringsfunktion är en metod som kan anropas från en mall och returnerar HTML som ska genereras i dess ställe. Formateringsfunktioner kan finnas i ASP.NET sidans kod bakom-klass eller centraliseras till klassfiler i App_Code mappen eller i ett separat klassbiblioteksprojekt. Att flytta formateringsfunktionen från ASP.NET sidans kod bakom-klass är perfekt om du planerar att använda samma formateringsfunktion på flera ASP.NET sidor eller i andra ASP.NET webbprogram.

För att demonstrera formateringsfunktioner ska vi låta produktinformationen innehålla texten [DISCONTINUED] bredvid produktens namn om den upphör. Låt oss också ha priset markerat gult om det är mindre än $ 20,00 (som vi gjorde i ItemDataBound händelsehanterarens exempel); om priset är $ 20.00 eller högre, låt oss inte visa det faktiska priset, utan i stället texten, Vänligen anropa för en pris offert. Bild 4 visar en skärmbild av produktlistan med dessa formateringsregler tillämpade.

Skärmbild som visar produkter som anges i DataList-kontrollen, där priset på produkter som kostar mer än 20,00 USD ersätts med texten

Bild 4: För dyra produkter ersätts priset med texten. Anropa efter en prisoffert (Klicka om du vill visa en bild i full storlek)

Steg 1: Skapa formateringsfunktionerna

I det här exemplet behöver vi två formateringsfunktioner, en som visar produktnamnet tillsammans med texten [DISCONTINUED], om det behövs, och en annan som visar antingen ett markerat pris om det är mindre än 20,00 USD eller texten, Anropa annars för en prisoffert. Låt oss skapa dessa funktioner i kod-bakom-klassen på ASP.NET-sidan och namnge dem DisplayProductNameAndDiscontinuedStatus och DisplayPrice. Båda metoderna måste returnera HTML-koden för att återges som en sträng och båda måste markeras Protected (eller Public) för att kunna anropas från ASP.NET sidans deklarativa syntaxdel. Koden för dessa två metoder följer:

protected string DisplayProductNameAndDiscontinuedStatus
    (string productName, bool discontinued)
{
    // Return just the productName if discontinued is false
    if (!discontinued)
        return productName;
    else
        // otherwise, return the productName appended with the text "[DISCONTINUED]"
        return string.Concat(productName, " [DISCONTINUED]");
}
protected string DisplayPrice(Northwind.ProductsRow product)
{
    // If price is less than $20.00, return the price, highlighted
    if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
        return string.Concat("<span class=\"AffordablePriceEmphasis\">",
                              product.UnitPrice.ToString("C"), "</span>");
    else
        // Otherwise return the text, "Please call for a price quote"
        return "<span>Please call for a price quote</span>";
}

Observera att DisplayProductNameAndDiscontinuedStatus metoden accepterar värdena för datafälten productName och discontinued som skalära värden, medan DisplayPrice metoden accepterar en ProductsRow instans (i stället för ett unitPrice skalärt värde). Endera metoden fungerar. Men om formateringsfunktionen fungerar med skalära värden som kan innehålla databasvärden NULL (till exempel UnitPrice; varken ProductName eller Discontinued tillåtna NULL värden), måste du vara särskilt noga med att hantera dessa skalära indata.

I synnerhet måste indataparametern vara av typen Object eftersom det inkommande värdet kan vara en DBNull instans i stället för den förväntade datatypen. Dessutom måste en kontroll göras för att avgöra om det inkommande värdet är ett databasvärde NULL eller inte. Om vi vill DisplayPrice att metoden ska acceptera priset som ett skalärt värde måste vi alltså använda följande kod:

protected string DisplayPrice(object unitPrice)
{
    // If price is less than $20.00, return the price, highlighted
    if (!Convert.IsDBNull(unitPrice) && ((decimal) unitPrice) < 20)
        return string.Concat("<span class=\"AffordablePriceEmphasis\">",
                              ((decimal) unitPrice).ToString("C"), "</span>");
    else
        // Otherwise return the text, "Please call for a price quote"
        return "<span>Please call for a price quote</span>";
}

Observera att unitPrice-parametern är av typen Object och att den villkorsstyrda satsen har ändrats för att avgöra om unitPrice är DBNull eller inte. Eftersom indataparametern skickas som ett unitPricemåste den dessutom Object omvandlas till ett decimalvärde.

Steg 2: Anropa formateringsfunktionen från DataList s ItemTemplate

När formateringsfunktionerna har lagts till i vår ASP.NET-sidans kod-bakom-klassen är allt som återstår att anropa dessa formateringsfunktioner från DataListens ItemTemplate. Om du vill anropa en formateringsfunktion från en mall placerar du funktionsanropet inom syntaxen för databindning:

<%# MethodName(inputParameter1, inputParameter2, ...) %>

I DataList s ItemTemplateProductNameLabel visar kontrollen Etikettwebb för närvarande produktens namn genom att tilldela dess Text egenskap resultatet av <%# Eval("ProductName") %>. För att se till att namnet visas tillsammans med texten [UTGÅNGEN], uppdaterar du vid behov den deklarativa syntaxen så att egenskapen Text istället får värdet från DisplayProductNameAndDiscontinuedStatus-metoden. När vi gör det måste vi skicka in produktens namn och utgångna värden med hjälp av syntaxen Eval("columnName"). Eval returnerar ett värde av typen Object, men DisplayProductNameAndDiscontinuedStatus metoden förväntar sig indataparametrar av typen String och Booleandärför måste vi omvandla värdena som returneras av Eval metoden till de förväntade indataparametertyperna, så här:

<h4>
    <asp:Label ID="ProductNameLabel" runat="server"
        Text='<%# DisplayProductNameAndDiscontinuedStatus((string) Eval("ProductName"),
              (bool) Eval("Discontinued")) %>'>
    </asp:Label>
</h4>

För att visa priset kan vi helt enkelt ange UnitPriceLabel egenskapen Etikett till Text det värde som returneras av DisplayPrice metoden, precis som vi gjorde för att visa produktens namn och texten [DISCONTINUED]. Men i stället för att skicka in UnitPrice som en skalär indataparameter skickar vi i stället hela ProductsRow instansen:

<asp:Label ID="UnitPriceLabel" runat="server"
    Text='<%# DisplayPrice((Northwind.ProductsRow)
          ((System.Data.DataRowView) Container.DataItem).Row) %>'>
</asp:Label>

När anropen till formateringsfunktionerna är på plats, ta en stund och titta på vår framsteg i en webbläsare. Skärmen bör se ut ungefär som i bild 5, med de produkter som har utgått inkluderande texten [DISCONTINUED] och de produkter som kostar mer än 20,00 $ ha deras pris ersatt med texten Ring för prisförslag.

Skärmbild som visar produkter som anges i DataList-kontrollen, där priset på produkter som kostar mer än 20,00 USD ersätts med texten

Bild 5: För dyra produkter ersätts priset med texten. Anropa efter en prisoffert (Klicka om du vill visa en bild i full storlek)

Sammanfattning

Formatering av innehållet i en DataList- eller Repeater-kontroll baserat på data kan utföras med hjälp av två tekniker. Den första tekniken är att skapa en händelsehanterare för ItemDataBound händelsen, som utlöses när varje post i datakällan är bunden till en ny DataListItem eller RepeaterItem. ItemDataBound I händelsehanteraren kan det aktuella objektets data undersökas och sedan kan formateringen tillämpas på innehållet i mallen eller, för DataListItem s, på hela själva objektet.

Du kan också använda anpassad formatering via formateringsfunktioner. En formateringsfunktion är en metod som kan anropas från mallarna DataList eller Repeater som returnerar HTML-koden som ska genereras i dess ställe. Ofta bestäms HTML-koden som returneras av en formateringsfunktion av de värden som är bundna till det aktuella objektet. Dessa värden kan skickas till formateringsfunktionen, antingen som skalära värden eller genom att skicka in hela objektet som är bundet till objektet (till exempel instansen ProductsRow ).

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 självstudien var Yaakov Ellis, Randy Schmidt och Liz Shulok. Vill du granska mina kommande MSDN-artiklar? Om så är fallet, hör av dig på mitchell@4GuysFromRolla.com.