Создание пользовательских элементов пользовательского интерфейса в MVC 3

#asp.net-mvc-3 #razor

#asp.net-mvc-3 #razor

Вопрос:

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

Поэтому я подумал, что делать это для каждого поля было излишеством

 @if (Model.CanEdit)
{ 
    @Html.TextBoxFor(model => Model.Foo, new { width = "100px" })
}
else
{ 
    @Html.TextBox(model => Model.Foo, new { width = "100px", @readonly = "readonly"})
}
  

Я решил использовать шаблон редактора, но потом понял, что ширину нельзя зафиксировать, поэтому мне было интересно, каков наилучший способ отправки параметров в шаблон редактора? Также он должен обрабатывать сценарий, в котором width может быть не определен, и вообще не использовать свойство width. Я обнаружил, что ViewData может помочь с этим, но наличие кода, который выглядит так, заставляет меня чувствовать, что я делаю что-то неправильно.

 @inherits System.Web.Mvc.WebViewPage<string>
@if (Model.CanEdit)
{ 
    @if(ViewData["width"] == null)
    {
        @Html.TextBox("", Model, new { width = ViewData["width"].ToString() })
    }
    else
    {
        @Html.TextBox("", Model)
    }
}
else
{ 
    @if(ViewData["width"] == null)
    {
        @Html.TextBox("", Model, new { width = ViewData["width"].ToString() , @readonly = "readonly"})
    }
    else
    {
        @Html.TextBox("", Model, new {@readonly = "readonly"})
    }
}
  

Интересно, может ли быть способ создать помощника, чтобы я мог сделать что-то вроде:

 @MyTextBoxFor(model => Model.Foo, true) @* true would be or readonly *@
@MyTextBoxFor(model => Model.Foo, true, 100) @* 100 would be the width length *@
  

Ответ №1:

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

 public static class MyHelpers
{
    public static MvcHtmlString MyTextBoxFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression, 
        bool flagReadonly,
        int? widthProperty) where TModel : class
    {
        MemberExpression memberExpression = expression.Body as MemberExpression;
        string parameterName = memberExpression.Member.Name;

        return new MvcHtmlString(
            string.Format("<input id="{0}" name="{0}" {1} {2} />",
            parameterName, // name and if of parameter
            flagReadonly ? "readonly="readonly"" : string.Empty,
            widthProperty.HasValue ? 
                string.Format("width="{0}px"", (int)widthProperty) : 
                string.Empty));
    }
}
  

Конечно, таким образом, вам предоставляется возможность строго вводить элементы вашего представления

 @Html.MyTextBoxFor(model => model.Foo, true)
  

и

 @Html.MyTextBoxFor(model => model.Foo, true, 100)
  

и т.д.

Ответ №2:

Простой пример:

 public static class MyHelpers
{
    public static MvcHtmlString MyTextBox(this HtmlHelper htmlHelper, string name, string value = "", bool canEdit = false, int width = 100)
    {
        if (canEdit)
        {
            return htmlHelper.TextBox(name, value, new { width = width.ToString()   "px" });
        }
        else
        {
            return htmlHelper.TextBox(name, value, new { @readonly = "readonly", width = width.ToString()   "px" });
        }
    }
}
  

Затем зарегистрируйте класс в web.config или используйте инструкцию using

 @using test.Helpers
@Html.MyTextBox("test")
@Html.MyTextBox("test", "asdf")
@Html.MyTextBox("test", "asdf", true, 500)
  

Результат:

 <input id="test" name="test" readonly="readonly" value="" type="text" width="100px">
<input id="test" name="test" readonly="readonly" value="asdf" type="text" width="100px">
<input id="test" name="test" value="asdf" type="text" width="500px">