具有Completex IEnumerable的MVC 3 View模型

时间:2012-09-28 18:47:36

标签: asp.net-mvc-3 razor

我有一个复杂的类,它是viewmodel属性的一部分。我的viewmodel有一个wine类属性,wine类有一个名为CaseProductions的ICollection属性。 CaseProduction类也有几个属性。

在create GET事件中,NewWineViewModel被实例化,然后它运行GetCaseProductionDefaults并创建一个CaseProduction类列表,这些类具有一些默认值,但大部分都是空的。

现在,我最初使用razor做一个foreach语句,然后按照我想要的方式弹出我的表。但我已经看到,无法将这种类型的IEnumerable绑定回POST上的viewmodel。我试过用下面的,但没有骰子。

EditorFor(m => m.Wine.CaseProductions)

我真的在寻找有关处理这个问题的最佳方法的建议。每种葡萄酒都有一系列的caseproductions,我希望它能在视图模型中绑定回葡萄酒。他们是否可以通过某种方式在剃刀中编辑这些元素的ID以确保它们绑定?处理这个问题的最佳方法是什么?

视图模型:

    public class NewWineViewModel
    {

        public Wine Wine { get; set; }
        public VOAVIRequest VOAVIRequest { get; set; }
        public bool IsRequest { get; set; }

        public Dictionary<int, int> BottlesPerCase { get; set; }
        public SelectList VarTypes { get; set; }
        public SelectList Origins { get; set; }
        public SelectList Apps { get; set; }
        public SelectList Vintages { get; set; }
        public SelectList Importers { get; set; }
}

案例制作类:

public class CaseProduction
{
    public int CaseProductionID { get; set; }
    public int WineID { get; set; }
    public int CaseProductionSizeID { get; set; }
    public int CaseCount { get; set; }
    public int CountPerCase { get; set; }

    public virtual CaseProductionSize CaseProductionSize { get; set; }
    public virtual Wine Wine { get; set; }

}

获取默认案例制作:

public List<CaseProduction> GetCaseProductionDefaults(vfContext db)
{
    //creates blank list of all formats
    List<CaseProduction> cp = new List<CaseProduction>();
    foreach (CaseProductionSize size in db.CaseProductionSizes)
    {
        int defaultBottlesPerCase = 1;
        switch ((CaseProductionSizeEnum)size.CaseProductionSizeID)
        {
            case CaseProductionSizeEnum.s187ml:
                defaultBottlesPerCase= 24;
                break;
            case CaseProductionSizeEnum.s375ml:
                defaultBottlesPerCase = 12;
                break;
            case CaseProductionSizeEnum.s500ml:
                defaultBottlesPerCase = 12;
                break;
            case CaseProductionSizeEnum.s750ml:
                defaultBottlesPerCase = 12;
                break;
            default:
                defaultBottlesPerCase = 1;
                break;
        }

        cp.Add(new CaseProduction { CaseProductionSizeID = size.CaseProductionSizeID, CountPerCase = defaultBottlesPerCase, CaseProductionSize = size, WineID = this.Wine.WineID });
    }
    return cp;
}

我的案例制作表的剃刀代码:

  @foreach (vf2.Models.CaseProduction cp in Model.Wine.CaseProductions)
            {
                <tr>
                    <td>@cp.CaseProductionSize.Name
                    </td>
                    <td>@Html.Raw(@Html.TextBoxFor(m => m.Wine.CaseProductions.Where(c => c.CaseProductionSizeID == cp.CaseProductionSizeID).First().CaseCount, new { @class = "caseCount", id = "txt" + cp.CaseProductionSize.Name }).ToString().Replace("CaseCount","txt" + cp.CaseProductionSize.Name))
                    </td>
                    <td>
                        @Html.DropDownListFor(m => m.Wine.CaseProductions.Where(c => c.CaseProductionSizeID == cp.CaseProductionSizeID).First().CountPerCase, new SelectList(Model.BottlesPerCase, "Key", "Value", cp.CountPerCase), new { @class = "countPerCase", id = "ddl" + cp.CaseProductionSize.Name, name = "ddl" + cp.CaseProductionSize.Name})
                    </td>
                    <td class="totalBottleCalc">
                    </td>
                </tr>
 }

我的caseproduction集合的实例化:

 public ActionResult Create(int ID = 0, int VintUpID = 0)
        {
            NewWineViewModel nw = new NewWineViewModel();

            nw.Wine.CaseProductions = nw.GetCaseProductionDefaults(db);
            nw.BottlesPerCase = nw.GetBottlesPerCase(db);

2 个答案:

答案 0 :(得分:0)

您必须在父模型构造函数中实例化嵌套列表和复杂模型。默认模型绑定程序不会实例化子类。

如果你这样做,那么你可以使用EditorFor(m =&gt; m.Wine.CaseProductions),并且你不需要你正在使用的复杂视图代码。

如果要自定义CaseProduction的呈现方式,则可以在〜/ Shared / EditorTemplates中创建CaseProduction.cshtml文件,它将使用此定义呈现集合中的每个项目(它将自动迭代集合)为你)。

此外,您不应在视图中执行linq查询。您的问题是,您将数据实体直接传递给视图。这是糟糕的设计。您需要创建一个仅包含呈现视图所需信息的ViewModel。然后,在将数据分配给View模型之前过滤数据。

答案 1 :(得分:0)

我认为模型绑定器没有拾取CaseProduction个对象,因为它们看起来不像CaseProduction个对象。

您已重命名CaseCount,您的CaseProductionSize没有ID(也不是CaseProduction,而且它缺少多个属性。在您的循环中,您必须包含所有属性,并保留名称与您的POCO名称一致。否则模型绑定器将不知道它们是什么。如果需要,您可以将所有属性放在隐藏字段中。