如何将IEnumerable序列绑定到具有多列的容器?

问题描述:

我相信我找不到合适的标题来解释我的问题,但我认为这是最好的简短解释。如何将IEnumerable序列绑定到具有多列的容器?

请让我解释一下细节。

我想表明我的一个网页上的图片列表,并使用MVC的一个@foreach环3.

偏这份名单如下的观点:

@model IEnumerable<Picture> 
@foreach (var item in Model) 
{ 
    <a href="@item.PicId"> 
     <img height="35px" style="padding-top:3px" src="[email protected]" id="pictureMy" /> 
    </a> 
} 

正如你可以理解我发送一个列表到这个partialview,它将图片放在一个列上。

它工作没有任何问题,但我想显示每行3张图片,但无法管理。

任何指导将非常感激。

在此先感谢您的帮助。

,你可以将它们分组按3:

@model IEnumerable<Picture> 
@foreach (var item in Model.Select((value, index) => new { value, index }).GroupBy(x => x.index/3)) 
{ 
    <div> 
    @foreach (var picture in item) 
    { 
     <a href="@picture.value.PicId"> 
      <img height="35px" style="padding-top:3px" src="[email protected]" id="pictureMy" /> 
     </a> 
    } 
    </div> 
} 

但说实话,这种划分不是应该在视图中进行。您应该定义视图模型,然后让您的控制器操作执行分组并返回视图模型。

因此,让我们先来定义我们的视图模型开始:

public class PictureViewModel 
{ 
    public int PicId { get; set; } 
} 

public class GroupedPicturesViewModel 
{ 
    public IEnumerable<PictureViewModel> Pictures { get; set; } 
} 

则控制器动作:

public ActionResult Index() 
{ 
    // fetch the pictures from the DAL or something 
    IEnumerable<Picture> pictures = ... 

    // Now build the view model 
    var model = pictures 
     .Select((value, index) => new { value, index }) 
     .GroupBy(x => x.index/3) 
     .Select(x => new GroupedPicturesViewModel 
     { 
      Pictures = x.Select(p => new PictureViewModel 
      { 
       PicId = p.value.PicId 
      }) 
     } 
    ); 
    return View(model); 
} 

那么相应的视图:

@model IEnumerable<GroupedPicturesViewModel> 
@Html.DisplayForModel() 

那么相应的显示模板GroupedPicturesViewModel类型(~/Views/Shared/DisplayTemplates/GroupedPicturesViewModel.cshtml):

@model GroupedPicturesViewModel 
<div> 
    @Html.DisplayFor(x => x.Pictures) 
</div> 

终于为PictureViewModel类型(~/Views/Shared/DisplayTemplates/PictureViewModel.cshtml)显示模板:

@model PictureViewModel 
<a href="@Model.PicId"> 
    <img class="image" src="@Url.Content("~/ImageHandler.ashx?id=" + Model.PicId)" alt="" /> 
</a> 

最后一个件事是窃听我是这种定位的。看起来很丑。你不觉得吗?看起来像意大利面代码。

让我们通过编写自定义,可重复使用的HTML帮助,这将使得那些照片改进:

public static class HtmlExtensions 
{ 
    public static IHtmlString Picture(this HtmlHelper<PictureViewModel> htmlHelper) 
    { 
     var anchor = new TagBuilder("a"); 
     var picture = htmlHelper.ViewData.Model; 
     var id = picture.PicId.ToString(); 
     var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext); 

     // You probably need another property on your view model here as this 
     // id is suspicious about href but since that's what you had in your 
     // original code I don't know what is your intent. 
     anchor.Attributes["href"] = id; 
     var image = new TagBuilder("img"); 
     image.Attributes["alt"] = ""; 
     image.Attributes["src"] = urlHelper.Content(
      "~/ImageHandler.ashx?id=" + urlHelper.Encode(id) 
     ); 
     image.AddCssClass("image"); 
     anchor.InnerHtml = image.ToString(); 
     return new HtmlString(anchor.ToString()); 
    } 
} 

,然后在显示模板中,我们将简单地拥有:

@model PictureViewModel 
@Html.Picture() 

而且这几乎是它。无需编写循环。一切都按照惯例运作。

+0

它就像一个魅力!非常感谢你Darin :) – MrGorki 2011-12-28 15:54:00

+0

这真的很令人兴奋!我打算实施你的建议。再次感谢你! – MrGorki 2011-12-28 16:01:04

+0

我想再次感谢你Darin(我知道这将是第三次),因为你对我非常有帮助。我还想问你一个问题,以清楚地理解图片 。选择((value,index)=> new {value,index}) .GroupBy(x => x.index/3) .Select(x =>新GroupedPicturesViewModel { 照片= x.Select(p =>新PictureViewModel { PicId = p.value.PicId })} 方法 ,是否有任何机会,以限制该查询的次数?就像只随机显示6个。 – MrGorki 2011-12-29 15:08:10