#c# #recursion #razor #asp.net-core-mvc #model-binding
Вопрос:
Мне трудно отправить обратно свою модель контроллеру. С тем, что я сделал, я получаю только корневой элемент и один дочерний элемент, отправленный обратно на контроллер. Я знаю, что проблема в том, что с рекурсивной функцией все html-элементы в конечном итоге имеют одно и то же имя, но как я могу это исправить? Поскольку я не знаю, сколько уровней будет в моем списке, я не могу использовать их для циклов :/
Это мой класс:
public class BilletesViewModel
{
public string Id { get; set; }
public string IdPadre { get; set; }
public string IdHijo { get; set; }
public int Nivel { get; set; }
public string Familia { get; set; }
public string Material { get; set; }
public decimal Cantidad { get; set; }
public string UnidadDeMedida { get; set; }
public int UnidadDeMedidaId { get; set; }
public string Merma { get; set; }
public bool Raiz { get; set; }
public List<BilletesViewModel> ListaMateriales { get; set; }
public List<SelectListItem> ListaUnidadesDeMedida { get; set; }
}
И это мое мнение. Я публикую все это на случай, если я упущу что-то еще.
@model DulcesDeLaRosa.Models.BilletesViewModel
@{
ViewBag.Title = "Nuevo Billete de Materiales";
var disabled = Model.ListaMateriales != null amp;amp; Model.ListaMateriales.Count > 0 ? "disabled" : "";
}
@helper ShowTree(List<DulcesDeLaRosa.Models.BilletesViewModel> ListaMateriales, int nivel, int contador)
{
if (ListaMateriales != null)
{
foreach (var material in ListaMateriales)
{
var marginLeft = 30 * nivel;
var marginString = marginLeft "px;";
var claseBorde = nivel > 0 ? "" : "";
<div class="form-inline col-12" style="margin-top:2%">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => material.Id)
<hr />
<div class="col-4 delarosa-max-width">
<div class="form-group col-12 delarosa-max-width" style="margin-left:@marginString">
@Html.EditorFor(model => material.Material, new { htmlAttributes = new { @class = "form-control delarosa-max-width" } })
@Html.ValidationMessageFor(model => material.Material, "", new { @class = "text-danger" })
</div>
</div>
<div class="col-2">
<div class="form-group col-12 delarosa-max-width">
@Html.EditorFor(model => material.Cantidad, new { htmlAttributes = new { @class = "form-control delarosa-max-width" } })
@Html.ValidationMessageFor(model => material.Cantidad, "", new { @class = "text-danger" })
</div>
</div>
<div class="col-2">
<div class="form-group col-12 delarosa-max-width">
@Html.DropDownListFor(model => material.UnidadDeMedidaId, material.ListaUnidadesDeMedida, new { @class = "form-control delarosa-max-width" })
@Html.ValidationMessageFor(model => material.UnidadDeMedidaId, "", new { @class = "text-danger" })
</div>
</div>
<div class="col-2">
<div class="form-group col-12 delarosa-max-width">
@Html.EditorFor(model => material.Merma, new { htmlAttributes = new { @class = "form-control delarosa-max-width" } })
@Html.ValidationMessageFor(model => material.Merma, "", new { @class = "text-danger" })
</div>
</div>
<div class="col-2">
<div class="form-group col-12">
<div class="col-9 offset-1">
<button type="submit" id="BtnAgregar" name="btn" class="btn btn-info delarosa-background" value="Agregar|@material.Id">Agregar Hijo</button>
</div>
<div class="col-2">
<button type="submit" id="BtnEliminar" name="btn" class="btn btn-info delarosa-background" value="Eliminar|@material.Id">X</button>
</div>
</div>
</div>
</div>
if (material.ListaMateriales != null amp;amp; material.ListaMateriales.Any())
{
<ul>
@ShowTree(material.ListaMateriales, nivel 1, contador 1)
</ul>
}
contador ;
}
}
}
<div style="margin-top: 20px;">
<h3>Nuevo Billete de Materiales</h3>
</div>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-inline col-12 delarosa-margen-div delarosa-max-width">
<div class="form-inline col-12 delarosa-max-width">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-inline col-11">
<div class="col-1">
<label class="delarosa-alineacion-izquierda">Familia: </label>
</div>
@Html.EditorFor(model => model.Familia, new { htmlAttributes = new { @class = "form-control", @id = "InputFamilia" } })
@Html.ValidationMessageFor(model => model.Familia, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Raiz, new { @Value = Model.Raiz })
</div>
<div class="col-1">
<input type="submit" id="BtnAgregarRaiz" name="btn" class="btn btn-info delarosa-background" value="Agregar Raiz" @disabled />
</div>
</div>
</div>
if (!Model.Raiz)
{
<div class="form-inline col-12 delarosa-margen-div">
<div class="col-4">
<div class="form-group col-12 delarosa-alineacion-centro">
<label class="delarosa-alineacion-centro">Material</label>
</div>
</div>
<div class="col-2">
<div class="form-group col-12 delarosa-alineacion-centro">
<label class="delarosa-alineacion-centro">Cantidad</label>
</div>
</div>
<div class="col-2">
<div class="form-group col-12 delarosa-alineacion-centro">
<label class="delarosa-alineacion-centro">Unidad</label>
</div>
</div>
<div class="col-2">
<div class="form-group col-12 delarosa-alineacion-centro">
<label class="delarosa-alineacion-centro">Merma %</label>
</div>
</div>
<div class="col-2">
<div class="form-group col-12 delarosa-alineacion-centro">
<label class="delarosa-alineacion-centro">Acciones</label>
</div>
</div>
</div>
<hr style="margin-bottom:2%" />
@ShowTree(Model.ListaMateriales, 0, 0)
}
<div class="form-inline col-12 delarosa-margen-div" style="width:100%">
<div class="col-6" style="text-align:left;">
@Html.ActionLink("Regresar", "Index", null, new { @class = "btn btn-outline-danger" })
</div>
<div class="col-6" style="text-align:right;">
<input type="submit" name="btn" value="Crear" class="btn btn-outline-danger" />
</div>
</div>
}
Кто-нибудь пробовал что-то подобное? Есть ли какой-нибудь способ, которым я могу это решить?
Я был бы признателен за любые указания
Комментарии:
1. Скорее, чем
foreach (var material in ListaMateriales)
тебе нужноfor (var i=0;i<ListaMateriales.Count;i )
….EditorFor(model => ListaMateriales[i].Material,
2. @JeremyLakeman Да, это работает, если я зацикливаюсь на первом списке, но на самом деле я не знаю глубины списка, он может быть от 1 до n вложенных циклов.
3. Ах. ИМХО, создайте в
Dictionary<string,BilletesViewModel>
качестве своей модели, проиндексированную полем идентификатора. То, что вы отображаете значения в виде дерева, не означает, что вам нужно привязывать свою модель в виде дерева.4. @JeremyLakeman Хорошо, да, я думаю, что в этом есть смысл. Я собираюсь попробовать этот подход. Спасибо.