Sdílet prostřednictvím


Opakované použití uživatelského rozhraní pomocí stránek předloh a částečných zobrazení

od Microsoftu

Stáhnout PDF

Toto je krok 7 bezplatného kurzu aplikace NerdDinner , který vás provede sestavením malé, ale kompletní webové aplikace pomocí ASP.NET MVC 1.

V kroku 7 se podíváme na způsoby, jak můžeme pomocí částečných šablon zobrazení a stránek předlohy použít "PRINCIP SUCHA" k odstranění duplicit kódu.

Pokud používáte ASP.NET MVC 3, doporučujeme postupovat podle kurzů Začínáme S MVC 3 nebo MVC Music Store.

NerdDinner Krok 7: Částečné části a stránky předlohy

Jednou z koncepcí návrhu, ASP.NET MVC využívá, je princip "Neopakovat se" (běžně označovaný jako "SUCHO"). Suchý návrh pomáhá eliminovat duplicity kódu a logiky, což v konečném důsledku urychluje sestavování aplikací a usnadňuje jejich údržbu.

Princip DRY jsme už viděli v několika našich scénářích NerdDinner. Několik příkladů: naše logika ověřování je implementována v rámci naší vrstvy modelu, což umožňuje, aby se vynucovala ve scénářích úprav i vytváření v našem kontroleru. Znovu používáme šablonu zobrazení Nenalezeno v rámci metod akcí Edit, Details a Delete; Používáme konvenční vzor pojmenování s našimi šablonami zobrazení, což eliminuje potřebu explicitně zadat název při volání metody pomocné rutiny View(). a znovu používáme třídu DinnerFormViewModel pro scénáře akcí Edit a Create.

Pojďme se teď podívat na způsoby, jak v našich šablonách zobrazení použít "suchý princip" k odstranění duplicit kódu i tam.

Znovu navštivte naše šablony pro úpravy a vytváření zobrazení.

V současné době používáme dvě různé šablony zobrazení – Edit.aspx a Create.aspx – k zobrazení uživatelského rozhraní formuláře Večeře. Jejich rychlé vizuální porovnání zvýrazní, jak jsou podobné. Formulář pro vytvoření vypadá takto:

Snímek obrazovky se stránkou Moje aplikace M V C Zobrazí se formulář Hostovat večeři.

A náš formulář pro úpravy vypadá takto:

Snímek obrazovky s paagem aplikace My M V C Zobrazí se formulář pro úpravy.

Není v tom moc rozdílu? Kromě textu nadpisu a záhlaví jsou rozložení formuláře a vstupní ovládací prvky identické.

Pokud otevřeme šablony zobrazení Edit.aspx a Create.aspx, zjistíme, že obsahují stejné rozložení formuláře a vstupní řídicí kód. Tato duplikace znamená, že nakonec musíme udělat změny dvakrát, kdykoli zavedeme nebo změníme novou večeři - což není dobré.

Použití částečných šablon zobrazení

ASP.NET MVC podporuje možnost definovat šablony "částečného zobrazení", které se dají použít k zapouzdření logiky vykreslování zobrazení pro dílčí část stránky. "Částečné části" poskytují užitečný způsob, jak jednou definovat logiku vykreslování zobrazení a pak ji znovu použít na více místech v aplikaci.

Abychom pomohli "Vysunout" duplikaci šablony zobrazení Edit.aspx a Create.aspx, můžeme vytvořit částečnou šablonu zobrazení s názvem "DinnerForm.ascx", která zapouzdřuje rozložení formuláře a vstupní prvky společné pro oba. Provedeme to tak, že klikneme pravým tlačítkem na adresář /Views/Dinners a zvolíme příkaz nabídky Přidat zobrazení>:

Snímek obrazovky s navigačním stromem Průzkumník řešení Večeře je zvýrazněná. Jsou vybrané možnosti Přidat a Zobrazit. Zobrazení je zvýrazněné.

Zobrazí se dialogové okno Přidat zobrazení. Nové zobrazení, které chceme vytvořit, pojmenujeme "DinnerForm", v dialogovém okně zaškrtneme políčko Vytvořit částečné zobrazení a označíme, že mu předáme třídu DinnerFormViewModel:

Snímek obrazovky s dialogovým oknem Přidat zobrazení Možnost Vytvořit částečné zobrazení je vybraná a zvýrazněná.

Když klikneme na tlačítko Přidat, Visual Studio pro nás vytvoří novou šablonu zobrazení DinnerForm.ascx v adresáři \Views\Dinners.

Potom můžeme zkopírovat nebo vložit duplicitní rozložení formuláře / vstupní řídicí kód ze šablon zobrazení Edit.aspx/ Create.aspx do naší nové částečné šablony zobrazení "DinnerForm.ascx":

<%= Html.ValidationSummary("Please correct the errors and try again.") %>

<% using (Html.BeginForm()) { %>

    <fieldset>
        <p>
            <label for="Title">Dinner Title:</label>
            <%= Html.TextBox("Title", Model.Dinner.Title) %>
            <%=Html.ValidationMessage("Title", "*") %>
        </p>
        <p>
            <label for="EventDate">Event Date:</label>
            <%= Html.TextBox("EventDate", Model.Dinner.EventDate) %>
            <%= Html.ValidationMessage("EventDate", "*") %>
        </p>
        <p>
            <label for="Description">Description:</label>
            <%= Html.TextArea("Description", Model.Dinner.Description) %>
            <%= Html.ValidationMessage("Description", "*") %>
        </p>
        <p>
            <label for="Address">Address:</label>
            <%= Html.TextBox("Address", Model.Dinner.Address) %>
            <%= Html.ValidationMessage("Address", "*") %>
        </p>
        <p>
            <label for="Country">Country:</label>
            <%= Html.DropDownList("Country", Model.Countries) %>                
            <%= Html.ValidationMessage("Country", "*") %>
        </p>
        <p>
            <label for="ContactPhone">Contact Phone #:</label>
            <%= Html.TextBox("ContactPhone", Model.Dinner.ContactPhone) %>
            <%= Html.ValidationMessage("ContactPhone", "*") %>
        </p>
            
        <p>
            <input type="submit" value="Save"/>
        </p>
    </fieldset>
    
<% } %>

Potom můžeme aktualizovat naše šablony zobrazení Upravit a Vytvořit tak, aby se částečná šablona DinnerForm nazvala částečná a odstranila duplikaci formuláře. Můžeme to udělat voláním Html.RenderPartial("DinnerForm") v našich šablonách zobrazení:

Create.aspx
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Host a Dinner
</asp:Content>

<asp:Content ID="Create" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Host a Dinner</h2>

    <% Html.RenderPartial("DinnerForm"); %>
    
</asp:Content>
Edit.aspx
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Edit: <%=Html.Encode(Model.Dinner.Title) %>
</asp:Content>

<asp:Content ID="Edit" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Edit Dinner</h2>

    <% Html.RenderPartial("DinnerForm"); %>

</asp:Content>

Cestu k požadované částečné šabloně můžete explicitně kvalifikovat při volání Html.RenderPartial (například: ~Views/Dinners/DinnerForm.ascx). V našem výše uvedeném kódu ale využíváme vzor názvů založený na konvencích v rámci ASP.NET MVC a jako název části, která se má vykreslit, zadáváme "DinnerForm". Když to uděláme, ASP.NET MVC bude vypadat jako první v adresáři zobrazení založených na konvencích (pro DinnersController to bude /Views/Dinners). Pokud tam nenajde částečnou šablonu, bude ji hledat v adresáři /Views/Shared.

Při volání Html.RenderPartial() pouze s názvem částečného zobrazení předá ASP.NET MVC částečnému zobrazení stejné objekty slovníku Model a ViewData, které používá šablona volajícího zobrazení. Alternativně existují přetížené verze Html.RenderPartial(), které umožňují předat alternativní model objektu nebo ViewData slovník pro částečné zobrazení použít. To je užitečné ve scénářích, kdy chcete předat pouze podmnožinu úplného modelu Model/ViewModel.

Vedlejší téma: Proč <% %> místo <%= %>?
Jedna z drobných věcí, které jste si u výše uvedeného kódu všimli, je, že při volání bloku Html.RenderPartial() používáme <blok v % %> místo <%= %.> <%= %> bloků v ASP.NET značí, že vývojář chce vykreslit zadanou hodnotu (například% <= "Hello" %> by vykreslilo "Hello"). <>% bloků místo toho značí, že vývojář chce spustit kód a že všechny výstupy vykreslené v nich musí být provedeny explicitně (například<: % Response.Write("Hello") %>. Důvod, proč používáme <% %> bloku s kódem Html.RenderPartial výše, je ten, že Html.RenderPartial() metoda nevrací řetězec a místo toho vypíše obsah přímo do výstupního streamu šablony volajícího zobrazení. Dělá to z důvodů efektivity výkonu a tím se vyhne nutnosti vytvářet (potenciálně velmi velký) dočasný objekt řetězce. To snižuje využití paměti a zlepšuje celkovou propustnost aplikace. Jednou z běžných chyb při použití html.RenderPartial() je, že zapomenete přidat středník na konec volání, když je <v %> bloku. Například tento kód způsobí chybu kompilátoru: <% Html.RenderPartial("DinnerForm") %> Místo toho je potřeba napsat: <% Html.RenderPartial("DinnerForm"); %> To je proto, že <% %> bloků jsou samostatné příkazy kódu a při použití jazyka C# musí být příkazy kódu ukončeny středníkem.

Použití šablon částečného zobrazení k objasnění kódu

Vytvořili jsme šablonu částečného zobrazení "DinnerForm", abychom zabránili duplikování logiky vykreslování zobrazení na více místech. To je nejčastější důvod pro vytváření částečných šablon zobrazení.

Někdy má stále smysl vytvářet částečná zobrazení, i když se volají jenom na jednom místě. Velmi složité šablony zobrazení mohou být často mnohem snadněji čitelné, když se logika vykreslování jejich zobrazení extrahuje a rozdělí do jedné nebo více dobře pojmenovaných částečných šablon.

Podívejte se například na níže uvedený fragment kódu ze souboru Site.master v našem projektu (který si za chvíli prohlédneme). Kód je poměrně přímočarý na čtení – částečně proto, že logika zobrazení odkazu pro přihlášení/odhlášení v pravém horním rohu obrazovky je zapouzdřená v části LogOnUserControl:

<div id="header">
    <div id="title">
        <h1>My MVC Application</h1>
    </div>
      
    <div id="logindisplay">
        <% Html.RenderPartial("LogOnUserControl"); %>
    </div> 
    
    <div id="menucontainer">
    
        <ul id="menu">              
            <li><%=Html.ActionLink("Home", "Index", "Home")%></li>
            <li><%=Html.ActionLink("About", "About", "Home")%></li>
        </ul>
    </div>
</div>

Kdykoli zjistíte, že jste zmateni při pokusu o pochopení kódu HTML/kódu v rámci šablony zobrazení, zvažte, zda by nebylo jasnější, kdyby některé z nich byly extrahovány a refaktorovány do dobře pojmenovaných částečných zobrazení.

Stránky předlohy

Kromě podpory částečných zobrazení ASP.NET MVC podporuje také možnost vytvářet šablony stránky předlohy, které lze použít k definování společného rozložení a html nejvyšší úrovně webu. Ovládací prvky zástupného symbolu obsahu lze pak přidat na stránku předlohy, aby bylo možné identifikovat nahraditelné oblasti, které lze přepsat nebo "vyplnit" zobrazeními. To poskytuje velmi efektivní (a suchý) způsob, jak použít společné rozložení v aplikaci.

Ve výchozím nastavení mají nové projekty ASP.NET MVC automaticky přidanou šablonu stránky předlohy. Tato stránka předlohy má název Site.master a nachází se ve složce \Views\Shared\:

Snímek obrazovky s navigačním stromem Nerd Dinner Předloha webu je zvýrazněná a vybraná.

Výchozí soubor Site.master vypadá takto. Definuje vnější html webu spolu s nabídkou pro navigaci v horní části. Obsahuje dva nahraditelné ovládací prvky zástupného symbolu obsahu – jeden pro nadpis a druhý pro místo, kde by se měl nahradit primární obsah stránky:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">
    <title>
       <asp:ContentPlaceHolder ID="TitleContent" runat="server" />
    </title>
   <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

<body>
    <div class="page">

        <div id="header">
            <div id="title">
                <h1>My MVC Application</h1>
            </div>
              
            <div id="logindisplay">
                <% Html.RenderPartial("LogOnUserControl"); %>
            </div> 
            
            <div id="menucontainer">

                <ul id="menu">              
                    <li><%=Html.ActionLink("Home", "Index", "Home")%></li>
                    <li><%=Html.ActionLink("About", "About", "Home")%></li>
                </ul>
            
            </div>
        </div>

        <div id="main">
            <asp:ContentPlaceHolder ID="MainContent" runat="server" />
        </div>
    </div>
</body>
</html>

Všechny šablony zobrazení, které jsme vytvořili pro naši aplikaci NerdDinner (Seznam, Podrobnosti, Úpravy, Vytvoření, Nenalezeno atd.), jsou založené na této šabloně Site.master. To je indikováno prostřednictvím atributu MasterPageFile, který byl ve výchozím nastavení přidán do horní <direktivy % @ Page %> při vytváření zobrazení pomocí dialogového okna Přidat zobrazení:

<%@ Page Inherits="System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerViewModel>" MasterPageFile="~/Views/Shared/Site.Master" %>

To znamená, že můžeme změnit obsah Site.master a tyto změny se automaticky použijí a použijí při vykreslení kterékoli z našich šablon zobrazení.

Pojďme aktualizovat oddíl hlavičky webu Site.master tak, aby hlavička naší aplikace byla NerdDinner, a ne My MVC Application. Pojďme také aktualizovat navigační nabídku tak, aby první karta byla "Najít večeři" (zpracovává se metodou akce Index() aplikace HomeController) a pojďme přidat novou kartu s názvem "Hostovat večeři" (kterou zpracovává metoda akce Create() třídy DinnersController):

<div id="header">

    <div id="title">
        <h1>NerdDinner</h1>
    </div>

    <div id="logindisplay">
        <% Html.RenderPartial("LoginStatus"); %>
    </div> 
    
    <div id="menucontainer">
        <ul id="menu">      
           <li><%=Html.ActionLink("Find Dinner", "Index", "Home")%></li>
           <li><%=Html.ActionLink("Host Dinner", "Create", "Dinners")%></li>
           <li><%=Html.ActionLink("About", "About", "Home")%></li>   
        </ul>
    </div>
</div>

Když soubor Site.master uložíme a aktualizujeme prohlížeč, uvidíme, že se změny hlaviček projeví ve všech zobrazeních v rámci naší aplikace. Příklad:

Snímek obrazovky se stránkou seznamu Nerd Dinner Upcoming Dinners (Nerd Dinner Upcoming Dinners)

A s adresou URL /Dinners/Edit/[id] :

Snímek obrazovky se stránkou formuláře Nerd Dinner Edit

Další krok

Částečné části a stránky předlohy poskytují velmi flexibilní možnosti, které umožňují přehledně uspořádat zobrazení. Zjistíte, že vám pomůžou vyhnout se duplikování obsahu nebo kódu zobrazení a usnadnit čtení a údržbu šablon zobrazení.

Pojďme se teď znovu vrátit ke scénáři výpisu, který jsme vytvořili dříve, a povolit podporu škálovatelného stránkování.