Supposons que j'ai ViewModel comme
public class AnotherViewModel
{
public string Name { get; set; }
}
public class MyViewModel
{
public string Name { get; set; }
public AnotherViewModel Child { get; set; }
public AnotherViewModel Child2 { get; set; }
}
Dans la vue, je peux rendre un partiel avec
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>
Dans le partiel je ferai
<%= Html.TextBox("Name", Model.Name) %>
or
<%= Html.TextBoxFor(x => x.Name) %>
Cependant, le problème est que les deux rendront name = "Name" alors que j'ai besoin d'avoir name = "Child.Name" pour que le classeur de modèle fonctionne correctement. Ou, name = "Child2.Name" lorsque je rend la deuxième propriété en utilisant la même vue partielle.
Comment faire pour que ma vue partielle reconnaisse automatiquement le préfixe requis? Je peux le passer en paramètre mais c'est trop gênant. C'est encore pire quand je veux par exemple le rendre récursif. Existe-t-il un moyen de rendre des vues partielles avec un préfixe, ou, mieux encore, avec une reconition automatique de l'expression lambda appelante de sorte que
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>
ajoutera automatiquement un "enfant" correct. préfixe aux chaînes de nom / id générées?
Je peux accepter n'importe quelle solution, y compris les moteurs de visualisation tiers et les bibliothèques - j'utilise en fait Spark View Engine (je «résous» le problème en utilisant ses macros) et MvcContrib, mais je n'y ai pas trouvé de solution. XForms, InputBuilder, MVC v2 - tout outil / aperçu qui fournit cette fonctionnalité sera génial.
Actuellement, je pense à le coder moi-même, mais cela semble être une perte de temps, je ne peux pas croire que ce truc trivial ne soit pas déjà implémenté.
De nombreuses solutions manuelles peuvent exister et toutes sont les bienvenues. Par exemple, je peux forcer mes partiels à être basés sur IPartialViewModel <T> {public string Prefix; Modèle T; }. Mais je préfère une solution existante / approuvée.
MISE À JOUR: il y a une question similaire sans réponse ici .
helper.ViewData.TemplateInfo.HtmlFieldPrefix
sous la forme{oldprefix}.{newprefix}
new ViewDataDictionary(helper.ViewData)
parnew ViewDataDictionary(((HtmlHelper)helper).ViewData)
. Voyez-vous un problème avec cela?string oldPrefix = helper.ViewData.TemplateInfo.HtmlFieldPrefix; if (oldPrefix != "") name = oldPrefix + "." + name;
jusqu'à présent, je cherchais la même chose que j'ai trouvé dans ce post récent:
http://davybrion.com/blog/2011/01/prefixing-input-elements-of-partial-views-with-asp-net-mvc/
la source
ViewDataDictionary
constructeur qui prend le courantViewData
, sinon vous perdrez les erreurs d'état du modèle, les données de validation, etc.Ma réponse, basée sur la réponse de Mahmoud Moravej y compris le commentaire d'Ivan Zlatev.
Edit: La réponse de Mohamoud est incorrecte pour le rendu partiel imbriqué. Vous devez ajouter le nouveau préfixe à l'ancien préfixe, uniquement si cela est nécessaire. Ce n'était pas clair dans les dernières réponses (:
la source
En utilisant MVC2, vous pouvez y parvenir.
Voici la vue fortement typée:
Voici la vue fortement typée pour la classe enfant (qui doit être stockée dans un sous-dossier du répertoire de vue appelé EditorTemplates):
Voici le contrôleur:
Voici les classes personnalisées:
Et la source de sortie:
Maintenant, c'est terminé. Définissez un point d'arrêt dans l'action Créer un contrôleur post à vérifier. Ne l'utilisez pas avec des listes car cela ne fonctionnera pas. Voir ma question sur l'utilisation de EditorTemplates avec IEnumerable pour plus d'informations à ce sujet.
la source
Html.EditorFor
méthode de rendu du formulaire enfant. C'est précisément pour cela que les modèles d'éditeur sont censés être utilisés. Cela devrait être la réponse.C'est une vieille question, mais pour quiconque arrive ici à la recherche d'une solution, pensez à l'utiliser
EditorFor
, comme suggéré dans un commentaire sur https://stackoverflow.com/a/29809907/456456 . Pour passer d'une vue partielle à un modèle d'éditeur, procédez comme suit.Vérifiez que votre vue partielle est liée à ComplexType .
Déplacez votre vue partielle vers un sous-dossier EditorTemplates du dossier de vue actuel ou vers le dossier Shared . Maintenant, c'est un modèle d'éditeur.
Changer
@Html.Partial("_PartialViewName", Model.ComplexType)
en@Html.EditorFor(m => m.ComplexType, "_EditorTemplateName")
. Le modèle d'éditeur est facultatif s'il s'agit du seul modèle pour le type complexe.Les éléments d'entrée Html seront automatiquement nommés
ComplexType.Fieldname
.la source
PartailFor pour asp.net Core 2 au cas où quelqu'un en aurait besoin.
la source
Je suis également tombé sur ce problème et après beaucoup de douleur, j'ai trouvé qu'il était plus facile de repenser mes interfaces de sorte que je n'ai pas besoin de publier des objets de modèle imbriqués. Cela m'a forcé à changer mes flux de travail d'interface: bien sûr, je demande maintenant à l'utilisateur de faire en deux étapes ce que je rêvais de faire sur une, mais la facilité d'utilisation et la maintenabilité du code de la nouvelle approche sont plus importantes pour moi maintenant.
J'espère que cela aide certains.
la source
Vous pouvez ajouter un assistant pour le RenderPartial qui prend le préfixe et le fait apparaître dans ViewData.
Puis un autre assistant qui concatène la valeur ViewData
et donc dans la vue ...
dans le partiel ...
la source
Comme vous, j'ajoute la propriété Prefix (une chaîne) à mes ViewModels que j'ajoute avant les noms d'entrée liés à mon modèle. (YAGNI empêchant le dessous)
Une solution plus élégante pourrait être un modèle de vue de base qui possède cette propriété et des HtmlHelpers qui vérifient si le modèle de vue dérive de cette base et, le cas échéant, ajoutent le préfixe au nom d'entrée.
J'espère que cela pourra aider,
Dan
la source
Que diriez-vous juste avant d'appeler RenderPartial?
Ensuite, dans votre partiel, vous avez
la source