wtorek, 17 sierpnia 2010

ASP.NET MVC 2 cz. 6 Widoki

Widok służy jedynie prezentacji danych użytkownikowi. Nie zawiera w sobie jakiejkolwiek logiki biznesowej czy też połączenia z bazą danych.

ASP.NET MVC korzysta z dynamicznego tworzenia zawartości. Co to znaczy? Otóż tworzenie statycznych stron HTML już straciło na świetności lata temu. Teraz dane muszą być podmieniane i aktualizowane w realnym czasie użytkowania. W MVC mamy możliwość dodawania kodu inline poprzez specjalne znaczniki:
<%: %> - dla .NET 4.0
<%= %> - dla .NET 3.5
Znaczniki te generują kod HTML. Dla znaczników które mają wykonywać kod HTML w obu wersjach frameworka korzystamy z znaczników:
<% %>

Czym różni się składnia dla .NET 4.0? Główną zmianą jest to, że nie musimy używać metody Html.Encode. Framework jest na tyle inteligentny, że zrobi to za nas.
Oprócz tego mamy do dyspozycji HTML helpers - metody które pozwalają w prosty sposób tworzyć różne elementy formularzy HTML.


Przekazywanie danych do widoku
Dane do widoku przekazujemy za pomocą właściwości ViewData. Właściwość ta jest typu ViewDataDictionary. Korzystać z tego słownika możemy na dwa sposoby:
1. Normalnie za pomocą klucza i wartości (wartość jest w tym wypadku typu object)
2. Za pomocą pola Model: ViewData.Model albo po prostu Model. Zwracając w View(obiekt) tak na prawdę niejawnie przypisujemy temu polu jakiś obiekt. Korzystając z modelu tworzymy tak na prawdę silnie typowane Widoki. Ułatwia to dostęp do poszczególnych pól obiektu. Należy pamiętać, że jeżeli chcemy przekazać listę obiektów, wtedy nasz silnie typowany obiekt tworzymy na podstawie IEnumerable



Metody pomocnicze - HTML Helpers
Metody te pozwalają w prosty sposób na rendering większości HTMLowskich kontrolek. Kontrolki możemy te podzielić na dwie grupy.
- zwykłe
- z silną typizacją
Kontrolki z silną typizacją umożliwiają korzystanie z danych przenoszonych przez Model dzięki czemu można korzystać z wyrażeń lambda. Zwykłe nie mają takiej możliwości i niestety należy wiedzieć jak nazywają się pola przenoszonej klasy.
Do tworzonych kontrolek możemy przypisać dowolne atrybuty HTML:

<%: Html.TextBoxFor(x => x.FirstName, new { someAttribut =  "wartosc" }) %>

Oczywiście problem pojawia się w przypadku słów kluczowych. W takim przypadku (mp. nadawanie stylu css) stawiamy przed słowem kluczowym @:

<%: Html.TextBoxFor(x => x.FirstName, new { @class =  "podkreslony" }) %>

lub korzystamy z jawnego słownika:

<%: Html.TextBoxFor(x => x.FirstName, new Dictionary<string, object> { {"class", "podswietlony" }}) %>

Helpery zawierają także łatwe tworzenie linków nawigacyjnych:
Url.Content("link w obrębie aplikacji")
Html.ActionLink("Tekst wyświetlany", "Akcja", "Kontroler") - link do nazwanej akcji/kontrolera
Url.Action("Akcja", "Kontroler") - odnośnik do danego kontrolera i akcji
Url.RouteUrl(new { controller = "c", action = "a" }) - dla danych z routingu


Możemy także skorzystać z listy Drop-Down oraz Multiselect list:

            var people = new List<Person>
            {
                new Person { Id = 1, FirstName = "Jacek"},
                new Person { Id = 2, FirstName = "Marek"},
                new Person { Id = 3, FirstName = "Sebastian"},
                new Person { Id = 4, FirstName = "Szymek"},
            };

            ViewData["people"] = new SelectList(people, "Id", "FirstName");


<%: Html.DropDownList("Name", (SelectList)ViewData["people"]) %>

Formę możemy stworzyć w następujący sposób:

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

    <% } %>

Przyda się nam to w przypadku gdy chcemy przechwycić formę w metodzie POST i wykonać jakieś operacje lub coś zwrócić a na formularzu będą błędy. Wówczas dzięki mechanizmowi bindowania można zachować już wypełnione pola i tylko poprawić źle wprowadzone wartości.



Tworzenie własnych Html helpers
Tworzyć dodatkowe helpery możemy w bardzo łatwy sposób. Jak można zauważyć wszystkie metody pomocnicze to metody rozszerzające. Dodamy więc naszą:

    public static class MyExtension
    {
        public static MvcHtmlString Video(this HtmlHelper html, string src)
        {
            string url = UrlHelper.GenerateContentUrl(src, html.ViewContext.HttpContext);
            TagBuilder tag = new TagBuilder("video");
            tag.InnerHtml = "Sorry, your borwser doesn't support HTML 5 video code";
            tag.MergeAttribute("src", "url");
            tag.MergeAttribute("controls", "controls");
            return MvcHtmlString.Create(tag.ToString());
        }
    }

Teraz rejestrujemy nowy namespace w webconfigu lub importujemy nasz helper do konkretnego widoku:

        <add namespace="MvcApplication5" />


Użycie:

<%: Html.Video("~/Content/plik.avi") %>



Używanie PartialViews

Umożliwiają nam wyodrębnienie często używanych części widoku. Zapisujemy je najczęściej do folderu Views/Shared (dla łatwości używania). Wstawianie następuję za pomocą instrukcji:

 <%: Html.Partial("nazwa_partialu") %>

Możemy też użyć wersji, która wpisuje dane bezpośrednio w strumień:

<% Html.RenderPartial("nazwa partialu"); %>

Przydaje się to w przypadkach kiedy generowanego kodu będzie bardzo dużo (dla małej ilości nie ma to praktycznego uzasadnienia).

Zobaczmy na praktyczny przykład zastosowania:

    public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
    }

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var people = new List<Person>
            {
                new Person { Id = 1, FirstName = "Jacek"},
                new Person { Id = 2, FirstName = "Marek"},
                new Person { Id = 3, FirstName = "Sebastian"},
                new Person { Id = 4, FirstName = "Szymek"},
            };

            return View(people);
        }

    }


<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication5.Controllers.Person>>" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
</head>
<body>
    <% foreach (var item in Model)
       { %>
        <%: Html.Partial("PersonDetail", item) %> 
      <% } %>
</body>
</html>


<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApplication5.Controllers.Person>" %>

<%: Model.Id %>   <%: Model.FirstName %>
<br />

Oczywiście przykład pokazany powyżej ma tylko przekazać idę samego stosowania partial views. W żadnym przypadku nie powinno się mieszać klas modelu biznesowego z kontrolerem jak jest to tutaj pokazane! (jak podkreślam to tylko przykład użycia partial views).

Brak komentarzy:

Prześlij komentarz