将MVC视图绑定到IEnumerable <keyvaluepair <string,bool =“”>&gt;问题</keyvaluepair <字符串>

时间:2014-05-02 19:04:22

标签: asp.net asp.net-mvc razor model-binding

我有一个观点:

  @{
    var i = 0;
  }
  @foreach (var field in Model.ConsentQuestions)
    {
      <div class="form-group">
        <div class="control-label col-md-8">
          @Html.Label(string.Format("ConsentQuestions[{0}].Key", i), field.Key)
          @Html.Hidden(string.Format("ConsentQuestions[{0}].Key", i), field.Key)
        </div>
        <p class="col-md-2">
          @Html.RadioButton(string.Format("ConsentQuestions[{0}].Value", i), true, htmlAttributes: new { id = string.Format("question{0}-true", i) })
          <label for="question@(i)-true">Yes</label>
          @Html.RadioButton(string.Format("ConsentQuestions[{0}].Value", i), false, htmlAttributes: new { id = string.Format("question{0}-false", i) })
          <label for="question@(i)-false">No</label>
        </p>
      </div>
      i++;
    }

Model.ConsentQuestionsIEnumerable<KeyValuePair<string, bool>>(原因是问题是用户可定义的)。无论出于何种原因,活页夹都无法弄清楚这一点。通常这种索引对集合很好(我正在做与其他IEnumerables类似的东西,没有问题)。奇怪的是,如果我断开我的验证方法,它会看到ConsentQuestions中有正确数量的项目,除了每个KVP都是{&#34;&#34;,false}。

我想知道如何纠正问题并获取表单中的值进行绑定。

编辑:我确实有一个看似有效的解决方案,使用继承自DefaultModelBinder的类,然后覆盖GetPropertyValue以正确看controllerContext.HttpContext.Request.Form ..虽然这很好,但我仍然想知道为什么在这种情况下它不起作用。

2 个答案:

答案 0 :(得分:2)

正如我的评论中提到的(除了拼写错误),你需要使用List,而不是IEnumerable(因为它不能在运行时由绑定器索引)并在索引属性上使用For帮助器

我的TestModel看起来像:

public class TestModel
{
    public List<KeyValuePair<string,bool>> ConsentQuestions { get; set; }
    public TestModel()
    {
        var consentQuestions = new List<KeyValuePair<string,bool>>();
        for (int i = 1; i <= 10; i++)
        {
            consentQuestions.Add(new KeyValuePair<string,bool>("Question " + i.ToString(), i % 2 == 0));
        }
        this.ConsentQuestions = consentQuestions;
    }
}

然后我在索引元素属性上应用了...For版本的帮助程序:

查看:

<div class="control-label col-md-8">
    @Html.DisplayFor(m=>m.ConsentQuestions[i].Key)
</div>
<p class="col-md-2">
    @Html.RadioButtonFor(m=>m.ConsentQuestions[i].Value, true, htmlAttributes: new { id = string.Format("question{0}-true", i) })
    <label for="question@(i)-true">Yes</label>
    @Html.RadioButtonFor(m => m.ConsentQuestions[i].Value, false, htmlAttributes: new { id = string.Format("question{0}-false", i) })
    <label for="question@(i)-false">No</label>
</p>

注意:我将HiddenFor更改为DisplayFor以查看问题(随时调整)。

哪个有效:

enter image description here

跟进:

我一直在检查生成的输出,的区别在于,使用第一种绑定方式无法匹配现有值(第二种方式有效)。这适用于使用实体类或KeyValuePair(没有区别)。看起来RadioButton绑定器已损坏,但RadionButtonFor不是:

@Html.RadioButton("ConsentQuestions[" + i.ToString() + "].Value", true, htmlAttributes: new { id = string.Format("question{0}-true", i) })
@Html.RadioButtonFor(m => m.ConsentQuestions[i].Value, false, htmlAttributes: new { id = string.Format("question{0}-false", i) })

半工作结果!:

enter image description here

这显然有点奇怪,因为它应该工作相同,但解决方案仍然只是使用帮助器的For版本。 强类型代码总是比字符串更好。

答案 1 :(得分:1)

只需更改模型即可使用Dictionary(字面意思是KeyValuePairs列表)。您甚至不需要更改视图。

这样的事情:

public ActionResult AnswerQuestions(IEnumerable<KeyValuePair<string, bool>> ConsentQuestions)
{
    // Do stuff
}

将改为:

public ActionResult AnswerQuestions(Dictionary<string, bool> ConsentQuestions)
{
    // Do stuff
}

主要区别在于,除IEnumerable所拥有的属性外,还有.Comparer.ContainsKey().ContainsValue().Count,{{ 1}},.Keys.TryGetValue()

以下是why binding KeyValuePairs doesn't work的完整答案。