2013-11-28 3 views
4

Мне нужен общий встроенный помощник для отображения полей.ASP.NET MVC встроенный помощник для полей

Вот что я в настоящее время:

@helper DisplayField(Func<MyModel, string> field) 
{ 
    if (string.IsNullOrWhiteSpace(field(Model)) == false) 
    { 
     <div class="row"> @field(Model) </div>  
    } 
} 

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

@DisplayField(m => m.Name) 
@DisplayField(m => m.PhoneNumber) 

Я понятия не имею, как показать этикетку (DisplayAttribute) внутри помощника. Пожалуйста помоги.

ответ

7

В верхней части страницы добавьте использование для System.Linq.Expressions, например.

@using System.Linq.Expressions 

(или добавить это пространство имен в web.config).

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

@helper DisplayField(Expression<Func<MyModel, string>> field) 
{ 
    @Html.LabelFor(field) 
    @Html.DisplayFor(field) 
} 

Вы можете добавить дополнительную логику там, чтобы проверить наличие пустого значения и т.д. Вы можете быть лучше создание HtmlHelper, хотя, таким образом, вы могут использовать общие аргументы типа, а не «MyModel» и «string», как указано выше. Когда я последний раз пробовал, было невозможно добавить общие аргументы типа встроенному помощнику, например. следующее не возможно, если эта функция не была с тех пор добавил:

@helper DisplayField<TModel, TValue>(Expression<Func<TModel, TValue>> field) 
{ 
    @Html.LabelFor(field) 
    @Html.DisplayFor(field) 
} 

Таким образом, чтобы получить общий метод, вы бы использовать пользовательские HtmlHelper.Для этого:

  1. Создайте файл, как следующее:

    using System; 
    using System.Linq; 
    using System.Linq.Expressions; 
    using System.Web; 
    using System.Web.Mvc; 
    using System.Web.Mvc.Html; 
    
    namespace MvcApplication1.HtmlHelpers 
    { 
        public static class HtmlHelpers 
        { 
         public static MvcHtmlString DisplayFieldFor<TModel, TValue>(
          this HtmlHelper<TModel> helper, 
          Expression<Func<TModel, TValue>> field) 
         { 
          var labelString = helper.LabelFor(field); 
          var displayString = helper.DisplayFor(field); 
    
          return MvcHtmlString.Create(
           labelString.ToString() + 
           displayString.ToString()); 
         } 
        } 
    } 
    
  2. В вашей странице, использование такой вещи будет:

    @Html.DisplayFieldFor(m => m.Name) 
    @Html.DisplayFieldFor(m => m.PhoneNumber) 
    

и т.д. Вам может потребоваться проверить ваши данные на своей странице или добавить пространство имен для HtmlHelper в web.config.

+0

Почти то, что мне нужно, кроме того, что если это не строка, это не работает – Andrei

1

@ David_001 предоставил очень изящное MVC-решение для этого; Я оставляю здесь свой ответ, поскольку он описывает внутренний механизм и может быть полезен, если вам нужно решить проблему, не покрываемую MVC из помощников.

Изменить тип параметра от Func<MyModel, string> до Expression<Func<MyModel, string>>. Таким образом, вы получаете динамическое выражение в методе, который вы можете анализировать вместо статического делегата, который вы получаете в текущей форме.
Вы можете получить значение поля, как это:

var compExpr = field.Compile(); 
var value = compExpr.DynamicInvoke(Model); 

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

var memberAccExpr = (System.Linq.Expressions.MemberAccessExpression)field.Body; 
var attr = (DisplayAttribute)memberAccExpr.Member.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault(); 

Я проверил это примерно в проект C# (не MVC), поэтому я не могу сказать, работает ли он в Razor; но я уверен, что вы также можете переместить свой код в обычный класс.
Обратите внимание, что при таком подходе вы теряете некоторую безопасность типов, поскольку вызывающий может предоставлять различные динамические выражения методу. Поэтому вы должны принять это во внимание, если проанализировать выражение, чтобы найти атрибут.

Смежные вопросы