我知道有许多自定义实现的CheckBoxListFor帮助方法来填充MVC框架中缺少的功能。但我还没准备好使用它们。我有兴趣使用MVC 4或5提供的功能创建一个复选框列表。所以,我创建了这个模型类:
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace MvcApplication1.Models { public class FruitViewModel { public int[] SelectedFruits { get; set; } public IList Fruits { get { return new List{ new Fruit{Id=1, Name="Apple", Selected = false}, new Fruit{Id=2, Name="Banana", Selected = false}, new Fruit{Id=3, Name="Cherry", Selected = false}, new Fruit{Id=4, Name="Durian", Selected = false}, new Fruit{Id=5, Name="Elderweiss Grape", Selected = false} }; } } } public class Fruit { public int Id { get; set; } public string Name { get; set; } public bool Selected { get; set; } } }
这是控制器类:
using MvcApplication1.Models; using System.Web.Mvc; namespace MvcApplication1.Controllers { public class FruitController : Controller { public ActionResult Index() { FruitViewModel model = new FruitViewModel(); return View(model); } [HttpPost] public ActionResult Index(FruitViewModel model) { if (ModelState.IsValid) { } return View(model); } } }
这是剃须刀的观点:
@model MvcApplication1.Models.FruitViewModel
@{
ViewBag.Title = "Index";
}
<h2>Select your favorite fruits</h2>
@using (Html.BeginForm("Index", "Fruit"))
{
<p>Using Html helper method:</p>
for (int i = 0; i < Model.Fruits.Count; i++)
{
@Html.CheckBoxFor(m => m.Fruits[i].Selected) @Model.Fruits[i].Name<br />
}
<p>Plain html without html helper</p>
for (int i = 0; i < Model.Fruits.Count; i++)
{
<input type="checkbox" name="SelectedFruits" value="@Model.Fruits[i].Id" checked="@Model.Fruits[i].Selected" />
@Model.Fruits[i].Name<br />
}
<input type="submit" name="submit" value="Submit" />
}
以下是我遇到的问题:
纯HTML版本将使用我选择的水果填充SelectedFruits集合。从屏幕截图中可以看到正确的ID。但是,当回发后页面刷新时,所选复选框状态将重置为不检查。
使用Html帮助程序CheckBoxFor的版本不会使用我选择的水果填充我的SelectedFruits集合&#39; ID,虽然它似乎在回发完成后将复选框状态保持为已选中状态。
所以,无论哪种情况,都存在很大的问题。
设置复选框列表的正确方法是什么,以便我可以正确填充SelectedFruits集合,并在表单发布完成后保持复选框的状态(当我在页面上添加其他内容并且验证失败时很重要) 。
答案 0 :(得分:4)
我建议你可以使用以下解决方案,
控制器更改[仅限获取方法设置要显示的视图数据]
public ActionResult Index()
{
FruitViewModel model = new FruitViewModel();
model.Fruits = new List<Fruit>
{
new Fruit{Id=1, Name="Apple", Selected = false},
new Fruit{Id=2, Name="Banana", Selected = false},
new Fruit{Id=3, Name="Cherry", Selected = false},
new Fruit{Id=4, Name="Durian", Selected = false},
new Fruit{Id=5, Name="Elderweiss Grape", Selected = false}
};
return View(model);
}
FruitModel更改,我们将根据用户选择的成果动态填充属性。
public int[] SelectedFruits
{
get
{
return Fruits != null && Fruits.Count > 0
? Fruits.Where(f => f.Selected == true).Select(f => f.Id).ToArray()
: new int[0];
}
set { }
}
查看页面更改[Index.cshtml]
for (int i = 0; i < Model.Fruits.Count; i++)
{
@Html.CheckBoxFor(m => m.Fruits[i].Selected) @Model.Fruits[i].Name<br />
@Html.HiddenFor(m => m.Fruits[i].Id)
@Html.HiddenFor(m => m.Fruits[i].Name)
}
我在您的代码中发现的问题是您使用了复选框名称属性作为&#34; SelectedFruits&#34;在html中为您手动呈现的复选框。由Html Helper呈现的标记的名称为&#34; Fruits [0] .Selected&#34;等...
因此,所选择的水果没有正确模型化。
请核实当前生成的标记,并在有任何疑问时发布您的反馈。
答案 1 :(得分:1)
您的问题是,viewmodel中的Fruits属性始终会创建一个新数组,其中每个水果的Selected
属性始终为false。您可以通过在viewmodel中初始化一次数组来修复它:
public IList<Fruit> Fruits
{
get
{
if (_fruits == null)
_fruits = new List<Fruit> {
new Fruit{Id=1, Name="Apple", Selected = false},
new Fruit{Id=2, Name="Banana", Selected = false},
new Fruit{Id=3, Name="Cherry", Selected = false},
new Fruit{Id=4, Name="Durian", Selected = false},
new Fruit{Id=5, Name="Elderweiss Grape", Selected = false}
}
return _fruits;
};
}
private List<Fruit> _fruits;
修复后,您必须更新控制器以修复Selected
属性:
[HttpPost]
public ActionResult Index(FruitViewModel model)
{
foreach (int fruitId in model.SelectedFruits)
model.Fruits[fruitId].Selected = true;
return View(model);
}