Using Editor Templates to Display Multiple Forms
我的问题与这个问题非常相似。我正在开发的应用程序是用 MVC 3 和 Razor 编写的。它允许其用户从商店中选择商品并将每件商品发送到不同的地址。
这是我的 ViewModel:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class DeliveryDetailsViewModel
{ public FromDetailsViewModel From { get; set; } public IList<ToDetailsViewModel> To { get; set; } } public class DetailsViewModel public class FromDetailsViewModel : DetailsViewModel public class ToDetailsViewModel : DetailsViewModel |
我的观点与下面类似。
1
2 3 4 5 |
@model Store.ViewModels.DeliveryDetailsViewModel
@Html.EditorFor(m => m.From) @Html.EditorFor(m => m.To) |
我的意图是显示一组表单(购物车中的每个项目一个),以使用户能够输入不同的交货详细信息。每个表单都有自己的提交按钮。
呈现”To”表单的编辑器模板如下:
1
2 3 4 5 6 7 8 9 10 11 |
@model Store.ViewModels.ToDetailsViewModel
@using (Html.BeginForm(“ConfirmTo”,“Delivery”)) <input type=“submit” value=“Confirm” /> |
我的控制器:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class DeliveryController : Controller
{ public ActionResult Index() { var model = new DeliveryDetailsViewModel(); model.From = new FromDetailsViewModel(); model.To = new List<ToDetailsViewModel>(); return View(model); } public ActionResult ConfirmTo(ToDetailsViewModel toDetails) |
我有几个问题:
“to”编辑器模板没有渲染任何东西(尽管它曾经如此)。它指出模型类型不匹配(即 ToDetailsViewModel 与 List<ToDetailsViewModel> 不同),尽管我认为编辑器模板应该将索引附加到输入字段名称以启用正确的绑定。
当点击确认并提交 To 列表中的第一个表单时,控制器接收到具有正确绑定的视图模型。提交以下任何表单(索引为 1 或更大)调用 ConfirmTo 操作并传递一个为空的 ToDetailsViewModel。
我们将不胜感激,如果您想了解有关我遇到的问题或我正在使用的代码的更多信息,请随时询问。
1) The”to” editor template isn’t rendering anything
在您的控制器操作中,您没有在列表中添加任何内容。你只是实例化了它。所以放一些元素:
1
2 3 4 |
2) When clicking Confirm and submitting the first form in the To list the controller receives the view model with the correct bindings. Submitting any of the following forms (with index 1 or greater) calls the ConfirmTo action and passes a ToDetailsViewModel which is null.
如果这对第一个元素也有效,我会感到惊讶,因为输入字段当前没有正确的名称。它们都以 To[someIndex] 为前缀,而您的 ConfirmTo 需要一个平面模型,而不是一个集合。
所以您可以将前缀设置为空字符串,以便在您的 ~/Views/Shared/EditorTemplates/ToDetailsViewModel.cshtml 编辑器模板中生成正确的输入元素:
1
2 3 4 5 6 7 8 9 10 11 12 13 |
@model ToDetailsViewModel
@{ ViewData.TemplateInfo.HtmlFieldPrefix =“”; } @using (Html.BeginForm(“ConfirmTo”,“Home”)) { @Html.TextBoxFor(m => m.FirstName) @Html.TextBoxFor(m => m.LastName) @Html.TextBoxFor(m => m.Email) @Html.TextBoxFor(m => m.Message) <input type=“submit” value=“Confirm” /> |
- 感谢您的帮助达林,我的问题的第 1 部分已解决!关于输入字段前缀,您提供的解决方案有效,但这意味着如果我返回视图并为其提供更新的模型,所有 FirstName 字段都会获得我输入的值,而不仅仅是我输入的一个表单已编辑。 (我希望我能很好地表达自己,以便被理解。)
- 我通过使用 RedirectToAction(“Index”) 而不是返回 View(“Index”, model) 解决了这个问题。谢谢达林!
1) 你试过这个吗,因为你的视图模型有
1
|
public IList<ToDetailsViewModel> To { get; set; }
|
To 是一个列表,因此你的编辑器模板应该有
1
|
@model IEnumerable<Store.ViewModels.ToDetailsViewModel>
|
并且模板应该使用foreach
1
|
@foreach(model in Model){}
|
- 不幸的是,我已经尝试过了,是的。因为”to”表单在页面上出现多次,模型绑定器会感到困惑,并使用提交的输入填写所有”FirstName”字段。这是因为每个表单的输入名称都相同。
- 此外,将视图模型列表传递给 EditorFor() 助手应该处理创建具有不同名称的字段。例如:”To_0__FirstName”和”To_1__FirstName”。
- 那么不如使用提交按钮,只需使用 <input type = button> 并编写一个 jQuery 来获取信息并通过 jQuery 提交
- 为此,您可以将 To 的 id 绑定到必要的列
- 我想到了这一点,这是一个非常好的建议,但是如果用户禁用了 JavaScript 怎么办?
来源:https://www.codenong.com/9389367/