Ошибка «Шаблоны можно использовать только с доступом к полю, доступом к свойствам, индексом одномерного массива или выражениями настраиваемого индексатора с одним параметром»

107

Почему я получаю сообщение об ошибке:

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

в этом коде:

@model IEnumerable<ArtSchoolProject.Models.Trainer>

@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_PageLayout.cshtml";
}

<h2>Index</h2>

<p>
@Html.ActionLink("Create New", "Create")
</p>
<ul class="trainers">


@foreach (var item in Model) {
<li>
  <div>
      <div class="left">
          <a href="@Url.Action("Details", "Details", new { id = item.ID })">
              <img src="~/Images/Trainer/@item.Picture" />
          </a>
      </div>
      <div class="right">
          @Html.ActionLink(item.Name,"Details",new {id=item.ID})
          <br />
          @Html.DisplayFor(modelItem=>@string. item.Description.ToString().Substring(0,100))
      </div>
  </div>
  </li>
  }

  </ul>

в строке:

@Html.DisplayFor(modelItem=>item.Description.ToString().Substring(0,100))

Обновить:

Задача решена. Я добавил в свой код:

  @{
string parameterValue = item.Description.ToString().Substring(0, 100); 
          }
          @Html.DisplayFor(modelItem=>parameterValue)

Мой новый код:

@foreach (var item in Model) {
<li>
  <div>
      <div class="left">
          <a href="@Url.Action("Details", "Details", new { id = item.ID })">
              <img src="~/Images/Trainer/@item.Picture" />
          </a>
      </div>
      <div class="right">
          @Html.ActionLink(item.Name,"Details",new {id=item.ID})
          <br />
          @{
string parameterValue = item.Description.ToString().Substring(0, 100); 
          }
          @Html.DisplayFor(modelItem=>parameterValue)
      </div>
  </div>
 </li>
}

Это только одна возможность. Просто из любопытства, есть ли другое решение для решения ошибки?

POIR
источник
3
Превосходно! Ваше решение сработало для меня, и оно очень простое. Было бы неплохо, если бы вы могли поместить свое решение в качестве ответа вместо обновления и принять его. поскольку мы обычно смотрим на принятые ответы.
Dush

Ответы:

101

У меня была такая же проблема с чем-то вроде

@foreach (var item in Model)
{
    @Html.DisplayFor(m => !item.IsIdle, "BoolIcon")
}

Я решил это, просто сделав

@foreach (var item in Model)
{
    var active = !item.IsIdle;
    @Html.DisplayFor(m => active , "BoolIcon")
}

Когда вы знаете фокус, это просто.

Разница в том, что в первом случае я передал метод в качестве параметра, а во втором - это выражение.

Даниэль
источник
1
Отлично!!! Спасибо за ответ @Daniel, я часами боролся с этим
дерьмом
75

Шаблон, на который он ссылается, является помощником Html DisplayFor.

DisplayFor ожидает получить выражение, соответствующее правилам, указанным в сообщении об ошибке.

Вы пытаетесь передать цепочку методов для выполнения, и это не нравится.

Это прекрасный пример того, как пригодится шаблон MVVM (Model-View-ViewModel).

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

class TrainerViewModel
{
    private Trainer _trainer;

    public string ShortDescription
    {
        get
        {
            return _trainer.Description.ToString().Substring(0, 100);
        }
    }

    public TrainerViewModel(Trainer trainer)
    {
        _trainer = trainer;
    }
}

Вы бы изменили свой класс модели представления, чтобы он содержал все свойства, необходимые для отображения этих данных в представлении, отсюда и название ViewModel.

Затем вы должны изменить свой контроллер, чтобы он возвращал TrainerViewModelобъект, а не Trainerобъект, и также измените объявление типа модели в файле представления на TrainerViewModel.

Шон Эйри
источник
5
+1 за правильную интерпретацию сообщения об ошибке и за лучшее решение, чем трюк, описанный другими.
R. Schreurs
11

Я столкнулся с аналогичной проблемой с тем же сообщением об ошибке, используя следующий код:

@Html.DisplayFor(model => model.EndDate.Value.ToShortDateString())

Я нашел здесь хороший ответ

Оказывается, вы можете украсить свойство в своей модели форматом отображения, а затем применить строку dataformatstring.

Обязательно импортируйте в свою модель следующую библиотеку:

using System.ComponentModel.DataAnnotations;
Роб
источник
0

Заполните служебный слой моделью, а затем отправьте ее в представление. Например: ViewItem = ModelItem.ToString (). Substring (0,100);

RainyTears
источник