ASP.NET MVC v praxi od A do Z, 8. díl – Třídy ViewData a ViewModel
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama

ASP.NET MVC v praxi od A do Z, 8. díl – Třídy ViewData a ViewModelASP.NET MVC v praxi od A do Z, 8. díl – Třídy ViewData a ViewModel

 

ASP.NET MVC v praxi od A do Z, 8. díl – Třídy ViewData a ViewModel

Google       Google       4. 9. 2009       12 009×

Dnes to bude pro změnu krátké, probereme dva způsoby, jak předávat data z controlleru příslušným views, a to pomocí tříd ViewData a ViewModel.

Reklama
Reklama

Pomocí těchto tříd můžeme poskytnout bohatší uživatelské rozhraní. Hezké by třeba bylo, kdyby měly stránky pro přidání a upravení večeře místo TextBoxu DropDownList (rozbalovací menu) pro vybrání země. Ale ne že bychom museli do DropDownListu dostupné země natvrdo napsat, musely by se pěkně dynamicky načítat podle toho, pro které státy máme dostupné validace telefonních čísel. Pomocí tříd ViewData a ViewModel nebude těžké toho dosáhnout.

Použití třídy ViewData

Bázová třída Controller, od které je odvozen každý controller, poskytuje vlastnost ViewData, do které můžeme uložit další data, která chceme předat view. Když budeme chtít, aby se seznam zemí zobrazoval jako vysouvací menu, můžeme do ViewData uložit instanci třídy SelectList:

// GET: /Dinners/Edit/2
public ActionResult Edit(int id)
{
    Dinner dinner = dinnerRepository.GetDinner(id);

    ViewData["Countries"] = new SelectList(PhoneValidator.Countries, dinner.Country);

    return View(dinner);
}

Konstruktor SelectListu přijímá v prvním parametru seznam hodnot pro DropDownList a jako druhý parametr přijímá defaultně zvolenou hodnotu. Řádek s TextBoxem pro výběr země v šabloně Edit pak stačí jen přepsat, aby vypadal následovně:

<label for="Country">Země:</label>
<%= Html.DropDownList("Country", ViewData["Countries"] as SelectList) %>             
<%=Html.ValidationMessage("Country", "*") %>

I metoda Html.DropDownList přijímá dva parametry – první určuje název ovládacího prvku a druhý parametr je seznam hodnot. Když teď aplikaci spustíme a zadáme URL „/Dinners/Edit/1“ uvidíme to, co je na obrázku:

Protože země chceme vybírat i v případě chyb na stránce s úpravami, musíme patřičně upravit i POST verzi metody Edit:

// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues)
{
    Dinner dinner = dinnerRepository.GetDinner(id);
    try
    {
        UpdateModel(dinner);
        dinnerRepository.Save();

        return RedirectToAction("Details", new {id = dinner.DinnerID});
    }
    catch
    {
        ModelState.AddRuleViolations(dinner.GetRuleViolations());
        ViewData["Countries"] = new SelectList(PhoneValidator.Countries, dinner.Country);

        return View(dinner);
    }
}

Pokud se vám zdá, že jsem zapomněl na metodu Create, protože při vytváření večeří přece taky chceme vybírat zemi, kde se večeře pořádá, máte pravdu. To totiž uděláme pomocí třídy ViewModel, abychom viděli oba způsoby v akci.

Použití třídy ViewModel

Použití ViewData, které jsme si ukázali v předchozí kapitole, má výhodu v tom, že je poměrně rychlé a jednoduché na implementaci. Někdo ale používá tento způsob nerad, protože při psaní názvu klíče může dojít k překlepu, který ale při kompilaci nijak nezjistíme (teď mluvím o té části ve hranatých závorkách).

Alternativním postupem je použití třídy ViewModel. Funguje to tak, že vytvoříme třídu, která má všechny potřebné vlastnosti, a teprve tu předáme danému view. Ukážeme si kód a vzápětí vysvětlím, jak to funguje (pro následující kód vytvořte třídu DinnerFormViewModel v adresáři Controllers):

using System.Web.Mvc;
using NerdDinner.Models;

namespace NerdDinner.Controllers
{
    public class DinnerFormViewModel
    {
        // vlastnosti
        public Dinner Dinner { get; private set; }
        public SelectList Countries { get; private set; }

        // konstruktor
        public DinnerFormViewModel(Dinner dinner)
        {
            Dinner = dinner;
            Countries = new SelectList(PhoneValidator.Countries, dinner.Country);
        }
    }
}

Takže teď k tomu, jak to vlastně bude fungovat. Normálně předáváme view instanci třídy Dinner. Jak ale vidíte, tak konstruktor třídy DinnerFormViewModel přijímá jako parametr také Dinner objekt a pak ho ukládá do vlastnosti, dá se tedy říct, že tato třída obaluje jak Dinner objekt, tak i SelectList naplněný seznamem dostupných zemí. Pak stačí jen mírně upravit akční metodu:

// GET: /Dinners/Edit/2
public ActionResult Edit(int id)
{
    Dinner dinner = dinnerRepository.GetDinner(id);

    return View(new DinnerFormViewModel(dinner));
}

Ještě musíme provést pár úprav šablony Edit. Nejdříve ji nastavíme tak, aby očekávala DinnerFormViewModel objekt, namísto stávajícího Dinner objektu (podívejte na tag „Page“ v kódu níže). K tomu navíc musíme upravit všechny položky ve formuláři, protože hodnoty jsou od teď dostupné přes Model.Dinner.NazevVlastnosti, nikoliv Model.NazevVlastnosti jako předtím. Kód níže ukazuje všechny změny, včetně upravené definice DropDownListu:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerFormViewModel>" %>

<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Upravit: <%=Html.Encode(Model.Dinner.Title)%>
</asp:Content>

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

    <h2>Upravit večeři</h2>

    <%=Html.ValidationSummary("Opravte prosím všechny chyby a zkuste to znovu.") %>  
    
    <% using (Html.BeginForm()) { %>

        <fieldset>
            <p>
                <label for="Title">Název večeře:</label>
                <%=Html.TextBox("Title", Model.Dinner.Title) %>
                <%=Html.ValidationMessage("Title", "*") %>
            </p>
            <p>
                <label for="EventDate">Datum:</label>
                <%=Html.TextBox("EventDate", String.Format("{0:g}", Model.Dinner.EventDate))%>
                <%=Html.ValidationMessage("EventDate", "*") %>
            </p>
            <p>
                <label for="Description">Popis:</label>
                <%=Html.TextArea("Description", Model.Dinner.Description) %>
                <%=Html.ValidationMessage("Description", "*")%>
            </p>
            <p>
                <label for="Address">Adresa:</label>
                <%=Html.TextBox("Address", Model.Dinner.Address) %>
                <%=Html.ValidationMessage("Address", "*") %>
            </p>
            <p>
                <label for="Country">Země:</label>
                <%= Html.DropDownList("Country", Model.Countries) %>             
                <%=Html.ValidationMessage("Country", "*") %>
            </p>
            <p>
                <label for="ContactPhone">Telefon:</label>
                <%=Html.TextBox("ContactPhone", Model.Dinner.ContactPhone) %>
                <%=Html.ValidationMessage("ContactPhone", "*") %>
            </p>
            <p>
                <label for="Latitude">Zem. šířka:</label>
                <%=Html.TextBox("Latitude", Model.Dinner.Latitude) %>
                <%=Html.ValidationMessage("Latitude", "*") %>
            </p>
            <p>
                <label for="Longitude">Zem. délka:</label>
                <%=Html.TextBox("Longitude", Model.Dinner.Longitude) %>
                <%=Html.ValidationMessage("Longitude", "*") %>
            </p>
            <p>
                <input type="submit" value="Uložit"/>
            </p>
        </fieldset>
        
    <% } %>
    
</asp:Content>

Upravenou POST Edit metodu a Create metody nemá vůbec cenu ukazovat. Jediná změna v nich totiž je přepsané „return“ tak, aby vypadalo takto:

return View(new DinnerFormViewModel(dinner));

Bohužel musíme upravit i Create view, aby vše fungovalo jako doposud – změny uvidíte v následujícím zdrojovém kódu:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerFormViewModel>" %>

<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
     Vytvořit večeři
</asp:Content>

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

    <h2>Vytvořit večeři</h2>

    <%=Html.ValidationSummary("Opravte prosím všechny chyby a zkuste to znovu.") %>
 
    <% using (Html.BeginForm()) {%>
  
        <fieldset>
            <p>
                <label for="Title">Název:</label>
                <%= Html.TextBox("Title", Model.Dinner.Title) %>
                <%= Html.ValidationMessage("Title", "*") %>
            </p>
            <p>
                <label for="EventDate">Datum:</label>
                <%=Html.TextBox("EventDate", Model.Dinner.EventDate) %>
                <%=Html.ValidationMessage("EventDate", "*") %>
            </p>
            <p>
                <label for="Description">Popis:</label>
                <%=Html.TextArea("Description", Model.Dinner.Description) %>
                <%=Html.ValidationMessage("Description", "*") %>
            </p>
            <p>
                <label for="Address">Adresa:</label>
                <%=Html.TextBox("Address", Model.Dinner.Address) %>
                <%=Html.ValidationMessage("Address", "*") %>
            </p>
            <p>
                <label for="Country">Země:</label>
                <%= Html.DropDownList("Country", Model.Countries) %> 
                <%=Html.ValidationMessage("Country", "*") %>
            </p>
            <p>
                <label for="ContactPhone">Telefon:</label>
                <%=Html.TextBox("ContactPhone", Model.Dinner.ContactPhone) %>
                <%=Html.ValidationMessage("ContactPhone", "*") %>
            </p>            
            <p>
                <label for="Latitude">Zem. šířka:</label>
                <%=Html.TextBox("Latitude", Model.Dinner.Latitude) %>
                <%=Html.ValidationMessage("Latitude", "*") %>
            </p>
            <p>
                <label for="Longitude">Zem. délka:</label>
                <%=Html.TextBox("Longitude", Model.Dinner.Longitude) %>
                <%=Html.ValidationMessage("Longitude", "*") %>
            </p>
            <p>
                <input type="submit" value="Uložit"/>
            </p>
        </fieldset>
    <% } 
%>
</asp:Content>

Odměnou za naše snažení nám bude DropDownList i na stránce s vytvářením večeří:

Dnešní kus práce máme za sebou. Všimli jste si ale, jak si jsou view šablony Edit a Create hrozně podobné? Přece by s tím mělo jít něco udělat, a taky že jde. Proto budou naším příštím tématem „partial“ šablony a master pages, které jistě znáte z klasického ASP.NET.

Zdroj: http://nerddinnerbook.s3.amazonaws.com/Part6.htm

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
(fotka) Jakub KottnauerJakub studuje informatiku na FIT ČVUT, jeho oblíbenou platformou je .NET.
Web     Twitter     Facebook     LinkedIn    

Nové články

Obrázek ke článku Hackerský kongres přiveze v září do Prahy špičky světové kryptoanarchie

Hackerský kongres přiveze v září do Prahy špičky světové kryptoanarchie

Hackerský kongres HCPP16 pořádá od 30. září do 2. října nezisková organizace Paralelní Polis již potřetí, a to ve stejnojmenném bitcoinovém prostoru v pražských Holešovicích. Letos přiveze na třídenní konferenci přes 40 většinou zahraničních speakerů – lídrů z oblastí technologií, decentralizované ekonomiky, politických umění a aktivismu. Náměty jejich přednášek budou také hacking, kryptoměny, věda, svoboda nebo kryptoanarchie.

Reklama
Reklama
Obrázek ke článku ICT PRO školení zaměřené nejenom na ICT

ICT PRO školení zaměřené nejenom na ICT

Dovolte, abychom se představili. Jsme zaměstnanci společnosti ICT Pro, profesionálové v oblasti poskytování komplexních ICT služeb. Neboli služeb spojených s informačními a komunikačními technologiemi, které dnes - ve 21. století - tvoří  nedílnou součást běžného provozu všech moderních firem.

loadingtransparent (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })();
Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý