Использование дополнительных слоев абстракции

Достигнуть большего контроля над логикой и разметкой можно за счет использования дополнительной абстракции над созданием самой разметки, вынесением отдельных методов, генерирующих повторяющие элементы, и созданием тегов с помощью специального класса TagBuilder. В WebForms при создании контролов (Custom Controls) используется похожий подход.

TagBuilder активно применяется в расширениях, входящих в саму сборку System.Web.Mvc, в чем можно убедиться, посмотрев, например, на исходный код System.Web.MVC.SelectExtensions.

В листинге 5.13 приведен код, использующий больше абстракции, нежели предыдущие. Также в листинге 5.13 продемонстрирована простая концепция по восстановлению значений после отправки данных на сервер (метод Getvalue, выполняющий поиск в коллекции viewData, затем в параметрах запроса).

Листинг 5.13. Реализация метода DatePicker с дополнительными слоями абстракции

public static class DataPickerHelper

{

  private static string DAY_PREFIX = "day_";

  private static string MONTH_PREFIX = "month_";

  private static string YEAR_PREFIX = "year_";

  private static string ListItemToOption(SelectListItem item)

  {

    TagBuilder builder = new TagBuilder("option")

    {

      InnerHtml = HttpUtility.HtmlEncode(item.Text)

    };

    if (item.value != null)

      builder.Attributes["value"] = item.Value;

    if (item.Selected)

      builder.Attributes["selected"] = "selected";

    return builder.ToString(TagRenderMode.Normal);

}

private static string SelectList(string id,

                             List<SelectListItem> items)

{

  StringBuilder listItemBuilder = new StringBuilder();

  foreach (var item in items)

  {

    listItemBuilder.AppendLine(ListItemToOption(item));

  }

  TagBuilder tagBuilder = new TagBuilder("select")

  {

    InnerHtml = listItemBuilder.ToString()

  };

  tagBuilder.Attributes.Add("id", id);

  tagBuilder.Attributes.Add("name", id);

  return tagBuilder.ToString(TagRenderMode.Normal);

}

  public static string DatePicker(this HtmlHelper html, string id)

  {

    return DatePicker(html, id, String.Empty);

  }

  public static string DatePicker(this HtmlHelper html,

                                string id, string text)

  {

    // buffer

    StringBuilder sb = new StringBuilder();

    // generate days

    List<SelectListItem> days = new List<SelectListItem>();

    string dayValue = GetValue(html, DAY_PREFIX + id);

    for (int i = 0; i <= 31; i++)

    {

      days.Add(new SelectListItem

      {

        Text = (i == 0) ? String.Empty : i.ToString(),

        Value = i.ToString(),

        Selected = (dayValue == i.ToString())

      });

    }

    sb.AppendLine(SelectList(DAY_PREFIX + id, days));

    // generate months

    List<SelectListItem> months = new List<SelectListItem>();

    string monthValue = GetValue(html, MONTH_PREFIX + id);

    for (int i = 0; i <= 12; i++)

    {

      months.Add(new SelectListItem

      {

        Text = (i == 0) ? String.Empty :

           DateTimeFormatInfo.CurrentInfo.MonthNames[i — 1],

        Value = i.ToString(),

        Selected = (monthValue == i.ToString())

      });

    }

    sb.AppendLine(SelectList(MONTH_PREFIX + id, months));

    // generate years

    List<SelectListItem> years = new List<SelectListItem>();

    string yearValue = GetValue(html, YEAR_PREFIX + id);

    for (int i = 1900; i <= DateTime.Now.Year; i++)

    {

      years.Add(new SelectListItem

      {

        Text = (i == 1900) ? String.Empty : i.ToString(),

           Value = i.ToString(),

        Selected = (yearValue == i.ToString())

      });

    }

    sb.AppendLine(SelectList(YEAR_PREFIX + id, years));

    // parent tag

    if (!String.IsNullOrEmpty(text))

    {

      TagBuilder div = new TagBuilder("div");

      div.Attributes.Add("id", id);

      div.InnerHtml = text + sb.ToString();

      sb = new StringBuilder(

              div.ToString(TagRenderMode.Normal));

    }

    return sb.ToString();

  }

  private static string GetValue(HtmlHelper html, string id)

  {

    object o = null;

    if (html.ViewData != null)

      o = html.ViewData.Eval(id);

    if (o == null)

      o = html.ViewContext.RequestContext.HttpContext.Request.Params[id];

    return (o == null) ? String.Empty : o.ToString();

  }

}

Более 800 000 книг и аудиокниг! 📚

Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением

ПОЛУЧИТЬ ПОДАРОК