Как получить данные EditorFor с вложенными моделями представления - PullRequest
4 голосов
/ 27 августа 2010

Вот моя ситуация -

У меня есть две модели вложенных представлений:

  1. <%=Html.EditorFor(x => x.DisplayEntitiesWithRadioboxesViewModel)%><br />

Находясь внутри родительского элемента (StructureViewModel), я могу легко заполнить вложенные модели ViewModel и передать их в основное представление:

Внутри контроллера - Пример

var moveDepartment = new StructureViewModel();
moveDepartment.DisplayEntitiesWithRadioboxesViewModel = fullDepartmentList.Select(x => new DisplayEntityViewModel
            {
                Id = x.Id,
                Path = x.Path,
                PathLevel = x.PathLevel,
                Description = x.Description,
            });

return View(moveDepartment);

EditorTemplete - Пример

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Site.Areas.Administration.ViewModel.DisplayEntityViewModel>>" %>
<table class="aligncenter"><%
  if (Model != null)
  {
    foreach (var entity in Model)
    {%>
      <tr class="tRow">
        <td style="text-align:left; text-indent:<%=Html.Encode(entity.PathLevel)%>em">
          <%=Html.Encode(entity.Description)%>
          <%=Html.RadioButton("radiobutton",entity.Id)%>
        </td>              
      </tr><%    
    }
  }%>
</table>


namespace Site.Areas.Administration.ViewModel
{
    public class DisplayEntityViewModel
    {
        public int Id { get; set; }
        public string Path { get; set; }
        public string PathLevel { get; set; }
        public string Description { get; set; }   
    }
}

Однако, когда я пытаюсь извлечь эту информацию, вложенные ViewModels имеют значение null:

[HttpPost]
public ActionResult Move(StructureViewModel StructureViewModel)

При наведении курсора на StructureViewModel он содержит только данные, установленные в родительской ViewModel. Например: скрытое значение можно увидеть, но DisplayEntitiesWithRadioboxesViewModel = null.

Единственный способ узнать, как получить доступ к DisplayEntitiesWithRadioboxesViewModel, - это использовать FormCollection, выполнять итерации по FormCollection и извлекать необходимую информацию из вложенных моделей ViewModels.

Это, однако, кажется неправильным, поскольку я обнаружил, что мне нужно заново заполнить DisplayEntitiesWithRadioboxesViewModel значениями из FormCollection, если, например, произошла ошибка и пользователь должен отправлено обратно в тот же вид.

Я пытался искать в Интернете / книгах, но не могу найти решение.

Есть ли лучший способ?

Заранее спасибо за любую помощь.

А почему вы использовали EditorFor для простой выпадающий, который легко использовать с DropDownFor

Это было теперь изменено для использования DropDownFor.

в чем ключ DisplayEntitiesWithRadioboxesViewModel значение в FormCollection

{string[3]}
[0] = "DisplayEntitiesWithRadioboxesViewModel.radiobutton"
[1] = "Action"
[2] = "OldParentId"

Клэр: -)

Ответы [ 3 ]

3 голосов
/ 31 августа 2010

Ваша проблема довольно распространена и ее легко исправить, когда вы поймете, как она работает.

Прямо сейчас у вас есть модель представления, у которой есть свойство IEnumerable<T> (не имеет значения, что является универсальным параметром). Вы пытаетесь передать элементы в представление и заполнить IEnumerable<T> теми же значениями, когда ответ возвращается, используя значения, изначально записанные на страницу и дополненные выбранным элементом (по крайней мере, из кода, который вы опубликовали в любом случае, это поможет вам точно указать свое намерение в этом вопросе). Проблема, с которой вы столкнулись, заключается в том, что вы должны отправить эти значения на страницу так, чтобы они могли быть возвращены.

Позвольте мне сейчас сказать, что вы, вероятно, должны НЕ использовать эту технику. Как правило, гораздо лучше вернуть только выбор и снова сгенерировать список, если вам нужно на стороне сервера.

Судя по всему, вы хотите вернуть весь список, а затем найти выбранный элемент, который является точкой раскрывающегося списка или группы переключателей. Чтобы вернуть выбор обратно, параметр для вашего действия контроллера должен иметь свойства, которые соответствуют переменным, переданным обратно. В этом случае похоже, что вы используете имя параметра radiobutton для всех ваших переключателей (то же самое Держите истину для выпадающего списка, только он использует имя списка). Какой бы из них ни был выбран, значение, связанное с ним, возвращается с этим именем. Среда MVC позаботится о том, чтобы попытаться найти соответствующее действие, в котором указано как можно больше имен.

То, что вам нужно использовать для параметра действия, - это новый класс, который содержит свойство для всех имен полей, отправляемых обратно на сервер! Или, конечно, вы можете просто добавить свойство radiobutton к своему StructureViewModel. Фактически, вы заметите, что он уже пытается установить это значение, только в настоящее время его нет в вашей модели представления. Однако вы по-прежнему не получите исходный список, но это нормально, потому что даже если вы получили исходный список обратно, у вас нет идентификатора, чтобы сообщить, какой элемент был выбран!

Надеюсь, это поможет вам понять, что происходит, если у вас есть еще вопросы, пожалуйста, задавайте.

3 голосов
/ 03 сентября 2010

Я бы порекомендовал вам везде использовать строго типизированные помощники, чтобы вам не пришлось беспокоиться о присвоении имен элементам управления. Вот как это сделать:

Модель:

public class DisplayEntityViewModel
{
    public int Id { get; set; }
    public string Path { get; set; }
    public string PathLevel { get; set; }
    public string Description { get; set; }
}

public class StructureViewModel
{
    public IEnumerable<DisplayEntityViewModel> DisplayEntitiesWithRadioboxesViewModel  { get; set; }
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var moveDepartment = new StructureViewModel();
        moveDepartment.DisplayEntitiesWithRadioboxesViewModel = new[] 
        {
            new DisplayEntityViewModel
            {
                Id = 1,
                Path = "some path 1",
                PathLevel = "some path level 1",
                Description = "some description 1"
            },
            new DisplayEntityViewModel
            {
                Id = 2,
                Path = "some path 2",
                PathLevel = "some path level 2",
                Description = "some description 2"
            },
        };
        return View(moveDepartment);
    }

    [HttpPost]
    public ActionResult Index(StructureViewModel StructureViewModel)
    {
        return View(StructureViewModel);
    }
}

Главный вид (~/Views/Home/Index.aspx):

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SomeNs.Models.StructureViewModel>" %>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<% using (Html.BeginForm()) { %>
    <table class="aligncenter">
        <%= Html.EditorFor(x => x.DisplayEntitiesWithRadioboxesViewModel) %>
    </table>
    <input type="submit" value="Go" />
<% } %>

</asp:Content>

Шаблон редактора (~/Views/Home/EditorTemplates/DisplayEntityViewModel.ascx)

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ToDD.Models.DisplayEntityViewModel>" %>

<tr class="tRow">
    <td style="text-align:left; text-indent:<%=Html.Encode(Model.PathLevel)%>em">
        <%= Html.Encode(Model.Description) %>

        <!-- Remember that you need to place input fields for each property
             that you expect to get back in the submit action
        -->
        <%= Html.HiddenFor(x => x.Description) %>
        <%= Html.TextBoxFor(x => x.Path) %>
    </td>              
</tr>

Теперь отправьте форму, и все должно быть правильно связано. Важно отметить, что шаблон редактора строго типизирован на DisplayEntityViewModel, а не IEnumerable<DisplayEntityViewModel>, как в вашем случае. Когда на главном экране вы пишете:

<%= Html.EditorFor(x => x.DisplayEntitiesWithRadioboxesViewModel) %>

фреймворк автоматически обнаруживает, что свойство является коллекцией, и вызывает шаблон редактора для каждого элемента этой коллекции, поэтому вам больше не нужно перебирать элементы, что делает ваш код более элегантным.


UPDATE:

Использование выпадающих списков также очень просто: оформить заказ этот ответ .

0 голосов
/ 31 августа 2010

Можете ли вы сказать мне, как точно выглядит EditorFor?И почему вы использовали EditorFor для простого раскрывающегося списка, который легко использовать с DropDownFor.

что такое Key значения DisplayEntitiesWithRadioboxesViewModel в FormCollection

Если я правильно понимаю, у вас есть представление с некоторой родительской информацией и одновременнонесколько итераций этих 2 полей в одном представлении.Это правильно?

Тогда я знаю, как это исправить.

...