[英]Polymorphic ViewModel collection and rendering in MVC partial Views
我的MVC应用程序中的ViewModel的多态集合存在问题。 我通过Web服务调用收到了这个,我需要迭代它们并根据对象类型给它们自己的局部视图。
public abstract class ProvinceViewModel
{
public string Code { get; set; }
}
public sealed class OntarioViewModel : ProvinceViewModel { }
public sealed class QuebecViewModel : ProvinceViewModel {}
在我看来,我试图迭代它们并分配局部视图。 我必须在这里进行大量的类型转换才能使其正常工作。 如果我尝试将其移动到控制器操作并传入抽象类型,我将得到一个错误,我们无法创建抽象类的实例。
ICollection<ProvinceViewModel> ProvinceList; // collection receive via service
@for (int i = 0, c = ProvinceList.Count; i < c; i++)
{
var currentProvince = this.Model.ElementAt(i);
@switch (additionalRegistry.Code)
{
case "QC":
@Html.Partial("AlbertaDetail", (QuebecViewModel)currentProvince)
break;
case "ON":
@Html.Partial("OntarioDetail", (OntarioViewModel)currentProvince)
break;
default:
@Html.Partial("ProvinceDetail", ProvinceViewModel)
break;
}
}
我强烈键入View,以便我可以访问不同的属性。
我将如何以更优雅的方式解决这个问题? 我是否需要为抽象类创建一个新的代理基类来创建它的实例更容易?
您可以使用显示模板实现此目的。 在Controller的Views目录中的DisplayTemplates文件夹中为每种类型创建一个显示模板:
+-- Views
+-- Provinces
+-- DisplayTemplates
+-- OntarioViewModel.cshtml
+-- QuebecViewModel.cshtml
在视图中使用DisplayFor帮助器显示每个模型:
@model ICollection<ProvinceViewModel>
@foreach (var province in Model)
{
@Html.DisplayFor(_ => province)
}
在遇到同样的问题时,我创建了以下解决方案:
首先,使用ExportMetadata
属性装饰您的(具体)视图模型, ExportMetadata
属性表示要使用的视图名称。 例如:
[ExportMetadata("View", "Ontario")]
public sealed class OntarioViewModel : ProvinceViewModel { }
[ExportMetadata("View", "Quebec")]
public sealed class QuebecViewModel : ProvinceViewModel {}
然后使用以下Partial
方法扩展您的HtmlHelper
:
public static MvcHtmlString Partial<T>(this HtmlHelper htmlHelper, T model, string prefix = null)
{
var modelType = typeof (T);
var partialAttr = modelType.GetCustomAttributes<ExportMetadataAttribute>().SingleOrDefault(x => x.Name == "View");
if (partialAttr == null)
throw new Exception(modelType.Name + " doesn't define any view to be used");
var partialName = (prefix ?? String.Empty) + partialAttr.Value;
return htmlHelper.Partial(partialName, model, htmlHelper.ViewData);
}
然后使用它:
@Html.Partial(currentProvince);
如果您的部分位于某个子目录中:
@Html.Partial(currentProvince, "Partials/")
(如果您需要帮助注册自定义HTML帮助程序,请参阅https://stackoverflow.com/a/5052790 )
我有类似的要求,这就是我设法解决这个问题的方法。 我的viewmodel(BusinessEventEmailViewModel)有一个在运行时使用unity解析的接口列表(IBusinessEventEmail)。 IBusinessEventEmail具有EventCode属性。
public class BusinessEventEmailViewModel : MailHeaderViewModel
{
#region members
public List<IBusinessEventEmail> Events { get; set; }
在我看来,我使用命名约定渲染局部视图:
Html.RenderPartial("~/Views/Shared/Email/_" + businessEvent.EventCode + ".cshtml", businessEvent);
然后,我有一个XXXEventEmail实现IBusinessEventEmail与EventCode XXX和部分视图_XXX.cshtml
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.