2

コレクション アイテムのコレクションにデータをバインドするのに問題があります (問題を正しく表現するのにも問題があります)。疑似モデルの例を使用して、誰にとっても簡単にしましょう。

次のサンプルモデルがあるとしましょう:

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; }
}

...そしてビューモデルの例:

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

編集アクション/ビューの目的は、ユーザーが月、月に割り当てられた週を編集し、特定の月の週から日を追加および削除できるようにすることです。ビューが役立つ場合があります。

@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" : "") />
        }
    }
}

コントローラ アクション メソッド

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]
            */
        }
}

フォームを送信するときに、選択した日がその週にバインドされるようにするにはどうすればよいですか?

4

1 に答える 1

0

最も簡単な方法は、フォームが type のデータ構造を取り込むことを目標にすることです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++; }

次に、投稿先のコントローラー アクションに次の署名を付けることができます。

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

ビュー モデル (通常は GET アクション) と非ビュー モデル (プレーン モデルと呼ばれるもの) のモデルにのみ使用する必要があるビュー モデルを混同しないようにすることが役立ちます。POST アクションがビュー モデルにバインドしようとすることは避けてください。そうすれば、作業が大幅に簡素化されます。

于 2012-09-12T20:25:35.413 に答える