Возможно ли иметь одну ViewModel в другой ViewModel в MVC? - PullRequest
0 голосов
/ 24 октября 2018

У меня есть требование, когда поставщик может иметь несколько адресов.Итак, я создал 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; }
}

Iсоздал это ViewModel, потому что у поставщика может быть несколько адресов. Так что создана коллекция CommunicationDetailsViewModel.И в дальнейшем, у Поставщика будет другая информация, такая как Банковская информация, Налоговая информация и т. Д. Поэтому я подумал о создании ViewModel для каждого из них и одного SupplierInformationViewModel для хранения всех этих ViewModels.Можем ли мы создать 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 голосов
/ 24 октября 2018

Вы должны использовать строго типизированный 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<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; }
}
0 голосов
/ 24 октября 2018

Вам нужно использовать индексирование и строго типизированный DropDownListFor(), чтобы генерировать правильные атрибуты имени и указывать на элементы в вашем цикле:

Model.CommunicationDetailsViewModel[i].CountryId

Вот так:

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