我有viewmodel
public class ClientIndexViewModel
{
[Key]
public int SurrogateId { get; set; } // not primary key just used in templating
public IEnumerable<Client> Clients { get; set; }
}
我创建了一个名为Index.cs.t4
的新MvcView t4模板。当我从控制器创建一个新视图并将我的模型类添加为ClientIndexViewModel
时,会生成视图模板(index.cshtml),但没有IEnumerable<Client>
模板化Index.cshtml
<table class="table">
<!-- Client properties should be here .. i think -->
<tr>
<th></th> <!-- This is all empty because i dont really know what i am doing -->
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.SurrogateId }) |
@Html.ActionLink("Details", "Details", new { id=item.SurrogateId }) |
@Html.ActionLink("Delete", "Delete", new { id=item.SurrogateId })
</td>
</tr>
}
当我查看模板文件时,这是有意义的。
Index.cs.t4
<#
IEnumerable<PropertyMetadata> properties = ModelMetadata.Properties;
foreach (PropertyMetadata property in properties) {
if (property.Scaffold && !property.IsPrimaryKey && !property.IsAssociation) {
#>
<#
if (property.IsAssociation && GetRelatedModelMetadata(property) == null) {
continue;
}
#>
<th>
@Html.DisplayNameFor(model => model.<#= GetValueExpression(property) #>)
</th>
<#
}
}
#>
我希望能够专门定位IEnumerable<Client>
变量的viewmodel上的properties
属性,作为PropertyMetaData
我想我可以在ModelMEtadataFunctions.include.t4
文件中创建一个方法。只是不太确定如何,或者我是否应该这样做
答案 0 :(得分:0)
我找到了一个使这项工作成功的黑客。这绝不是任何理想的使用,但考虑到它只是视觉工作室的脚手架代码,而不是项目代码,它似乎并不太糟糕
首先。对于视图,Model Class是我想要枚举的实体类型。所以我从客户端实体获取客户端的所有属性,而不是我的viewmodel。然而,模型是错误的(当然)。因此,在模板文件Index.cs.t4
中,我根据ViewDataTypeShortName
参数(在Imports.include.t4
中找到)更改了控制块。这给了我Client
,因为我选择了客户端实体。
因此,例如在foreach
中,它通常会显示
@foreach (var item in Model){
<tr>
<td>
@Html.DisplayFor(modelItem => <#= "item." + GetValueExpression(property) #>)
</td>
</tr>
}
现在我通过添加
来控制它@foreach (var item in Model.<#= NewViewDataTypeShortName #>)
// NewViewDataTypeShortName is created with
// <# string NewViewDataTypeShortName = ViewDataTypeShortName + 's'; #>
// Based on my naming convention.
在Index.cshtml
@foreach (var item in Model.Clients) {
然后我通过在ModelMetaDataFunctions.cs.include.t4
string GetViewModelName(string ViewDataTypeName,string
ViewDataTypeShortName,string ViewName){
string[] names = ViewDataTypeName.Split(new string[]{"."},StringSplitOptions.None);
return names[0] + ".Domain.ViewModels." +
ViewDataTypeShortName + ViewName +"ViewModel";
}
在Index.cs.t4
中调用哪个
@model <#= GetViewModelName(ViewDataTypeName,ViewDataTypeShortName,ViewName) #>
然后在Index.cshtml
中显示为
@model TaskR.Domain.ViewModels.ClientIndexViewModel
这基本上给了我所需要的一切。它不是理想的,并且依赖于命名约定,我不确定我想交给另一个开发人员。例如,如果在主项目中创建了viewmodel,那么这将不会正确支撑,因为它基于数据类的单独项目。此外,实体类型名称和视图模型名称具有非常严格的约定,以实现此功能。
如果您有更好的主意,请发帖,我不认为这是最佳做法
答案 1 :(得分:0)
如果您的Models文件夹与ViewModels文件夹位于同一文件夹根目录中,则可以使用
string GetViewModelName(string ViewDataTypeName,string
ViewDataTypeShortName,string ViewName){
string[] names = ViewDataTypeName.Split('.');
names[names.Length-2] = "ViewModels";
names[names.Length-1] = names[names.Length-1]+"ViewModel";
return string.Join(".",names);
}
在我之后它更通用了