Skip to main content
 首页 » 编程设计

c#之MVC 添加和删除子集合中的项目

2024年01月01日40kerrycode

我在将数据绑定(bind)到集合项的集合时遇到了问题(我也无法正确表述我的问题)。让我们通过使用 psudo 模型的示例来简化每个人的操作。

假设我有以下示例模型:

public class Month() 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Week> Weeks { get; set; } 
} 
 
public class Week() 
{ 
    public int ID { get; set; } 
    public int MonthID { get; set; } 
    public String Name { get; set; } 
    public virtual ICollection<Day> Days { get; set; } 
} 
 
public class Day() 
{ 
    public int ID { get; set; } 
    public String Name { get; set; } 
} 

...和一个示例 View 模型:

public class EditMonthViewModel() 
{ 
    public Month Month { get; set; } 
    public List<Week> Weeks { get; set; } 
    public List<Day> AllDays { get; set; } 
} 

编辑操作/ View 的目的是让用户能够编辑月份、分配给月份的周数,以及从某个月的周数中添加和删除天数。 View 可能会有所帮助。

@model myProject.ViewModels.EditMonthViewModel 
 
//... 
@using (Html.BeginForm()) 
{ 
    //Edit Month Stuff... 
 
    @for(int i = 0; i < Model.Weeks.Count(); i++) 
    { 
        <h2>@Model.Weeks[i].Name</h2> 
        @Html.EditorFor(model => Model.Weeks[i].Name) 
 
        //loop through all possible days 
        //Select only days that are assigned to Week[i]  
        @for(int d = 0; d < Model.AllDays.Count(); d ++) 
        { 
            //This is the focus of this question.   
            //How do you bind the data here? 
            <input type="checkbox" 
                   name="I have no idea"  
                   @Html.Raw(Model.Weeks[i].Days.Contains(Model.AllDays[d]) ? "checked" : "") /> 
        } 
    } 
} 

Controller 操作方法

public ActionResult Edit(int id) 
{ 
    var viewModel = new EditMonthViewModel(); 
    viewModel.Month = db.Months.Find(id); 
    viewModel.Weeks = db.Weeks.Where(w => w.MonthID == id).ToList(); 
 
    viewModel.AllDays = db.Days.ToList(); 
} 
 
[HttpPost] 
public ActionResult Edit(EditMonthViewModel viewModel) 
{ 
    var monthToUpdate = db.Months.Find(viewModel.Month.ID); 
    //... 
 
    if(viewModel.Weeks != null) 
    { 
        foreach (var week in viewModel.Weeks) 
        { 
            var weekToUpdate = monthToUpdate.Weeks.Single(w => w.ID == week.ID); 
            //... 
 
            /*So, I have a collection of weeks that I can grab,  
              but how do I know what was selected? My viewModel only has a  
              list of AllDays, not the days selected for Week[i] 
            */ 
        } 
} 

我如何确保在提交表单时所选日期将绑定(bind)到该周?

请您参考如下方法:

看起来最简单的事情就是让表单的目标是填充 IEnumerable<DayModel> 类型的数据结构。 , 其中DayModel定义为:

public class DayModel 
{ 
    public int WeekId { get; set; } 
    public int DayId { get; set; } 
    public bool IsIncluded { get; set; } 
} 

在大多数情况下,您可以保持 Razor 代码不变,但是当涉及到呈现复选框时,您可以执行如下操作:

@{ 
    var modelIdx = 0; 
} 
 
// ... 
 
<input type="hidden" name="days[@modelIdx].WeekId" value="@Model.Weeks[i].Id" /> 
<input type="hidden" name="days[@modelIdx].DayId" value="@Model.AllDays[d].Id" /> 
<input type="checkbox" name="days[@modelIdx].IsIncluded" value="@(Model.Weeks[i].Days.Contains(Model.AllDays[d]) ? "checked" : "")" /> 
@{ modelIdx++; } 

然后,您发布到的 Controller 操作可能具有此签名:

[HttpPost] 
public ActionResult Edit(IEnumerable<DayModel> days) 
{ 
    //... 
} 

对我有帮助的是永远不要混淆 View 模型,它应该只用于 View 模型(通常是 GET 操作)和非 View 模型(我们称之为普通模型)。避免让您的 POST 操作尝试绑定(bind)到 View 模型,这将大大简化您的生活。