J'appelle ma vue partielle comme ceci:
<% Html.RenderPartial("~/controls/users.ascx"); %>
Puis-je transmettre des paramètres à une vue partielle? Comment vais-je y accéder dans la page réelle users.ascx?
Vous pouvez passer un objet modèle au partiel (par exemple une liste de chaînes):
<% Html.RenderPartial("~/controls/users.ascx", new string[] { "foo", "bar" }); %>
Ensuite, vous tapez fortement le partiel et la propriété Model
sera du type approprié:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Collections.Generic.IEnumerable<string>>" %>
<% foreach (var item in Model) { %>
<div><%= Html.Encode(item) %></div>
<% } %>
Il existe une autre surcharge pour RenderPartial qui passera par votre modèle.
<% Html.RenderPartial("~/controls/users.ascx", modelGoesHere); %>
Comment y accéder? Tout comme vous le feriez normalement avec n'importe quelle vue:
<%= Model.MagicSauce %>
Il a fallu un certain temps pour pénétrer, mais MVC signifie que vous utilisez un modèle, une vue et un contrôleur d'une manière ou d'une autre pour à peu près tout, y compris les vues partielles. La façon dont les trois éléments s'emboîtent peut être un peu intimidante au début. Je n'en avais jamais fait jusqu'à maintenant, et ça marche - Woohoo!
J'espère que cela aidera la prochaine personne .... Désolé, j'utilise un rasoir au lieu des formulaires .Net. Je récupère également des données d'une base de données SQL Server dans Entity Framework, qu'un développeur est susceptible d'utiliser. J'ai aussi probablement un peu exagéré avec WebGrid, qui est tellement plus élégant qu'une déclaration foreach. Un @ webgrid.GetHtml () basique affichera chaque colonne et ligne.
Dans cet exemple de travail, les utilisateurs ont téléchargé des photos. Leurs photos sont affichées dans leur formulaire d'édition à l'aide d'une vue partielle. Les métadonnées ImageID et FileName sont conservées dans SQL Server tandis que le fichier lui-même est conservé dans le répertoire ~/Content/UserPictures.
Je sais que c'est un peu à moitié vaste, car tous les détails du téléchargement et de la modification des données personnelles ne sont pas affichés. Seules les parties pertinentes de l'utilisation d'une vue partielle sont concentrées, bien que des EF bonus soient ajoutés. L'espace de nom est MVCApp3 pour S&G.
Modèle de vue partielle ViewModels.cs
Le tableau des images SQL Server comprend de nombreuses autres colonnes en plus de ImageID et FileName telles que [Légende], [Description], un hachage MD5 pour empêcher la même image d'être téléchargée plusieurs fois et la date de téléchargement. Le ViewModel distille l'entité jusqu'au strict minimum nécessaire à un utilisateur pour voir ses photos.
public class Picts
{
public int ImageID { get; set; }
public string FileName { get; set; }
}
Vue principale Edit.cshtml
Notez le cast/convert pour taper fortement le ViewData [].
@Html.Partial(
partialViewName: "Picts",
model: (IEnumerable<MVCApp3.Models.Picts>)ViewData["Picts"]
)
Si vous ne définissez pas le modèle fortement typé à utiliser pour la vue partielle, vous obtiendrez un " L'élément de modèle transmis au dictionnaire est de type 'System.Data.Entity.DynamicProxies ... "erreur car il suppose que vous passez le modèle parent/maître.
Vue partielle Picts.cshtml (tout le contenu du fichier est affiché)
@model IEnumerable<MVCApp3.Models.Picts>
@{
var pictsgrid = new WebGrid(Model);
}
@pictsgrid.GetHtml(
tableStyle: "grid",
displayHeader: false,
alternatingRowStyle: "alt",
columns: pictsgrid.Columns(
pictsgrid.Column(format:@<text><img src="@Url.Content("~/Content/Users/" + @item.FileName)" alt="@item.ImageID" width="200" />
@Html.ActionLink(linkText: "Delete", actionName: "DeletePicture", routeValues: new { id = @item.ImageID })
</text>)
))
Contrôleur IdentityController.cs
Définissez le contenu des données dans ViewData ["MyPartialViewModelKeyName"] que votre vue partielle consommera. Vous pouvez donner à la clé de dictionnaire le nom que vous voulez, mais je lui ai donné ViewData ["Picts"] pour être cohérent avec le nom du fichier de vue partielle et sa définition de classe de modèle de vue.
Étant donné que les images peuvent être partagées entre plusieurs utilisateurs, il existe une table plusieurs-à-plusieurs avec une requête PITA correspondante dans Entity Framework utilisant des froms imbriqués et des jointures internes pour renvoyer uniquement les images appartenant à un utilisateur ou partagées avec lui:
public class IdentityController : Controller
{
private EzPL8Entities db = new EzPL8Entities();
// GET: /Identity/Edit/5
[Authorize]
public ActionResult Edit(int? id)
{
if (id == null)
return new HttpNotFoundResult("This doesn't exist");
// get main form data
ezpl8_UsersPhysicalIdentity ezIDobj = db.ezpl8_UsersPhysicalIdentity.Find(id)
// http://learnentityframework.com/LearnEntityFramework/tutorials/many-to-many-relationships-in-the-entity-data-model/
// get partial form data for just this user's pictures
ViewData["Picts"] = (from user in db.ezpl8_Users
from ui in user.ezpl8_Images
join image in db.ezpl8_Images
on ui.ImageID equals image.ImageID
where user.ezpl8_UserID == id
select new Picts
{
FileName = image.FileName,
ImageID = image.ImageID
}
).ToList();
return View(ezIDobj);
}
// Here's the Partial View Controller --not much to it!
public ViewResult Picts(int id)
{
return View(ViewData["Picts"]);
}
[Authorize] //you have to at least be logged on
public ActionResult DeletePicture(int id)
{
//ToDo: better security so a user can't delete another user's picture
// TempData["ezpl8_UserID"]
ezpl8_Images i = db.ezpl8_Images.Find(id);
if (i != null)
{
var path = System.IO.Path.Combine(Server.MapPath("~/Content/Users"), i.FileName);
System.IO.File.Delete(path: path);
db.ezpl8_Images.Remove(i);
db.SaveChanges();
}
return Redirect(Request.UrlReferrer.ToString());
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
// get main form data
ezpl8_UsersPhysicalIdentity ezIDobj = db.ezpl8_UsersPhysicalIdentity.Find(id)
// http://learnentityframework.com/LearnEntityFramework/tutorials/many-to-many-relationships-in-the-entity-data-model/
// get partial form data for just this user's pictures
ViewData["Picts"] = (from user in db.ezpl8_Users
from ui in user.ezpl8_Images
join image in db.ezpl8_Images
on ui.ImageID equals image.ImageID
where user.ezpl8_UserID == id
select new Picts
{
FileName = image.FileName,
ImageID = image.ImageID
}
).ToList();
return View(ezIDobj);
}
// Voici le contrôleur de vue partielle - pas grand chose! public ViewResult Picts (int id) {return View (ViewData ["Picts"]); }
[Authorize] //you have to at least be logged on
public ActionResult DeletePicture(int id)
{
//ToDo: better security so a user can't delete another user's picture
// TempData["ezpl8_UserID"]
ezpl8_Images i = db.ezpl8_Images.Find(id);
if (i != null)
{
var path = System.IO.Path.Combine(Server.MapPath("~/Content/Users"), i.FileName);
System.IO.File.Delete(path: path);
db.ezpl8_Images.Remove(i);
db.SaveChanges();
}
return Redirect(Request.UrlReferrer.ToString());
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}