如何将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()
而且这几乎是它。无需编写循环。一切都按照惯例运作。
它就像一个魅力!非常感谢你Darin :) – MrGorki 2011-12-28 15:54:00
这真的很令人兴奋!我打算实施你的建议。再次感谢你! – MrGorki 2011-12-28 16:01:04
我想再次感谢你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