DisplayNameFor() 来自模型中的 List<Object>
Posted
技术标签:
【中文标题】DisplayNameFor() 来自模型中的 List<Object>【英文标题】:DisplayNameFor() From List<Object> in Model 【发布时间】:2014-01-15 11:15:40 【问题描述】:我相信这很简单,我只是似乎找不到正确的方法来显示模型中列表中项目的显示名称。
我的简化模型:
public class PersonViewModel
public long ID get; set;
private List<PersonNameViewModel> names = new List<PersonNameViewModel>();
[Display(Name = "Names")]
public List<PersonNameViewModel> Names get return names; set names = value;
和名称:
public class PersonNameViewModel
public long ID get; set;
[Display(Name = "Set Primary")]
public bool IsPrimary get; set;
[Display(Name = "Full Name")]
public string FullName get; set;
现在我想制作一个表格来显示一个人的所有姓名,并获取 DisplayNameFor FullName。很明显,
@html.DisplayNameFor(model => model.Names.FullName);
不会工作,并且
@Html.DisplayNameFor(model => model.Names[0].FullName);
如果没有名字就会中断。是否有“最佳方式”在此处获取显示名称?
【问题讨论】:
如果类属性没有用 get;放; DisplayNameFor 根本不起作用!这个新手错误有时也会发生在职业选手身上:D。 【参考方案1】:这确实有效,即使列表中没有项目:
@Html.DisplayNameFor(model => model.Names[0].FullName)
之所以有效,是因为 MVC 解析表达式而不是实际执行它。这使它可以找到正确的属性和属性,而无需列表中存在元素。
值得注意的是,参数(上面的model
)甚至不需要使用。这也有效:
@Html.DisplayNameFor(dummy => Model.Names[0].FullName)
这样:
@ Namespace.Of.PersonNameViewModel dummyModel = null;
@Html.DisplayNameFor(dummyParam => dummyModel.FullName)
【讨论】:
我假设如果你有一个IEnumerable<PersonNameViewModel>
而不是List<PersonNameViewModel>
,那么使用表达式model => model.Names.First().FullName
也是安全的。它是否正确?也就是说,我认为我最喜欢三个中的dummyModel
示例。否则,您可能需要在其中输入或粘贴多个属性model.Names[0].
。再说一次,也许您应该将该部分重构为接受List
或IEnumerable
作为其模型的部分视图。
我测试过,FirstOrDefault()
确实适用于空列表。
不幸的是,这不适用于 IEnumerable 属性。【参考方案2】:
还有另一种方法,我想这更清楚:
public class Model
[Display(Name = "Some Name for A")]
public int PropA get; set;
[Display(Name = "Some Name for B")]
public string PropB get; set;
public class ModelCollection
public List<Model> Models get; set;
public Model Default
get return new Model();
然后,在视图中:
@model ModelCollection
<div class="list">
@foreach (var m in Model.Models)
<div class="item">
@Html.DisplayNameFor(model => model.Default.PropA): @m.PropA
<br />
@Html.DisplayNameFor(model => model.Default.PropB): @m.PropB
</div>
</div>
【讨论】:
【参考方案3】:我喜欢 T-moty 的解决方案。我需要一个使用泛型的解决方案,所以我的解决方案基本上是这样的:
public class CustomList<T> : List<T> where T : new()
public static async Task<CustomList<T>> CreateAsync(IQueryable<T> source)
return new CustomList<T>(List<T> list); //do whatever you need in the contructor, constructor omitted
private T defaultInstance = new T();
public T Default
get return defaultInstance;
在视图中使用 this 与他的示例相同。我创建了一个空对象的单个实例,因此我不会在每次引用 Default 时都创建一个新实例。
注意,new() 约束是调用new T() 所必需的。如果您的模型类没有默认构造函数,或者您需要向构造函数添加参数,则可以使用:
private T defaultInstance = (T)Activator.CreateInstance(typeof(T), new object[] "args" );
视图将有一个 @model 行,例如:
@model CustomList<Namespace.Of.PersonNameViewModel.Model>
【讨论】:
请注意,DisplayNameFor
从未真正为属性调用 get
,因此创建实例并不重要。【参考方案4】:
作为替代解决方案,您可以尝试:
@Html.DisplayNameFor(x => x.GetEnumerator().Current.ItemName)
即使列表为空也能正常工作!
【讨论】:
我为什么要使用这个解决方案而不是 Tim S 的解决方案?以上是关于DisplayNameFor() 来自模型中的 List<Object>的主要内容,如果未能解决你的问题,请参考以下文章