ЖАНРЫ

Шрифт:

sb.Append("<option></option>") ;

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

{

sb.Append("<option>");

sb.Append(i.ToString);

sb.Append("</option>");

sb.Append("</select>");

sb.Append(" ");

}

/* Month */

sb.Append("<select id=\"month_");

sb.Append(id);

sb.Append("\">");

sb.Append("<option></option>");

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

{

sb.Append("<option>");

sb.Append(DateTimeFormatInfo.CurrentInfo.MonthNames[i]);

sb.Append("</option>");

}

sb.Append("</select>");

sb.Append(" ");

/* Year */

sb.Append("<select id=\"year_");

sb.Append(id);

sb.Append("\">");

sb.Append("<option></option>");

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

{

sb.Append("<option>");

sb.Append(i.ToString);

sb.Append("</option>");

}

sb.Append("</select>");

if (!String.IsNullOrEmpty(text))

{

sb.Append("</div>");

}

return sb.ToString;

}

}

Плюс

решения, продемонстрированного в листинге 5.11, — простота реализации "в лоб", копированием кода из макета верстки. Минусы решения очевидны — поддержка такого кода сложна за счет необходимости работы с кодом, перемешанным с большим количеством строковых констант.

Использование ресурсов

Упростить модификацию самой разметки и внесение в нее косметических изменений можно за счет размещения статических строковых констант в файлах ресурсов. Генерацию финальной разметки при этом можно выполнять, используя только методы форматирования строк, как это показано в листинге 5.12.

Листинг 5.12. Реализация метода DatePickerc помощью ресурсов

public static string DatePicker(this HtmlHelper html,

string id, string text)

{

return String.Format(Resources.DatePicker, id, text,

Resources.DaysOptions,

Resources.MonthsOptions, Resources.YearsOptions);

}

В приведенном фрагменте есть заметное преимущество — централизованное управление разметкой, возможность использования разной разметки для различных культур и разделение самой разметки и кода. Можно пойти дальше и создать дополнительную обертку над ресурсами, которая будет отвечать за небольшую модификацию фрагментов разметки. Кода в случае, приведенном в листинге 5.12, значительно меньше, чем в листинге 5.11, однако гибкость такого решения может быть недостаточной для вспомогательных методов, требующих частой модификации.

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

Достигнуть большего контроля над логикой и разметкой можно за счет использования дополнительной абстракции над созданием самой разметки, вынесением отдельных методов, генерирующих повторяющие элементы, и созданием тегов с помощью специального класса 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

Поделиться с друзьями: