2015-08-12 3 views
1

Я создал контрольный контроллер и посмотрел на тестовое сложное связывание, но я не могу заставить его работать.Связывание модели со сложным типом

Вот мой ViewModel:

public class TestViewModel 
{ 
    public SubTest MainTest { get; set; } 

    public List<SubTest> SubTestList { get; set; } 
} 

public class SubTest 
{ 
    public string Name { get; set; } 
    public int Id { get; set; } 
} 

Вот мой Вид:

@model TestViewModel  

@{ 
    using (Html.BeginForm()) 
    { 
     <h2>Main</h2> 

     <p> 
      @Html.DisplayTextFor(m => m.MainTest.Id) 
      => 
      @Html.DisplayTextFor(m => m.MainTest.Name) 
     </p> 

     <h2>Subs</h2> 

     foreach (var sub in Model.SubTestList) 
     { 
      <p> 
       @Html.DisplayTextFor(m => sub.Id) 
       => 
       @Html.DisplayTextFor(m => sub.Name) 
      </p> 
     } 

     <button type="submit">Submit</button> 
    } 
} 

А вот мой контроллер:

public ActionResult Test() 
{ 
    TestViewModel tvm = new TestViewModel(); 
    tvm.MainTest = new SubTest() { Id = 0, Name = "Main Test" }; 

    tvm.SubTestList = new List<SubTest>() 
    { 
     new SubTest() { Id = 1, Name = "Sub Test 1" } , 
     new SubTest() { Id = 2, Name = "Sub Test 2" } , 
     new SubTest() { Id = 3, Name = "Sub Test 3" } , 
     new SubTest() { Id = 4, Name = "Sub Test 4" } , 
    }; 

    return View(tvm); 
} 

[HttpPost] 
public ActionResult Test(TestViewModel tvm) 
{ 
    return View(tvm); 
} 

Когда я загрузить страницу, все отображается правильно , но если я устанавливаю точку останова в методе POST, я вижу, что значения параметра равны нулю.

Что я делаю неправильно?

ответ

2

Во-первых, DisplayTextFor() не генерирует элементы управления форматом (вход, текстовое поле, выберите), поэтому для отправки формы обратно нет.

Во-вторых, если вы действительно хотели, чтобы изменить значения вашей модели (скажем, с помощью текстового поля), то вам нужно будет использовать for цикл (или пользовательские EditorTemplate для TYPEOF SubTest) а не foreach петли для свойства коллекции, например

for (int i = 0; i < Model.SubTestList.Count; i++) 
{ 
    @Html.TextBoxFor(m => m.SubTestList[i].Id) 
    @Html.TextBoxFor(m => m.SubTestList[i].Name) 
} 

Или используя EditorTemplate (имя шаблона должна соответствовать вашему типу модели

В /View/Shared/EditorTemplates/SubTest.cshtml

@model yourAssembly.SubTest 
@Html.TextBoxFor(m => m.Id) 
@Html.TextBoxFor(m => m.Name) 

и в главном окне

@model TestViewModel 
.... 
@Html.EditorFor(m => m.SubTestList) 

EditorFor() Метод принимает IEnumerable<T> и является достаточно умным, чтобы оказал HTML из шаблона для каждого элемента в коллекции.

+0

Это правильно, я внес изменения, и он работает, спасибо большое!. Можете ли вы объяснить мне, почему foreach не работает в этом случае? – Shimrod

+0

Цикл foreach будет генерировать повторяющиеся атрибуты 'name', которые не имеют отношения к вашим свойствам модели (например,' name = "sub.Id" ') и без индексаторов, необходимых для привязки к коллекции (он также генерирует дубликат' id 'атрибуты, которые являются недопустимыми html). Предложите вам проверить html ваш генератор в обоих случаях, чтобы увидеть разницу (он должен быть 'name =" SubTestList [0] .Id "', 'name =" SubTestList [1] .Id "и т. Д.). –