【问题标题】:Is it possible to have one ViewModel in another ViewModel in MVC?是否可以在 MVC 中的另一个 ViewModel 中有一个 ViewModel?
【发布时间】:2018-10-24 09:41:00
【问题描述】:

我有一个要求,供应商可以有多个地址。所以我创建了一个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。我们可以创建ViewModelViewModels 吗?

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

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

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

我的行动方法

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

【问题讨论】:

  • 您正在创建与您的模型无关的name 属性。请参阅Post an HTML Table to ADO.NET DataTable 以了解关系(例如它将是CommunicationDetailsViewModel[0].CountryId
  • 使用强类型Html.Kendo().DropDownListFor(m =&gt; m.CommunicationDetailsViewModel[i].CountryId, ...`以便生成正确的名称属性

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


【解决方案1】:

您需要使用索引和强类型DropDownListFor(),以便生成正确的名称属性并指向循环中的项目:

Model.CommunicationDetailsViewModel[i].CountryId

像这样:

@Html.Kendo().DropDownListFor(model => model.CommunicationDetailsViewModel[i].CountryId)

【讨论】:

    【解决方案2】:

    您应该使用强类型DropDownListFor() 来绑定嵌套视图模型,如下所示:

    @(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&lt;CommunicationDetailsViewModel&gt; 的新实例的无参数构造函数:

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

    【讨论】:

    • 是的。有效。但是我的情况现在对我来说变得复杂了。我想动态生成控件并发布它们的值。我最好为此创建单独的问题。谢谢。
    猜你喜欢
    • 2022-10-22
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-23
    相关资源
    最近更新 更多