Sdílet prostřednictvím


Filtrování předlohy a podrobností na dvou stránkách pomocí ovládacího prvku Repeater a DataList (C#)

Scott Mitchell

Stáhnout PDF

V tomto kurzu se podíváme na to, jak rozdělit hlavní a podrobnou sestavu na dvě stránky. Na stránce předlohy použijeme ovládací prvek Repeater k vykreslení seznamu kategorií, které po kliknutí uživatele převedou na stránku "podrobností", kde seznam DataList se dvěma sloupci zobrazuje produkty patřící do vybrané kategorie.

Úvod

V předchozím kurzu jsme viděli, jak zobrazit hlavní a podrobné sestavy na jedné webové stránce pomocí DropDownLists k zobrazení "hlavních" záznamů a DataList pro zobrazení "podrobností". Dalším běžným vzorem, který se používá pro hlavní nebo podrobné sestavy, je mít hlavní záznamy na jedné webové stránce a podrobnosti na druhé. V předchozím kurzu Filtrování předlohy a podrobností na dvou stránkách jsme tento vzor prozkoumali pomocí zobrazení GridView k zobrazení všech dodavatelů v systému. Toto zobrazení GridView obsahovalo pole HyperLinkField, které se vykreslilo jako odkaz na druhou stránku a předávalo ho SupplierID v řetězci dotazu. Druhá stránka použila GridView k výpisu produktů poskytovaných vybraným dodavatelem.

Tyto dvoustránkové sestavy předlohy a podrobností lze také provádět pomocí ovládacích prvků DataList a Repeater. Jediným rozdílem je, že dataList ani repeater poskytují podporu pro ovládací prvek HyperLinkField. Místo toho musíme přidat webový ovládací prvek HyperLink nebo element HTML ukotvení (<a>) v rámci ovládacího prvku ItemTemplate. Vlastnost HyperLink NavigateUrl nebo atribut ukotvení href je pak možné přizpůsobit pomocí deklarativních nebo programových přístupů.

V tomto kurzu prozkoumáme příklad, který uvádí kategorie v seznamu s odrážkami na jedné stránce pomocí ovládacího prvku Repeater. Každá položka seznamu bude obsahovat název a popis kategorie, přičemž název kategorie se zobrazí jako odkaz na druhou stránku. Kliknutím na tento odkaz přejdete uživatele na druhou stránku, kde se v seznamu DataList zobrazí produkty, které patří do vybrané kategorie.

Krok 1: Zobrazení kategorií v seznamu s odrážkami

Prvním krokem při vytváření jakékoli hlavní/podrobné sestavy je začít zobrazením "hlavních" záznamů. Proto je naším prvním úkolem zobrazit kategorie na stránce předlohy. CategoryListMaster.aspx Otevřete stránku ve DataListRepeaterFiltering složce, přidejte ovládací prvek Repeater a z inteligentní značky zvolte přidání nového ObjectDataSource. Nakonfigurujte nový ObjectDataSource tak, aby přistupoval k datům z CategoriesBLL metody třídy GetCategories (viz Obrázek 1).

Nakonfigurujte ObjectDataSource tak, aby používal metodu GetCategories třídy CategoriesBLL.

Obrázek 1: Konfigurace objektu ObjectDataSource pro použití CategoriesBLL metody třídy GetCategories (kliknutím zobrazíte obrázek v plné velikosti)

Dále definujte šablony repeateru tak, aby zobrazovaly název a popis každé kategorie jako položku v seznamu s odrážkami. Zatím si nedělejme starosti s odkazem na každou kategorii na stránku podrobností. Následující příklad ukazuje deklarativní značky pro Repeater a ObjectDataSource:

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"
    EnableViewState="False">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
 
    <ItemTemplate>
        <li><%# Eval("CategoryName") %> - <%# Eval("Description") %></li>
    </ItemTemplate>
 
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
 
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

Po dokončení této značky si chvíli prohlédněte průběh v prohlížeči. Jak ukazuje obrázek 2, Opakovač se vykresluje jako seznam s odrážkami, který zobrazuje název a popis jednotlivých kategorií.

Každá kategorie se zobrazí jako položka seznamu s odrážkami.

Obrázek 2: Každá kategorie se zobrazí jako položka seznamu s odrážkami (kliknutím zobrazíte obrázek v plné velikosti)

Pokud chcete uživateli povolit zobrazení "podrobností" pro danou kategorii, musíme přidat odkaz na každou položku seznamu s odrážkami, který po kliknutí uživatele přemístit na druhou stránku (ProductsForCategoryDetails.aspx). Na této druhé stránce se pak zobrazí produkty pro vybranou kategorii pomocí seznamu DataList. Abychom mohli určit kategorii, na jejíž odkaz se kliknulo, musíme pomocí nějakého mechanismu předat klikané kategorie CategoryID na druhou stránku. Nejjednodušším a nejjednodušším způsobem přenosu skalárních dat z jedné stránky na jinou je použití řetězce dotazů, což je možnost, kterou použijeme v tomto kurzu. Stránka bude zejména očekávat předání ProductsForCategoryDetails.aspx vybrané categoryID hodnoty přes pole řetězce dotazu s názvem CategoryID. Pokud například chcete zobrazit produkty pro kategorii Nápoje, která má CategoryID 1, uživatel navštíví ProductsForCategoryDetails.aspx?CategoryID=1.

Pokud chcete vytvořit hypertextový odkaz pro každou položku seznamu s odrážkami v repeateru, musíme buď přidat ovládací prvek HyperLink Web, nebo element ukotvení HTML (<a>) do ItemTemplate. Ve scénářích, kdy se hypertextový odkaz zobrazuje stejně pro každý řádek, bude stačit každý přístup. U repeaterů dávám přednost použití elementu ukotvení. Pokud chcete použít element anchor, aktualizujte ItemTemplate repeateru na:

<li>
    <a href='ProductsForCategoryDetails.aspx?CategoryID=<%# Eval("CategoryID") %>'>
        <%# Eval("CategoryName") %>
    </a> - <%# Eval("Description") %>
</li>

Všimněte si, že CategoryID objekt může být vložen přímo do atributu elementu href ukotvení, ale abyste to udělali, nezapomeňte oddělovat href hodnotu atributu apostrofy (a všimněte si uvozovek), protože Eval metoda v atributu href odděluje řetězec ("CategoryID") uvozovkami. Případně můžete místo toho použít webový ovládací prvek HyperLink:

<li>
    <asp:HyperLink runat="server" Text='<%# Eval("CategoryName") %>'
        NavigateUrl='<%# "ProductsForCategoryDetails.aspx?CategoryID=" &
            Eval("CategoryID") %>'>
    </asp:HyperLink>
    - <%# Eval("Description") %>
</li>

Všimněte si, že statická část adresy URL je ProductsForCategoryDetails.aspx?CategoryID připojena k výsledku Eval("CategoryID") přímo v rámci syntaxe vazby dat pomocí zřetězení řetězců.

Jednou z výhod použití ovládacího prvku HyperLink je, že k němu lze v případě potřeby přistupovat programově z obslužné rutiny události Repeateru ItemDataBound . Můžete například chtít zobrazit název kategorie jako text, nikoli jako odkaz na kategorie bez přidružených produktů. Takovou kontrolu lze provést programově v ItemDataBound obslužné rutině události. U kategorií bez přidružených produktů může být vlastnost HyperLink NavigateUrl nastavena na prázdný řetězec, což vede k tomu, že se název konkrétní kategorie vykresluje jako prostý text (nikoli jako odkaz). Další informace o formátování obsahu datalistu a opakovače založeného na datech najdete v kurzu Formátování seznamu dat a opakovače na základě programové logiky prostřednictvím ItemDataBound obslužné rutiny události.

Pokud postupujete podle pokynů, můžete na stránce použít buď element ukotvení, nebo přístup k ovládacímu prvku HyperLink. Bez ohledu na přístup by se při prohlížení stránky v prohlížeči měl každý název kategorie vykreslit jako odkaz na ProductsForCategoryDetails.aspxa předat příslušnou CategoryID hodnotu (viz obrázek 3).

Názvy kategorií teď odkazují na ProductsForCategoryDetails.aspx

Obrázek 3: Odkaz na názvy ProductsForCategoryDetails.aspx kategorií (kliknutím zobrazíte obrázek v plné velikosti)

Krok 3: Výpis produktů, které patří do vybrané kategorie

CategoryListMaster.aspx Po dokončení stránky jsme připraveni obrátit pozornost na implementaci stránky ProductsForCategoryDetails.aspx"podrobnosti" . Otevřete tuto stránku, přetáhněte DataList ze sady nástrojů do Designer a nastavte jeho ID vlastnost na ProductsInCategory. Dále z inteligentní značky DataList zvolte přidat na stránku nový ObjectDataSource a pojmovte ji ProductsInCategoryDataSource. Nakonfigurujte ji tak, aby volal metodu ProductsBLL třídy GetProductsByCategoryID(categoryID) ; nastavte rozevírací seznamy na kartách INSERT, UPDATE a DELETE na (None).

Nakonfigurujte ObjectDataSource tak, aby používal metodu GetProductsByCategoryID(categoryID) třídy ProductsBLL.

Obrázek 4: Konfigurace objektu ObjectDataSource pro použití ProductsBLL metody třídy GetProductsByCategoryID(categoryID) (kliknutím zobrazíte obrázek v plné velikosti)

Vzhledem k tomu, že GetProductsByCategoryID(categoryID) metoda přijímá vstupní parametr (categoryID), nabízí průvodce Zvolit zdroj dat možnost určit zdroj parametru. Nastavte zdroj parametru na QueryString pomocí QueryStringField CategoryID.

Jako zdroj parametru použijte ID kategorie pole řetězce dotazu.

Obrázek 5: Použití pole CategoryID řetězce dotazu jako zdroje parametru (kliknutím zobrazíte obrázek v plné velikosti)

Jak jsme viděli v předchozích kurzech, visual Studio po dokončení průvodce Zvolit zdroj dat automaticky vytvoří pro Seznam dat seznam ItemTemplate , který obsahuje seznam názvů a hodnot jednotlivých datových polí. Tuto šablonu nahraďte šablonou, která obsahuje pouze název, dodavatele a cenu produktu. Nastavte také vlastnost DataList RepeatColumns na hodnotu 2. Po těchto změnách by deklarativní značky DataList a ObjectDataSource měly vypadat podobně jako následující:

<asp:DataList ID="ProductsInCategory" runat="server" DataKeyField="ProductID"
    RepeatColumns="2" DataSourceID="ProductsInCategoryDataSource"
    EnableViewState="False">
    <ItemTemplate>
        <h5><%# Eval("ProductName") %></h5>
        <p>
            Supplied by <%# Eval("SupplierName") %><br />
            <%# Eval("UnitPrice", "{0:C}") %>
        </p>
    </ItemTemplate>
</asp:DataList>
 
<asp:ObjectDataSource ID="ProductsInCategoryDataSource"
    OldValuesParameterFormatString="original_{0}" runat="server"
    SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" QueryStringField="CategoryID"
            Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

Pokud chcete zobrazit tuto stránku v akci, začněte od CategoryListMaster.aspx stránky. Potom klikněte na odkaz v seznamu kategorií s odrážkami. Tímto způsobem přejdete na ProductsForCategoryDetails.aspxadresu a projdete CategoryID řetězcem dotazu. ObjectDataSource ProductsInCategoryDataSource v ProductsForCategoryDetails.aspx pak získá pouze tyto produkty pro zadanou kategorii a zobrazí je v seznamu DataList, který vykreslí dva produkty na řádek. Obrázek 6 ukazuje snímek obrazovky ProductsForCategoryDetails.aspx při prohlížení nápojů.

Nápoje jsou zobrazeny, dva na řádek

Obrázek 6: Zobrazí se nápoje, dva na řádek (kliknutím zobrazíte obrázek v plné velikosti)

Krok 4: Zobrazení informací o kategoriích na ProductsForCategoryDetails.aspx

Když uživatel klikne na kategorii v CategoryListMaster.aspxnástroji , přejde na ProductsForCategoryDetails.aspx a zobrazí produkty, které patří do vybrané kategorie. Neexistují však žádné vizuální upozornění na to, ProductsForCategoryDetails.aspx jaká kategorie byla vybrána. Uživatel, který chtěl kliknout na Nápoje, ale omylem kliknul na Koření, nemá způsob, jak si uvědomit svou chybu, jakmile dosáhne ProductsForCategoryDetails.aspx. Abychom tento potenciální problém zmírnili, můžeme v horní části ProductsForCategoryDetails.aspx stránky zobrazit informace o vybrané kategorii – její název a popis.

Chcete-li toho dosáhnout, přidejte FormView nad ovládací prvek Repeater v ProductsForCategoryDetails.aspx. Dále přidejte na stránku nový ObjectDataSource z inteligentní značky FormView s názvem CategoryDataSource a nakonfigurujte ji tak, aby používal metodu CategoriesBLL třídy GetCategoryByCategoryID(categoryID) .

Přístup k informacím o kategorii prostřednictvím metody GetCategoryByCategoryID(categoryID) třídy CategoriesBLL

Obrázek 7: Přístup k informacím o kategorii prostřednictvím CategoriesBLL metody třídy GetCategoryByCategoryID(categoryID) (kliknutím zobrazíte obrázek v plné velikosti)

Stejně jako u objektu ProductsInCategoryDataSource ObjectDataSource přidaného v kroku 3 CategoryDataSourcenás průvodce konfigurací zdroje dat vyzve k zadání zdroje pro GetCategoryByCategoryID(categoryID) vstupní parametr metody. Použijte úplně stejné nastavení jako předtím a nastavte zdroj parametru na QueryString a hodnotu QueryStringField na CategoryID (podívejte se zpět na Obrázek 5).

Po dokončení průvodce visual Studio automaticky vytvoří ItemTemplate, EditItemTemplatea InsertItemTemplate pro FormView. Vzhledem k tomu, že poskytujeme rozhraní jen pro čtení, můžete odebrat EditItemTemplate a InsertItemTemplate. Nebojte se také přizpůsobit FormView .ItemTemplate Po odebrání nadbytečných šablon a přizpůsobení itemTemplate by deklarativní značky FormView a ObjectDataSource měly vypadat nějak takto:

<asp:FormView ID="FormView1" runat="server" DataKeyNames="CategoryID"
    DataSourceID="CategoryDataSource" EnableViewState="False" Width="100%">
    <ItemTemplate>
        <h3>
            <asp:Label ID="CategoryNameLabel" runat="server"
                Text='<%# Bind("CategoryName") %>' />
        </h3>
        <p>
            <asp:Label ID="DescriptionLabel" runat="server"
                Text='<%# Bind("Description") %>' />
        </p>
    </ItemTemplate>
</asp:FormView>
 
<asp:ObjectDataSource ID="CategoryDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategoryByCategoryID" TypeName="CategoriesBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" Type="Int32"
            QueryStringField="CategoryID" />
    </SelectParameters>
</asp:ObjectDataSource>

Obrázek 8 ukazuje snímek obrazovky při prohlížení této stránky v prohlížeči.

Poznámka

Kromě FormView jsem také přidal ovládací prvek HyperLink nad FormView, který uživatele vrátí do seznamu kategorií (CategoryListMaster.aspx). Nebojte se umístit tento odkaz jinam nebo ho úplně vynechat.

Informace o kategoriích se teď zobrazují v horní části stránky.

Obrázek 8: Informace o kategoriích se teď zobrazují v horní části stránky (kliknutím zobrazíte obrázek v plné velikosti)

Krok 5: Zobrazení zprávy, pokud do vybrané kategorie nepatří žádné produkty

Stránka CategoryListMaster.aspx obsahuje seznam všech kategorií v systému bez ohledu na to, jestli jsou k dispozici nějaké přidružené produkty. Pokud uživatel klikne na kategorii bez přidružených produktů, dataList v ProductsForCategoryDetails.aspx souboru se nevykreslí, protože její zdroj dat nebude obsahovat žádné položky. Jak jsme viděli v minulých kurzech, GridView poskytuje EmptyDataText vlastnost, která se dá použít k určení textové zprávy, která se má zobrazit, pokud v jeho zdroji dat nejsou žádné záznamy. DataList ani Repeater bohužel takovou vlastnost nemá.

Aby bylo možné zobrazit zprávu informující uživatele, že pro vybranou kategorii neexistují žádné odpovídající produkty, musíme na stránku přidat ovládací prvek Popisek, jehož Text vlastnost je přiřazena k zobrazení zprávy v případě, že neexistují žádné odpovídající produkty. Pak musíme programově nastavit jeho Visible vlastnost na základě toho, jestli DataList obsahuje nějaké položky.

Pokud to chcete udělat, začněte přidáním popisku pod DataList. Nastavte jeho ID vlastnost na NoProductsMessage a vlastnost Text na "Pro vybranou kategorii neexistují žádné produkty..." Dále musíme programově nastavit vlastnost tohoto objektu Visible Label na základě toho, jestli byla nějaká data svázaná s objektem ProductsInCategory DataList nebo ne. Toto přiřazení musí být provedeno po svázaní dat se seznamem DataList. Pro Objekty GridView, DetailsView a FormView můžeme vytvořit obslužnou rutinu události pro událost ovládacího prvku DataBound , která se aktivuje po dokončení datové vazby. DataList ani Repeater však nemá DataBound událost k dispozici.

V tomto konkrétním příkladu můžeme přiřadit vlastnost Label Visible v obslužné Page_Load rutině události, protože data budou přiřazena k objektu DataList před událostí stránky Load . Tento přístup by však v obecném případě nefungoval, protože data z ObjectDataSource mohou být vázána na DataList později v životním cyklu stránky. Pokud jsou například zobrazená data založena na hodnotě v jiném ovládacím prvku, například při zobrazení hlavní/podrobné sestavy pomocí DropDownList k uložení "hlavních" záznamů, data se nemusí vynořit do ovládacího prvku data web až do PreRender fáze životního cyklu stránky.

Jedním z řešení, které bude fungovat pro všechny případy, je přiřadit Visible vlastnost False v obslužné rutině události DataList ItemDataBound (nebo ItemCreated) při vazbě položky typu Item nebo AlternatingItem. V takovém případě víme, že zdroj dat obsahuje alespoň jednu položku dat, a proto můžeme popisek skrýt NoProductsMessage . Kromě této obslužné rutiny události potřebujeme také obslužnou rutinu události pro událost DataList DataBinding , kde inicializujeme vlastnost Label Visible do True. Vzhledem k tomu, že událost DataBinding se aktivuje před ItemDataBound událostmi, vlastnost Label Visible bude zpočátku nastavena na Truehodnotu ; Pokud však existují nějaké datové položky, bude nastavena na Falsehodnotu . Následující kód implementuje tuto logiku:

protected void ProductsInCategory_DataBinding(object sender, EventArgs e)
{
    // Show the Label
    NoProductsMessage.Visible = true;
}
 
protected void ProductsInCategory_ItemDataBound(object sender, DataListItemEventArgs e)
{
    // If we have a data item, hide the Label
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
        NoProductsMessage.Visible = false;
}

Všechny kategorie v databázi Northwind jsou přidružené k jednomu nebo více produktům. Pro otestování této funkce jsem ručně upravil databázi Northwind pro tento kurz a znovu přiřadil všechny produkty spojené s kategorií Plodiny (CategoryID = 7) do kategorie Mořské plody (CategoryID = 8). To můžete provést v Průzkumníku serveru tak, že zvolíte Nový dotaz a použijete následující UPDATE příkaz:

UPDATE Products SET
    CategoryID = 8
WHERE CategoryID = 7

Po odpovídající aktualizaci databáze se vraťte na CategoryListMaster.aspx stránku a klikněte na odkaz Vytvořit. Vzhledem k tomu, že již neexistují žádné produkty, které patří do kategorie Plodiny, měla by se zobrazit zpráva Pro vybranou kategorii neexistují žádné produkty... zpráva, jak je znázorněno na obrázku 9.

Pokud do vybrané kategorie nepatří žádné produkty, zobrazí se zpráva.

Obrázek 9: Zpráva se zobrazí, pokud do vybrané kategorie nepatří žádné produkty (kliknutím zobrazíte obrázek v plné velikosti).

Souhrn

I když sestavy hlavní a podrobné sestavy můžou zobrazit hlavní i podrobné záznamy na jedné stránce, na mnoha webech jsou rozdělené na dvě webové stránky. V tomto kurzu jsme se podívali na to, jak implementovat takovou hlavní/podrobnou sestavu tím, že kategorie jsou uvedené v seznamu s odrážkami pomocí repeateru na "hlavní" webové stránce a přidružené produkty uvedené na stránce podrobností. Každá položka seznamu na webové stránce předlohy obsahovala odkaz na stránku podrobností, která byla předána podél hodnoty řádku CategoryID .

Na stránce podrobností bylo načtení těchto produktů pro zadaného dodavatele provedeno metodou ProductsBLL třídy GetProductsByCategoryID(categoryID) . Hodnota parametru categoryID byla zadána deklarativně pomocí CategoryID hodnoty řetězce dotazu jako zdroje parametru. Podívali jsme se také na to, jak zobrazit podrobnosti o kategorii na stránce podrobností pomocí objektu FormView a jak zobrazit zprávu, pokud do vybrané kategorie nepatří žádné produkty.

Všechno nejlepší na programování!

O autorovi

Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.

Zvláštní poděkování...

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty pro tento kurz byli Zack Jones a Liz Shulok. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.