2010-08-27 4 views
4

Voici ma situation -Comment obtenir des données de EditorFor avec viewmodels imbriquées

J'ai deux modèles de vue imbriqués:

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

qui siègent au sein de leur parent (StructureViewModel), Je peux peupler les ViewModels imbriqués facilement et le transmettre à la vue principale:

Dans le contrôle r - Exemple

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

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

Cependant lorsque je tente de retirer ces informations les ViewModels imbriquées sont nulles:

[HttpPost] 
public ActionResult Move(StructureViewModel StructureViewModel) 

Quand je passe la souris sur StructureViewModel il ne contient que des données sur le ViewModel parent. Par exemple: une valeur masquée peut être vue mais DisplayEntitiesWithRadioboxesViewModel = null. La seule façon dont je sais comment accéder au DisplayEntitiesWithRadioboxesViewModel est d'utiliser FormCollection et de parcourir le FormCollection pour sortir les informations dont j'ai besoin des ViewModels imbriqués.

Cela cependant ne semble pas juste, comme je l'ai trouvé à je dois alors re-peupler le DisplayEntitiesWithRadioboxesViewModel avec les valeurs du FormCollection, si par exemple une erreur est survenue et l'utilisateur doit être renvoyé à la même vue.

J'ai essayé de chercher sur le web/livres mais je ne trouve pas de solution.

Y a-t-il un meilleur moyen?

Merci d'avance pour toute aide.

Et pourquoi avez-vous utilisé un EditorFor pour un menu déroulant simple, , qui est facile à utiliser avec DropDownFor

Cela a maintenant été modifié pour utiliser le DropDownFor.

ce qui est la clé de la DisplayEntitiesWithRadioboxesViewModel valeur dans FormCollection

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

Clare :-)

Répondre

3

Votre problème est assez commun et assez facile à résoudre une fois que vous comprenez comment cela fonctionne.

En ce moment, vous avez un modèle de vue qui a une propriété qui est IEnumerable<T> (peu importe le paramètre générique). Vous essayez de transmettre les éléments à la vue et remplir les IEnumerable<T> avec les mêmes valeurs lorsque la réponse revient, en utilisant les valeurs écrites à l'origine sur la page, et augmentées avec l'élément sélectionné (au moins à partir du code que vous avez publié quand même, cela vous aiderait à indiquer votre intention exacte dans la question). Le problème que vous avez ici est que vous devez envoyer ces valeurs à la page d'une manière dans laquelle ils peuvent être retournés. Permettez-moi simplement de dire maintenant que vous devriez probablement utiliser cette technique. Il est généralement préférable de renvoyer uniquement la sélection et de générer à nouveau la liste si vous avez besoin d'un serveur. Du point de vue des choses, vous voulez retourner la liste entière et ensuite rechercher l'élément qui est sélectionné, qui est après tout le point d'un groupe de boutons déroulants ou radio. Afin de récupérer la sélection, le paramètre de votre action de contrôleur doit avoir des propriétés qui correspondent aux variables retransmises. Dans ce cas, il semble que vous utilisiez le nom de paramètre radiobutton pour tous vos boutons radio (la même attente vaut true pour la liste déroulante, seulement il utilise le nom de la liste). Quelle que soit la personne sélectionnée, la valeur associée est renvoyée avec ce nom. Le framework MVC s'occupe d'essayer de trouver l'action appropriée qui a autant de noms spécifiés que possible.

Ce que vous devez utiliser pour votre paramètre d'action est une nouvelle classe qui contient une propriété pour tous les noms de champs renvoyés au serveur! Ou bien sûr vous pouvez simplement ajouter la propriété radiobutton à votre StructureViewModel aussi. En fait, vous remarquerez qu'il essaie déjà de définir cette valeur, mais elle n'existe pas sur votre modèle de vue. Cependant, vous ne recevrez toujours pas la liste d'origine, mais tout va bien, car même si vous avez reçu la liste d'origine, vous n'avez aucun identifiant pour vous permettre de savoir quel élément a été sélectionné!

Espérons que cela vous aide à comprendre ce qui se passe, si vous avez d'autres questions, s'il vous plaît demander.

0

Pouvez-vous me dire comment le EditorFor ressemble exactement? Et pourquoi avez-vous utilisé un EditorFor pour une liste déroulante simple, qui est facile à utiliser avec DropDownFor.

ce qui est le Key de la valeur DisplayEntitiesWithRadioboxesViewModel dans FormCollection

Si je comprends bien, vous avez une vue, avec certains parents-info, et en même temps plusieurs itérations de ces 2 champs dans la même vue . Est-ce correct?

Ensuite, je sais comment résoudre ce problème.

+0

Bonjour Stefanvds, J'ai modifié ma question ci-dessus pour répondre à vos questions. J'ai une vue parent qui contient une instance de DisplayEntitiesWithRadioboxesViewModel. Le DisplayEntitiesWithRadioboxesViewModel est IEnumerable. Merci Clare Détails cependant j'utiliser que pour les Vues imbriquées une fois dans ce – ClareBear

+0

il est logique que la clé pour votre radiobutton est 'DisplayEntitiesWithRadioboxesViewModel.radiobutton' parce que dans votre éditeurPour vous avez un radiobutton avec son nom 'radiobutton'. Si je comprends bien, tout fonctionne, seule la valeur radiobuttons n'est pas analysée dans votre viewmodel. Je pense que la meilleure façon est de créer un helper RadioButtonList comme décrit ici: http://geekswithblogs.net/michelotti/archive/2009/08/05/mvc-radiobuttonlist-html-helper.aspx. J'ai fait la même chose avec CheckBoxList et ça a bien marché. aussi, peut-être remplacer radiobuttonlist avec dropdown? – Stefanvds

+0

avez-vous réussi à le réparer? :) – Stefanvds

3

Je vous recommande d'utiliser des aides fortement typées partout pour ne pas avoir à vous soucier de nommer vos commandes.Voici comment procéder:

Modèles:

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

Vue principale (~/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> 

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

Soumettez maintenant le formulaire et tout devrait être lié correctement. Une chose importante à noter est que le modèle d'éditeur est fortement typé à DisplayEntityViewModel et non IEnumerable<DisplayEntityViewModel> comme dans votre cas. Lorsque votre écran principal, vous écrivez:

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

le cadre détecte automatiquement que la propriété est une collection et appellera le modèle de l'éditeur pour chaque élément de cette collection afin de ne plus besoin de boucle à travers les éléments qui rend votre code plus élégant.


MISE À JOUR:

Utilisation des listes déroulantes est également très facile: la caisse this answer.

+0

Bien que cela renvoie toutes les valeurs soumises au navigateur vers le serveur, il ne parvient toujours pas à récupérer la valeur sélectionnée, ce qui je crois est son malentendu. –

+0

@ NickLarsen, ce n'est pas clair pour moi sur la liste déroulante. Après son édition, l'OP déclare qu'elle a utilisé une liste déroulante mais n'a pas montré son code et parle toujours de 'radiobutton'. L'utilisation de la méthode d'aide 'DropDownListFor' fonctionne parfaitement avec les modèles d'éditeur et génère des noms corrects. Je ne comprends donc pas ce que vous voulez dire lorsque vous dites que cela * ne parvient toujours pas à récupérer la valeur sélectionnée *. –

+0

Si elle crée une liste déroulante ou une liste de boutons radio, elle essaie de sélectionner un seul élément dans une liste. D'après ce que je comprends, son problème est de récupérer la valeur sélectionnée à l'aide de l'une ou l'autre des méthodes et doit analyser les données de formulaire pour les récupérer, mais souhaiterait les récupérer en tant que propriété de son modèle de vue. La solution simple consiste à ajouter le nom de la liste utilisée, qui dans ce cas est 'radiobutton' comme une propriété de son modèle de vue et elle n'aura plus à creuser dans les données de formulaire pour la valeur qu'elle veut. –

Questions connexes