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&lt;PersonNameViewModel&gt; 而不是List&lt;PersonNameViewModel&gt;,那么使用表达式model =&gt; model.Names.First().FullName 也是安全的。它是否正确?也就是说,我认为我最喜欢三个中的dummyModel 示例。否则,您可能需要在其中输入或粘贴多个属性model.Names[0].。再说一次,也许您应该将该部分重构为接受ListIEnumerable 作为其模型的部分视图。 我测试过,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>的主要内容,如果未能解决你的问题,请参考以下文章

DisplayNameFor()方法的工作原理

如何@Html.DisplayNameFor() 对列表的基类属性的属性?

MVC 5 视图中的@model 和 Model 是啥

来自epipole和图像点的极线

我无法访问列表中的模型字段

即使模型正确,来自 API 的响应也不会映射到对象