【问题标题】:MVC How do I create a form for a model which contains lists as propertiesMVC 如何为包含列表作为属性的模型创建表单
【发布时间】:2015-02-27 11:47:35
【问题描述】:

所以我有这个简单的模型:

public class OptOut
    {
        public int optOutID { get; set; }
        public bool hasOptedOut { get; set; }        
        public List<Cohort> list { get; set; }

        public OptOut()
        {
            List<Cohort> list = new List<Cohort>();
            list.Add(new Cohort());
            list.Add(new Cohort());
            list.Add(new Cohort());
            list.Add(new Cohort());
            this.list = list;
        }

    }

您可以看到其中一个属性是ListCohort 对象。 Cohort 对象有一些简单的布尔属性:

public class Cohort
    {
        public bool ukft { get; set; }
        public bool ukpt { get; set; }
        ...etc
    }

我想创建一个循环遍历Cohort 对象列表的表单。

所以在我的Controller 中,我将模型传递给View

public ActionResult Page()
        {                        
            return View(new OptOut());
        }

然后在 html 中创建一个像这样的表单:

 @using (Html.BeginForm("OptedOut", "Home"))
        {            var m = Model.list;

            <div id="radios" class="form-group" style="margin-top:25px;">
                @Html.RadioButtonFor(model => Model.hasOptedOut, true) <span style="margin-right:8px;">Yes</span>
                @Html.RadioButtonFor(model => Model.hasOptedOut, false) <span>No</span> <br />

                //here I would normally loop through the list but I'm changing only the first element for testing purposes
                @Html.RadioButtonFor(model => m.ElementAt(0).ukft, true) <span style="margin-right:8px;">Yes</span>
                @Html.RadioButtonFor(model => m.ElementAt(0).ukft, false) <span>No</span> <br />
            </div>

            <div class="form-group">
                <input id="confirm" type="submit" value="Confirm" class="btn btn-success btn-lg"/>
            </div>
        }

到目前为止一切顺利。如您所见,我添加了两组单选按钮——一组用于OptOut 模型中的简单hasOptedOut 布尔属性,另一组用于List 中第一个元素的ukft 属性。

现在,当我在两组单选按钮中选择是 (true) 时,我应该会看到 hasOptedOut = trueCohortList 对象的第一个 ukft = true。所以我在POST之后得到了控制器中的模型:

[HttpPost]
public ActionResult OptedOut(Dlhe.Smart.Models.OptOut optout)
{                
    return View("some_view");
}

hasOptedOut 确实如此。但是,ukft 在列表中仍然为 false。所以我认为Lists 并不是那么简单,但是我该如何解决这个问题呢?

编辑:

按照建议,我尝试过这样做,但没有成功:

@using (Html.BeginForm("OptedOut", "Home"))
        {            var m = Model.list;
            for (int i=0; i<Model.list.Count(); i++) {

                <div id="radios" class="form-group" style="margin-top:25px;">

                    @Html.RadioButtonFor(model => m[i].ukft, true) <span style="margin-right:8px;">Yes</span>
                    @Html.RadioButtonFor(model => m[i].ukft, false) <span>No</span> <br />
                </div>                
            }

                <div class="form-group" style="margin-top:25px;">
                    <input id="confirm" type="submit" value="Confirm" class="btn btn-success btn-lg"/>
                </div>
        }

【问题讨论】:

  • 您需要使用for 循环(或自定义EditorTemplate for typeof Cohort) - 例如for(int i = 0; i &lt; Model.list.Count; i++) { @Html.RadioButtonFor(m=&gt; m[i].ukft, true) ....}
  • 我推荐阅读这篇文章。只需 10 分钟,您将立即成为模型绑定集合的专家 - haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
  • @StephenMuecke 我看不出你的建议对我写的有什么影响,但我还是试过了,不幸的是它仍然没有更新 ukft 属性
  • @heymega 我大约一个小时前才读到它——我正在寻找不同的解决方案
  • 它确实有所作为。检查您使用这两种方法生成的 html。为了绑定到集合,您的控件需要命名为name="list[0].ukft"name="list[1].ukft" 等。您当前生成重复的nameid(无效的html)属性并且没有与您的模型匹配的回帖。正在发生的一切是 DefaultModelBinder 正在创建一个 OptOut 的新实例,其中包含 4 个 Cohort 的新实例,所有这些实例都具有默认的 false

标签: c# asp.net-mvc model


【解决方案1】:

我认为最简单的方法是为您的类型创建一个 EditorTemplate。

创建 EditorTemplate:

1) 在 Views/Shared 文件夹中创建一个名为 Editor Templates 的新文件夹

2) 在该文件夹中创建一个新的、强类型的局部视图,并使用您的类型名称作为文件名。 E.G Cohort.cshtml 可能如下所示:

@model Models.Cohort

@Html.RadioButtonFor(model => model.ukft, true) <span style="margin-right:8px;">Yes</span>
@Html.RadioButtonFor(model => model.ukft, false) <span>No</span> <br />

3) 在您的主视图中使用 @Html.EditorFor(model => model.list),razor 将为列表中的每个群组呈现在步骤 2 中创建的部分视图。

【讨论】:

  • 感谢您的建议。你能告诉我 razor 将如何计算出在表单中呈现局部视图吗?
  • 我不是幕后发生的事情的专家,但是当调用 @Html.EditorFor() 时,它会在 EditorTemplates 文件夹中查找给定类型的编辑器。如果给 EditorFor 一个 List,那么它会为 T 寻找一个编辑器模板并遍历 List 中的每个项目,为每个成员呈现一个 EditorTemplate。
  • 感谢您,我将主页中的代码替换为以下内容:@using (Html.BeginForm("OptedOut", "Home")) { @Html.EditorFor(model => Model .list)
    } 但它似乎没有渲染局部视图。你确定我不需要做任何其他事情吗? (除了创建强类型分部视图)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-02
  • 2011-06-10
  • 2021-12-16
相关资源
最近更新 更多