2009-07-10 5 views
3

J'ai deux instances d'un contrôle Address.ascx dans une page ASP.NET MVC.Comment utiliser deux instances du même fichier .ascx dans la même page dans ASP.NET MVC?

<h1>Shipping Address</h1> 
    <% Html.RenderPartial("Controls/AddressControl"); %> 

    <h1>Billing Address</h1> 
    <% Html.RenderPartial("Controls/AddressControl"); %> 

Bien sûr, avec le code exactement comme ça, je vais finir avec les mêmes ID pour chaque champ de l'adresse. Je peux facilement ajouter une chaîne à l'ID des champs, donc j'aurais 'Street1_billing' et 'Street1_shipping', mais je ne vois pas comment mapper cela au modèle.

Quelle est la meilleure solution pour mapper un modèle à un tableau d'éléments (dans ce cas seulement 2). Je ne connais aucune solution prête à l'emploi ASP.NET pour cela.

Note: Ceci est légèrement similaire à this question et je pourrais utiliser this solution from Scott Hanselman, mais ce n'est pas exactement ce que je veux. Dans mon cas, je sais que j'ai deux éléments, donc c'est essentiellement un tableau de 2 éléments, mais je me demande s'il y a une solution un peu plus élégante.

PS. Je suis sûr que cela a été demandé à plusieurs reprises auparavant, mais je ne peux pas sembler juste de mettre dans les termes de recherche. S'il vous plaît lier cette question si vous êtes conscient de dupes!

Répondre

3

Vous pouvez avoir un ViewModel

OrderCheckoutViewModel 
{ 
    public Address ShippingAddress{get;set;} 
    public Address BillingAddress{get;set;} 
} 

Les valeurs de FormElements sont mis en correspondance le membre de droite du ViewModel s'ils ont le formulaire

Il n'y a pas moyen facile et élégant de venir de StreetAddress1 à ShippingAddress.StreetAddress1. Mon modèle d'adresse a la forme:

public class Address 
{ 
    String StreetAddress1 { get; set } 
    String StreetAddress2 { get; set } 
    String City { get; set } 
    String State { get; set } 
    String Zip { get; set } 
    String InstanceName{ get; set } 
} 

Je mis le InstanceName au nom de la propriété (ShippingAddress).

Ensuite, les éléments de formulaire sont définis dans cette forme

<input type="text" name="<%=Model.InstanceName%>.StreetAddress1"><input> 

La place du ascx semble hors du commun.Une raison pour laquelle vous ne le mettez pas dans Shared et y accéder par

<% Html.RenderPartial("AddressControl",Model.ShippingAddress); %> 

?

+0

merci. cela semble la solution la plus propre jusqu'à présent. Je n'avais pas réalisé que le modelbinder était si intelligent :-) et en ce qui concerne l'emplacement .ascx, je suis en train d'écrire un panier dans une application existante et je veux garder les commandes du panier aussi séparées que possible. –

+0

Ce type est intelligent en effet. Une chose que je n'ai toujours pas vue est si vous pouvez mapper une valeur de l'itinéraire avec le même type de syntaxe. –

4

Tout d'abord, ajoutez une classe au modèle.

public class Address 
{ 
    String StreetAddress1 { get; set } 
    String StreetAddress2 { get; set } 
    String City { get; set } 
    String State { get; set } 
    String Zip { get; set } 
} 


Dans Address.ascx, vous avez besoin d'une ligne en haut qui hérite du modèle d'adresse, comme ceci:

<%@ Page Language="C#" 
    Inherits="System.Web.Mvc.ViewPage<MyProject.Models.Address>" %> 


Dans le contrôleur pour la vue principale , poussez vos deux adresses dans le ViewData.

Address myAddressObject1 = new Address 
{ 
    AddressLine1 = "123 Anywhere Street", 
    // ..etc. Same with MyAddressObject2. Or, just populate from database. 
} 

ViewData["Address1"] = myAddressObject1; 
ViewData["Address2"] = myAddressObject2; 
// 
// do other stuff as needed 
// 
Return View(); 


Dans votre vue principale, appelez vos deux adresses subviews comme ceci:

<%= Html.RenderPartial("Address", ViewData["Address1"]) %> 
<%= Html.RenderPartial("Address", ViewData["Address2"]) %> 
Questions connexes