我有如下财产:
[DisplayName("Children")]
public List<long> ChildrenIds
{
get { return SelectedGroup.Children.Select(x => x.Id).ToList(); }
set
{
foreach (long groupId in value)
{
if (groupId != 0 && !SelectedGroup.Children.Select(x => x.Id).Contains(groupId))
{
var group = FactoryTools.Factory.Get<GroupLookup>(groupId);
if (group != null) SelectedGroup.AddChild(group);
}
}
var childrenLooper = SelectedGroup.Children.ToList();
foreach (var group in childrenLooper)
{
if (group.Id != 0 && !value.Contains(group.Id))
{
SelectedGroup.Children.Remove(group);
}
}
}
}
当我在标准Razor Listbox
中选择了至少一个孩子时,这很有效:
<div class="oneThird">
@Html.LabelFor(x => x.ChildrenIds)
@Html.ListBoxFor(x => x.ChildrenIds, ListHelper.GetGroupsMinusSelf(Model.SelectedGroup))
@Html.ValidationMessageFor(x => x.ChildrenIds)
</div>
但是,当我取消选择上面ListBox
中的所有项目时,此属性的setter永远不会被调用,因此这些项目永远不会被删除...什么是确保所有项目的最佳方法这些物品被删除了吗?
答案 0 :(得分:2)
如果没有选择任何项目,则没有从浏览器发布的数据,并且ASP.NET MVC模型绑定没有值设置。
换句话说,模型活页夹说:“我没有设置的价值,所以我打电话给设定者是没有意义的”,而你期望它说:“我没有价值设置,但无论如何我都会用一个空列表给Serj的setter打电话“。
但真正的问题在于,您正在推动模型绑定超出其设计目标。模型绑定只是将HTTP请求中数据的字符串表示形式转换为强类型数据。因此,您绑定到的模型应该表示HTML表单或类似简单的东西(是的,我知道Microsoft吹嘘您可以开箱即用模型绑定到复杂对象,但这只适用于最简单的情况,TBH )。一旦数据被强类型化,请在您的操作方法(或业务对象,服务,帮助程序或其他)中进行数据处理。
我建议你
1)像MyForm类那样引入类似的东西:
public class MyForm
{
public IEnumerable<int> ChildrenIds { get;set; }
}
2)引入一个类似的视图模型:
public class MyViewModel
{
public MyViewModel(Data somedata)
{
/* populate Options */
}
public IEnumerable<SelectListItem> Options { get; set; }
public MyForm Form { get; set; }
}
3)在您的视图中使用此模型:
@Html.ListBoxFor(m => m.Form.ChildrenIds, Model.Options)
4)最后,对于你的动作方法,你建模绑定到MyForm:
public ActionResult MyMethod(MyForm form)
{
/* inspect POSTed form.ChildrenIds, add/remove from domain model etc. as you see fit */
}
这将使您更清楚地将HTTP问题与业务问题分开。