ASP.NET MVC - расширение TextBoxFor без переписывания метода - PullRequest
8 голосов
/ 01 июня 2011

Есть ли какой-нибудь возможный способ расширить основные html-помощники (TextBoxFor, TextAreaFor и т. Д.), Используя методы расширения на их выходе, вместо того, чтобы просто переписать все методы полностью? Например, добавив в ...

@Html.TextBoxFor( model => model.Name ).Identity("idName")

Я знаю, что могу добиться этого, используя уже следующее.

@Html.TextBoxFor( model => model.Name, new { @id = "idName" })

Но это становится неуклюжим и разочаровывающим, когда вам приходится начинать добавлять множество свойств. Есть ли способ добавить расширения к ним, не передавая htmlAttributes для каждой мелочи?

Ответы [ 2 ]

9 голосов
/ 02 июня 2011

Как говорит @AaronShockley, поскольку TextBoxFor() возвращает MvcHtmlString, единственным вариантом для разработки стиля «плавного API» для изменения выходных данных будет работа с MvcHtmlString, возвращаемыми вспомогательными методами.Немного другой способ сделать это, который, я думаю, подходит к тому, что вам нужно, состоит в том, чтобы использовать объект 'строителя свойств', например так:

public class MvcInputBuilder
{
    public int Id { get; set; }

    public string Class { get; set; }
}

... и настроить такие методы расширения, как этот:

public static MvcHtmlString TextBoxFor<TModel, TProp>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProp>> expression,
    params Action<MvcInputBuilder>[] propertySetters)
{
    MvcInputBuilder builder = new MvcInputBuilder();

    foreach (var propertySetter in propertySetters)
    {
        propertySetter.Invoke(builder);
    }

    var properties = new RouteValueDictionary(builder)
        .Select(kvp => kvp)
        .Where(kvp => kvp.Value != null)
        .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

    return htmlHelper.TextBoxFor(expression, properties);
}

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

@this.Html.TextBoxFor(
    model => model.Name,
    p => p.Id = 7,
    p => p.Class = "my-class")

Это дает вам строгую типизацию и интеллектуальный смысл для входных свойств, которые вы можете настроить для каждого метода расширения с помощьюдобавление свойств в соответствующий подкласс MvcInputBuilder.

6 голосов
/ 01 июня 2011

Все основные html-помощники возвращают объект типа System.Web.Mvc.MvcHtmlString. Вы можете настроить методы расширения для этого класса. Вот пример:

public static class MvcHtmlStringExtensions
{
    public static MvcHtmlString If(this MvcHtmlString value, bool check)
    {
        if (check)
        {
            return value;
        }

        return null;
    }

    public static MvcHtmlString Else(this MvcHtmlString value, MvcHtmlString alternate)
    {
        if (value == null)
        {
            return alternate;
        }

        return value;
    }
}

Затем вы можете использовать их в виде:

@Html.TextBoxFor(model => model.Name)
     .If(Model.Name.StartsWith("A"))
     .Else(Html.TextBoxFor(model => model.LastName)

Чтобы создать методы расширения, которые изменяют атрибуты в отображаемом теге HTML, вам нужно преобразовать результат в строку и найти и заменить искомое значение.

using System.Text.RegularExpressions;

public static MvcHtmlString Identity(this MvcHtmlString value, string id)
{
    string input = value.ToString();
    string pattern = @"(?<=\bid=")[^"]*";
    string newValue = Regex.Replace(input, pattern, id);
    return new MvcHtmlString(newValue);
}

public static MvcHtmlString Name(this MvcHtmlString value, string id)
{
    string input = value.ToString();
    string pattern = @"(?<=\bname=")[^"]*";
    string newValue = Regex.Replace(input, pattern, id);
    return new MvcHtmlString(newValue);
}

Атрибуты id и name всегда добавляются html-помощниками, но если вы хотите работать с атрибутами, которые могут отсутствовать (и вам придется добавить их вместо простой замены), вы Вам нужно будет изменить код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...