How to get EditorFor data with nested view modes

Here is my situation -

I have two nested view models:

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

Which sits inside its parent (StructureViewModel), I can easily populate the nested ViewModels and pass it to the main view:

Inside the controller - an example

 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 - Example

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

However, when I try to undo this information, nested ViewModels are null:

 [HttpPost] public ActionResult Move(StructureViewModel StructureViewModel) 

When I am above StructureViewModel , it contains only the dataset in the parent ViewModel. For example: a hidden value can be seen, but DisplayEntitiesWithRadioboxesViewModel = null.

The only way to find out how to access DisplayEntitiesWithRadioboxesViewModel is to use a FormCollection and iterate over the FormCollection and pull the information I need from the nested ViewModels.

However, this does not look like what I found in I, then I need to FormCollection DisplayEntitiesWithRadioboxesViewModel values ​​from the FormCollection if, for example, an error occurs and the user should be sent back to the same view.

I tried searching on the Internet / books, but cannot find a solution.

Is there a better way?

Thanks in advance for your help.

And why did you use the editor for a simple dropdown menu that is easy to use with DropDownFor

Now it has been modified to use DropDownFor.

what is the key DisplayEntitiesWithRadioboxesViewModel value in FormCollection

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

Clare :-)

+4
source share
3 answers

Your problem is quite common and somewhat easily fixed when you understand how it works.

Now you have a view model that has the IEnumerable<T> property (it doesn't matter what the generic parameter is). You are trying to pass elements to the view and fill IEnumerable<T> the same values ​​when the answer is returned, using the values ​​originally written to this page and supplemented by the selected element (at least from the code that you posted anyway, this will help indicate your exact intention in the question). The problem is that you have to post these values ​​to the page so that they can be returned.

Let me say now that you probably should NOT use this technique. As a rule, it is much better to go back to the selection and create the list again if you need the server side.

From the looks of things, you want to return the entire list, and then look for the selected item, which after all the points of the drop-down list or a group of radio buttons. To get the selection back, the parameter for the action of your controller must have properties that correspond to the variables passed back. In this case, it looks like you are using the radiobutton parameter radiobutton for all of your radio buttons (keep the same for the dropdown list, only it uses the list name). Which one is selected, the value associated with it is returned with that name. The MVC framework takes care to find a suitable action that identifies as many names as possible.

What you need to use for the action parameter is a new class that contains a property for all field names returned to the server! Or, of course, you can simply add the radiobutton property to your StructureViewModel too. In fact, you will notice that it is trying to set this value already, only it does not exist in your view model. However, you still won’t get the original list, but everything is fine, because even if you received the original list, you don’t have an identifier so that you know which item was selected!

Hope this helps you understand what happens, if you have additional questions, please ask.

+3
source

I would recommend that you use strongly typed helpers everywhere so you don't have to worry about naming your controls. Here's how to proceed:

Models:

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

Controller:

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

The main view ( ~/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> 

Editor Template ( ~/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> 

Now submit the form and everything should be connected correctly. It is important to note that the editor template is strongly typed on the DisplayEntityViewModel , not the IEnumerable<DisplayEntityViewModel> , as in your case. When you write in your main view:

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

the structure automatically detects that the property is a collection, and an editor template is called for each element of this collection, so you no longer need to iterate over the elements that make your code more elegant.


UPDATE:

Using dropdowns is also very simple: checkout this answer .

+3
source

Can you tell me what EditorFor looks EditorFor ? And why did you use EditorFor for a simple drop down menu that is easy to use with DropDownFor .

What are Key values ​​of DisplayEntitiesWithRadioboxesViewModel in FormCollection

If I understand correctly, you have a view with some information about the parents and at the same time several iterations of these two fields in the same view. Is it correct?

Then I know how to fix it.

0
source

All Articles