Как динамически заполнить HTML с помощью Model в цикле foreach в Aspnet.core Razor? - PullRequest
0 голосов
/ 08 марта 2019

Я на самом деле пытаюсь динамически заполнить HTML-код в Asp.Net Core Razor, и я хочу использовать что-то вроде этого:

@model Aktienverwaltung.Models.ProtokollDividenden

foreach (var item in Model)
{
   <div class="form-group row">
       <label asp-for="@item" class="col-lg-3 control-label text-lg-right pt-2" for="inputRounded"></label>
       <div class="col-lg-6">
           <input asp-for="@item" class="form-control input-rounded" id="inputRounded" />
       </div>
       <span asp-validation-for="@item" class="text-danger"></span>
   </div>
}

это часть моего контроллера:

public async Task<IActionResult> Edit(Guid? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var protokollDividenden = await _context.ProtokollDividenden.FindAsync(id);
    if (protokollDividenden == null)
    {
        return NotFound();
    }
    // return View(await _context.ProtokollDividenden.ToListAsync());
    return View(protokollDividenden);
}

и Модель:

public partial class ProtokollDividenden
    {
        public Guid Id { get; set; }
        public string Aktie { get; set; }
        public string Depotname { get; set; }
        public string Wkn { get; set; }
        public string Kuerzel { get; set; }
        public double Dividende { get; set; }
        public DateTime Datum { get; set; }
        public bool BereitsVerarbeitet { get; set; }
    }

Все, что я пробовал, идет не так, потому что я не могу перечислить Модель или что-то еще.Я тоже попробовал его как List (см. Незакомментированную область в Controller), но я не могу заставить цикл foreach работать - у кого-нибудь была идея?

1 Ответ

0 голосов
/ 08 марта 2019

Во-первых, вы можете только перечислить перечислимое , то есть IEnumerable<T>, List<T> и т. Д. Сейчас у вас есть только один элемент в качестве модели, поэтому foreach будет очевидно ошибка.

Если вы do вернете перечисляемую модель, то ваша следующая проблема - привязка модели.Чтобы правильно связать данные, которые вы публикуете, с параметром в вашем действии, типы списков должны быть названы в соответствии с форматом CollectionProperty[N].Property, где N - индекс.Чтобы такие вещи, как помощники по тегам, генерировали правильные атрибуты name на входах формы, им необходимо полное выражение модели.Вы можете думать о модельном выражении как о карте к определенному свойству, с которым вы пытаетесь связать.

Допустим, вы спросили меня, как добраться до места.В идеале вам понадобятся шаги, с которых вы начнете прямо сейчас.Если бы я начинал свои указания с какого-то другого места, это не сильно помогло бы, потому что тогда вам потребовались бы указания на это место сначала , прежде чем вы могли бы следовать моим указаниям до конечного пункта назначения.

Концепция здесь аналогична.Использование foreach и создание переменной item, в основном, удаляет первую часть направлений.Помощники по тегам знают, как добраться от item до свойства, с которым вы связываетесь, но они не знают, как добраться до item.Таким образом, вы получите имена типа item.Foo, которые не смогут быть связаны с чем-то значимым.Вместо этого вам нужно использовать цикл for и полное выражение модели с использованием индекса в цикле:

@for (var i = 0; i < Model.Count; i++) // assuming `Model` is a list
{
    <input asp-for="@Model[i].Foo" />
}

Стоит отметить, что значение asp-for выше является специальной конструкцией, необходимой, так как Model - это список, по которому вы перебираете.Если бы вместо этого было свойство списка в модели, вы просто использовали бы asp-for="ListProperty[i].Foo".Часть @Model существует просто потому, что некоторый фактический член должен использоваться перед индексной нотацией.Я видел, как люди смущаются этим и начинают пытаться поставить @Model перед всем, то есть @Model.ListProperty[i].Foo.

РЕДАКТИРОВАТЬ

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

Есть Html.EditorFor и Html.EditorForModel (который, я думаю , все еще существует в ASP.NET Core ... я не использую их лично).Оба являются «шаблонными помощниками», что означает, что они полагаются на шаблоны, чтобы определить, как они обрабатывают то, что им передается.Так как вы работаете со своей моделью прямо здесь, вы захотите Html.EditorForModel, который вы будете использовать буквально через следующее вместо всего вашего текущего кода представления:

@Html.EditorForModel()

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

<label for="Id">Id</label>
<input id="Id" name="Id" value="" />

<label for="Aktie">Aktie</label>
<input id="Aktie" name="Aktie" value="" />

<label for="Depotname">Depotname</label>
<input id="Depotname" name="Depotname" value="" />

...

Естьнекоторые очевидные проблемы с этим.У него нет ни одного из ваших классов или структуры Bootstrap, поэтому он будет выглядеть ужасно.Это очень просто в интерпретации отображения типа на вход.Например, Id - это то, чего, вероятно, вообще не должно быть, или, если оно присутствует, это должен быть скрытый ввод.Aktie может быть длинным текстовым полем, но вы всегда будете получать ввод, а не что-то вроде textarea.Возможно, Depotname должен быть select с некоторым списком возможных вариантов, но опять же, вы только когда-нибудь получите базовый текстовый ввод.Список можно продолжить.

Некоторые из них можно исправить проще, чем другие.Чтобы получить скрытый ввод, примените атрибут [HiddenInput] к свойству в вашем классе.Атрибут DataType можно применить, чтобы придать дополнительный контекст.Например, если вы хотите textarea, вы можете применить [DataType(DataType.MultilineText)] к свойству в вашем классе.Если вам нужно изменить текст метки, вы можете сделать это с помощью [Display(Name = "My Label Text")].

Для более сложных вещей именно здесь начинают поступать шаблоны. Например, вы можете создать представление типа Views\Shared\EditorTemplates\String.cshtml и внутри добавить:

@model string

<div class="form-group row">
   <label asp-for="@Model" class="col-lg-3 control-label text-lg-right pt-2" for="inputRounded"></label>
   <div class="col-lg-6">
       <input asp-for="@Model" class="form-control input-rounded" id="inputRounded" />
   </div>
   <span asp-validation-for="@Model" class="text-danger"></span>

Затем этобудет использоваться для любого члена типа string.Как вы можете себе представить, вы можете добавить другие такие виды, как DateTime.cshtml, Int32.cshtml и т. Д., Каждый из которых будет использоваться для их соответствующих типов.Вы также можете добавить шаблоны для любого из элементов этого перечисления DataType, чтобы вы могли иметь MultilineText.cshtml, EmailAddress.cshtml и т. Д. Наконец, есть атрибут UIHint, который можно применять для указания любого шаблона.Например, если вы применили [UIHint("Foo")] к свойству, тогда будет использоваться Foo.cshtml.

Вы также можете создавать шаблоны для своих собственных пользовательских типов.Так, например, у вас может быть ProtokollDividenden.cshtml, и тогда это представление будет фактически использоваться в качестве шаблона для этого класса, что означает, что оно будет использоваться для вашего вызова @Html.EditorForModel().

Однако,При этом важно отметить, что после добавления пользовательского шаблона вы на 100% ответственны за это сейчас.Другими словами, если бы вы добавили представление для всей вашей модели, это заняло бы место, и Html.EditorForModel на самом деле больше не генерировал бы отдельные поля для вас, в основном возвращая вас к той же проблеме, с которой вы начали,Вместо этого он просто сбросил бы ваш пользовательский шаблон и назвал бы его днем.

...