Вторник, 30 мая, 2017

Применение хелперов DisplayFor и собственных шаблонов в ASP.NET MVC

комментарии: 2

Одно из интересных дополнений в ASP.NET MVC, которое появилось еще во второй версии, это возможность применять шаблоны для полей классов, которые преобразовываются в HTML, так как это нужно разработчику. Допустим, одно и тоже поле нужно отобразить в нескольких представлениях. Причем рендеринг этого поля находится в одном месте, он настраивается произвольно и одинаково работает во всех представлениях. Рассмотрим модель, которая будет использоватся для отображения в представлении:

    public class Author
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public string Avatar { get; set; }
        public bool Active { get; set; }
    }

    public class Post
    {
        public string Title { get; set; }
        public string Body { get; set; }
        public string Rating { get; set; }
        public DateTime Date { get; set; }
        public Author AuthorInfo { get; set; }
    }

Реализуем простой метод действия для тестирования отображения нашей модели:

        //
        // GET: /Home/

        public ActionResult Index()
        {
            var author = new Author
                {
                    Name = "codehint", 
                    Email = "codehint@company.com",
                    Active = true,
                    Avatar = "http://cs403223.vk.me/v403223819/989d/loWi8Z-KVUs.jpg"
                };

            var post = new Post
                {
                    Title = "ASP.NET MVC",
                    Body = "ASP.NET MVC - замечательный фреймворк",
                    Date = DateTime.Now,
                    AuthorInfo = author
                };

            return View(post);
        }

Если создать строго типизированное представление для выше приведенных классов по получится следующее:

@model MvcApplication.Models.Post
<fieldset>
    <legend>Информация о посте</legend>
    <p>Заголовок: @Model.Title</p>
    <p>Текст: @Model.Body</p>
    <p>Дата: @Model.Date</p>
</fieldset>
<fieldset>
    <legend>Автор</legend>
    <p>Имя: @Model.AuthorInfo.Name</p>
    <p>Email: @Model.AuthorInfo.Email</p>
    <p>Действующий: @Model.AuthorInfo.Active</p>
    <p>Автар: @Model.AuthorInfo.Avatar</p>
</fieldset>

Второй fieldset добавлен для отображения информациии об авторе. Запускаем приложение и видим следующее:

Все отображенные свойства представляют собой строки, кроме даты. Шаблоны по умолчанию, которые предлагает Visual Studio, отображают строки как строки, а режиме редактирования как TextBox. В MVC введена концепция шаблонов, которые тесно связаны с работой Dynamic Data. Фреймворк включает в себя набор шаблонов для каждого типа поля, плюс еще разработчик может сам расширить каждый рендеринг по умолчанию, добавляя свой собственный шаблон. Изменим вышеприведенное представление, используя строготипизированные хелперы:

@model MvcApplication.Models.Post

Информация о посте

Заголовок: @Html.DisplayFor(x => x.Title)

Текст: @Html.DisplayFor(x => x.Body)

Дата: @Html.DisplayFor(x => x.Date)

Автор

Имя: @Html.DisplayFor(x => x.AuthorInfo.Name)

Email: @Html.DisplayFor(x => x.AuthorInfo.Email, "Email")

Действующий: @Html.DisplayFor(x => x.AuthorInfo.Active)

Аватар: @Html.DisplayFor(x => x.AuthorInfo.Avatar)

Заметим, что хелпер DisplayFor позволяет указать шаблон в качестве второго параметра, что будет показано дальше. Существует еще EditorFor для представлений редактирования. Если мы запустим приложение, то вобщем ничего не изменилось, кроме одной детали.

Сейчас поле автора Active изменилось на CheckBox. Как это произошло? Дело в том, что хелпер DisplayFor использует шаблоны для рендеринга. А так как Active - это тип Boolean, то вместо строки отображается CheckBox. Хорошая новость заключается в том, что разработчик может сам дополнить или изменить это поведение для собственных нужд. Это сильное вспомогательное средство, когда можно заранее приготовить шаблоны для необходимого отображения данных. Также если мы посмотрим на страницу, то увидим что отображаются и дата и время. Допустим, мы хотим, чтобы отображалась только дата. Первое, что приходит в голову, это воспользоватся форматированием и вывести одну дату, но это придется делать для каждого представления, где выводится дата поста. Но, лучшим решением будет создать шаблон для даты.

В Solution Explorer в папке Views/Home создадим подпапку DisplayTemplates:

В этой папке создадим частичное представление и назовем его DateTime:

@model DateTime

@Model.ToString("dd-MM-yy")

Запустим приложение и увидим что отображена одна дата:

Итак, что здесь произошло: хелпер DisplayFor обнаружил, что мы создали шаблон для DateTime и он выбрал его вместо шаблона по умолчанию. Это значит, что мы можем изменить отображение полей, которое нам предлагает ASP.NET MVC. Но этого может быть недостаточно в некоторых случаях.

Обратим внимание на поле Email. Оно отображено на странице в виде простой строки, но нам нужно чтобы это была ссылка. Тогда пользователи смогут отправлять email просто кликая на ссылку. Проблема в том, что это просто строка - тип String и мы не можем переопределить шаблон для всех строк.

К счастью, есть маневр, позволяющий переопределить шаблон только для поля Email. Для этого используем второй параметр в хелпере DisplayFor, который позволяет указать шаблон. Создадим второе частичное представление и назовем его Email:

@model String

@Model

Добавим параметр в представлении:

Email: @Html.DisplayFor(x => x.AuthorInfo.Email, "Email")

Запустим приложение и увидим ссылку:

Итак, нам удалось изменить отображение электронной почты с помощью собственного шаблона. Единственное что не радует, это то, что нужно указывать имя шаблона в каждом хелпере DisplayFor. Лучше это сделать как-то централизованно и не изменять код в каждом представлении. И тут приходит на помощь средство Data Annоtation (другая концепция Dynamic Data). Создадим еще одно частичное представление, назовем его Avatar, и напишем следующий код:

@model String


И дальше вместо указания второго параметра в хелперах, найдем модель Author и добавим одну маленькую деталь:

        [UIHint("Avatar")]
        public string Avatar { get; set; }

Мы определили шаблон в одном месте прямо над полем Avatar. Запустим приложение и увидим на странице:

Так как шаблон указан прямо в определении модели, то все представления, отображающие поле Avatar будут использовать шаблон Avatar.cshtml. И это значит, что при изменении кода в шаблоне все представления обновятся автоматически.

Комментарии

Oleksandr Musatkin Oleksandr Musatkin 30 января, 2015, 07:12
При вводе @HTML, не предоставляется возможность дописать DisplayFor, т.е @HTML.DisplayFor подчеркивает красным, ошибка, нет такого метода пишет. Что делать?
Василий Мажекин Василий Мажекин 04 февраля, 2015, 07:58
Oleksandr, нужно подключить неймспейс System.Web.Mvc.Html там класс с этим методом DisplayExtensions.DisplayFor

 

Добавить комментарий

Войти через Twitter Войти через Facebook Войти через ВКонтакте Войти через Github Войти через Google Войти через LinkedIn

Copyright © 2013 All Rights Reserved for CodeHint.ru      Powered by Windows Azure