在MVC中是否可以在另一个ViewModel中拥有一个ViewModel?

时间:2018-10-24 09:41:00

标签: c# asp.net-mvc asp.net-mvc-5 kendo-asp.net-mvc

我要求供应商可以有多个地址。因此,我创建了一个CommunicationDetailsViewModel,如下所示:

public class CommunicationDetailsViewModel
{
    public string OrganizationName { get; set; }
    public List<Country> Country { get; set; }

    public List<State> State { get; set; }

    public List<City> City { get; set; }

    [Display(Name = "Id")]
    public int CountryId { get; set; }

    [Display(Name = "Id")]
    public int StateId { get; set; }

    [Display(Name = "Id")]
    public int CityId { get; set; }

    [StringLength(32), Required(ErrorMessage ="Address is required")]
    public string Address { get; set; }

}

我还有另一个ViewModel,称为SuppllierInformationViewModel,如下所示:

public class SupplierInformationViewModel
{
    [StringLength(50, ErrorMessage = "Organization name cannot be greater than 50 characters"), Required(ErrorMessage ="Organization name is required")]
    public string OrganizationName { get; set; }

    public List<CommunicationDetailsViewModel> CommunicationDetailsViewModel { get; set; }
}

我创建了这个ViewModel是因为供应商可以在其中输入多个地址。因此创建了CommunicationDetailsViewModel的集合。而且,供应商实体将拥有其他信息,例如银行信息,税收信息等。因此,我想到为每个实体创建一个ViewModel,并为每个其他实体SupplierInformationViewModel创建一个ViewModels 1}}。我们可以创建ViewModel中的ViewModels吗?

在视图中,我必须绑定这些多个地址。以下是我的看法:

@model WebAPI.ViewModels.SupplierInformationViewModel
@{
    ViewBag.Title = "Supplier Information";
}

<h4>Supplier Details</h4>

@using (Html.BeginForm("Save", "SupplierInformation", FormMethod.Post))
{
    <div class="demo-section k-content">
        <div class="form-group">
            @Html.Label("Organization name")
            @Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("OrganizationName").HtmlAttributes(new { @class = "k-textbox required", placeholder = "Organization Name" })
        </div>

        @for (int i = 0; i < Model.CommunicationDetailsViewModel.Count; i++)
        {
            <div class="form-group">
                @Html.Label("Country")
                @(Html.Kendo().DropDownList().Name("CountryId").DataTextField("CountryName").DataValueField("Id").BindTo(Model.CommunicationDetailsViewModel[i].Country))
            </div>
            <div class="form-group">
                @Html.Label("State")
                @(Html.Kendo().DropDownList().Name("StateId").DataTextField("StateName").DataValueField("Id").BindTo(Model.CommunicationDetailsViewModel[i].State))
            </div>
            <div class="form-group">
                @Html.Label("City")
                @(Html.Kendo().DropDownList().Name("CityId").DataTextField("CityName").DataValueField("Id").BindTo(Model.CommunicationDetailsViewModel[i].City))
            </div>
            <div class="form-group">
                @Html.Label("Address")
                @Html.Kendo().TextBoxFor(model => model.CommunicationDetailsViewModel[i].Address).Name("Address").HtmlAttributes(new { @class = "k-textbox required", placeholder = "Address", @maxlength = "32" })
            </div>
            <div class="form-group">
                @Html.Label("Building name")
                @Html.Kendo().TextBoxFor(model => Model.CommunicationDetailsViewModel[i].BuildingName).Name("BuildingName").HtmlAttributes(new { @class = "k-textbox required", placeholder = "Address", @maxlength = "32" })
            </div>
        }
    </div>
    @Html.Kendo().Button().Name("btnSave").Content("Save").HtmlAttributes(new { type = "submit", @class = "k-button k-primary" })
}    

现在,当我发布回该动作时,确实在OrganizationName中得到了SupplierInformationViewmodel,但是CommunicationDetailsViewModel为空。
这是为什么?它与命名约定有关吗?如果可以,该如何处理?
任何帮助表示赞赏。

我的动作方法

[HttpPost]
public ActionResult Save(SupplierInformationViewModel supplierInformationViewModel)
{
    return View();
}

2 个答案:

答案 0 :(得分:2)

您需要使用索引和强类型data have; input Freq Class Subclass $; datalines; 20 1 1a 20 1 1b 2 1 1c 2 1 1d 2 1 1e 1 1 1f 22 2 2a 6 2 2b 2 2 2c 1 2 2d 31 3 3a 17 3 3b 7 3 3c 3 3 3d 3 3 3e ; run; data want; set have; by class; length subclass_groups $20 subclass_temp $20; retain subclass_temp; if first.class then call missing(freq_temp,subclass_temp); if freq>9 then do; subclass_groups = subclass; output; end; else do; freq_temp + freq; call catx(',',subclass_temp,subclass); end; if last.class then do; freq = freq_temp; subclass_groups = subclass_temp; output; end; drop subclass subclass_temp freq_temp; run; ,以便生成正确的名称属性并指向循环中的项目:

DropDownListFor()

赞:

Model.CommunicationDetailsViewModel[i].CountryId

答案 1 :(得分:1)

您应使用强类型的DropDownListFor()来绑定嵌套的viewmodel,如下所示:

@(Html.Kendo().DropDownListFor(model => model.CommunicationDetailsViewModel[i].CountryId)
              .DataTextField("CountryName")
              .DataValueField("Id")
              .DataSource(ds => ds.Read(read => 
                  read.Action("GetCountry", "ControllerName")
               ))
 )

使用DropDownListFor()时,不需要Name("CountryId")

您还可以尝试添加无参数构造函数,该构造函数分配List<CommunicationDetailsViewModel>的新实例:

public class SupplierInformationViewModel
{
    public SupplierInformationViewModel()
    {
        this.CommunicationDetailsViewModel = new List<CommunicationDetailsViewModel>();
    }

    [StringLength(50, ErrorMessage = "Organization name cannot be greater than 50 characters"), Required(ErrorMessage ="Organization name is required")]
    public string OrganizationName { get; set; }

    public List<CommunicationDetailsViewModel> CommunicationDetailsViewModel { get; set; }
}