【问题标题】:Bind Dictionary with list in viewmodel to checkboxes将字典与视图模型中的列表绑定到复选框
【发布时间】:2017-05-06 15:19:06
【问题描述】:

您如何正确地将字典及其每个键的值绑定到复选框? 我可以在 HTTPGET 中显示它们,但将所选值再次绑定到 HTTPPOST 似乎不起作用。

视图模型

public class EditViewModel
{
    public Foo Foo { get; set; }
    public Dictionary<Bar, List<BarVersionEditVM>> Matrix { get; set; }
}

public class BarVersionEditVM
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Version { get; set; }
    public bool IsSupported { get; set; }
}

查看:

<form asp-action="Edit">
<div class="row">
 @foreach (var kvp in Model.Matrix.OrderByDescending(x => x.Key.Name))
 {
   <div class="col-md-2 col-lg-2">
     <fieldset>
         <legend>@kvp.Key.Name</legend>
        @foreach (var version in kvp.Value)
        {
          <div>
           <input type="checkbox" id="@version.ID" value="@version.IsSupported" name="@version.Name" @(version.IsSupported ? "checked=\"checked\"" : "") />
               <label>@version.Version:</label>
         </div>
        }
    </fieldset>
  </div>
  }
  </div>
<input type="hidden" asp-for="@Model.Foo.ID" />
<input type="submit" value="Save" class="btn btn-default" />
</form>

在视图中,我也尝试使用 foreach 和 Html 帮助程序进行重写,但没有成功:

@Html.CheckBoxFor(model => model.Matrix[kvpair.Key][i].IsSupported)

控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(EditViewModel vm) {
 // vm is there but Matrix  are null.
// and only the ID of Foo property is filled in.
}

有什么建议吗?

【问题讨论】:

  • DefaultModelBinder 不会绑定到值是复杂对象或集合的字典,除非其格式为 propertyName[indexer].Key="", propertyName[indexer].Value="" - 在您的情况下 - name=Matrix[0].Key=".."name="name=Matrix[0].Value[0].ID=".."、@987654328 @ 等,(并且没有帮助方法可以为您生成正确的名称属性)。创建一个代表您的视图的视图模型比使用Dictionary 要容易得多
  • 例如 EditViewModel 包含 List&lt;BarVM&gt;BarVM 包含 List&lt;BarVersionEditVM&gt; 然后使用 nested for` 循环(或自定义 EditorTemplates 类型)
  • 但如果您在视图中显示/编辑的只是这些,您的视图模型可以简单得多。
  • 好的,让我试试看。

标签: c# asp.net asp.net-core asp.net-core-mvc


【解决方案1】:

除非您的DictionaryKeyValue 都具有简单的值类型(例如公共Dictionary&lt;string, string&gt;),否则DefaultModelBinder 要求表单控件name 属性采用格式

<input .... name="Matrix[0].Key" value="..." />
<input .... name="Matrix[0].Value[0].ID" value="..." />
<input .... name="Matrix[0].Value[0].Name" value="..." />

没有 HtmlHelper 方法可以生成正确的 html 以允许绑定到您的 Dictionary

使用集合的IList&lt;T&gt; 属性创建简单的视图模型要简单得多。根据您显示的视图,这些模型将是

public class EditVM
{
    public int FooID { get; set; }
    public List<BarVM> Bars { get; set; }
}
public class BarVM
{
    public string Name { get; set; }
    public List<BarVersionVM> Versions { get; set; }
}
public class BarVersionVM
{
    public int ID { get; set; }
    public string Name { get; set; } // not clear where you use this property
    public string Version { get; set; }
    public bool IsSupported { get; set; }
}

然后您的视图将是

@model EditVM
....
@Html.HiddenFor(m => m.FooID)
@for(int i = 0; i < Model.Bars.Count; i++)
{
    <fieldset>
        <legend>@Model.Bars[i].Name</legend>
        @Html.HiddenFor(m => m.Bars[i].Name) // in case you need to return the view in the POST method
        @for(int j = 0; j < Model.Bars[i].Versions.Count; j++)
        {
            <div>
                @Html.HiddenFor(m => m.Bars[i].Versions[j].ID)
                @Html.CheckBoxFor(m => m.Bars[i].Versions[j].IsSupported)
                @Html.LabelFor((m => m.Bars[i].Versions[j].IsSupported, Model.Bars[i].Versions[j].Version)
            </div>
        }
    </fieldset>
}
<input type="submit" value="Save" />

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 1970-01-01
    • 2014-01-24
    • 2015-09-11
    • 2013-04-05
    • 1970-01-01
    相关资源
    最近更新 更多