DisplayNameFor () From List <Object> in Model


87

이것은 매우 간단하다고 생각합니다. 모델 내의 목록에있는 항목의 표시 이름을 표시하는 올바른 방법을 찾지 못하는 것 같습니다.

내 단순화 된 모델 :

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);  

이름이 없으면 깨집니다. 여기에서 표시 이름을 얻는 '가장 좋은 방법'이 있습니까?

답변:


143

이것은 목록에 항목이 없어도 실제로 작동합니다.

@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)

나는 경우 대신의 있으리라 믿고있어 List<PersonNameViewModel>당신은이 IEnumerable<PersonNameViewModel>, 다음의 표현을 사용하는 것이 안전합니다 model => model.Names.First().FullName. 이 올바른지? 즉, 나는 dummyModel세 가지 중 가장 좋은 예를 좋아한다고 생각 합니다. 그렇지 않으면에 입력하거나 붙여 넣어야하는 여러 속성이있을 수 있습니다 model.Names[0].. 그럼 다시, 어쩌면 당신이 받아들이는 부분보기로 섹션 리팩토링해야 List또는 IEnumerable그 모델을.
aaaantoine

6
FirstOrDefault()빈 목록을 테스트하고 작업합니다.
Josh K

불행히도 이것은 IEnumerable 속성에서 작동하지 않습니다.
Willy David Jr.

7

이를위한 또 다른 방법이 있으며, 더 분명하다고 생각합니다.

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>

1

나는 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; }
    }
}

보기에서 이것을 사용하는 것은 그의 예와 동일합니다. 빈 개체의 단일 인스턴스를 생성하므로 Default를 참조 할 때마다 새 인스턴스를 생성하지 않습니다 .

참고는 새로운 () 제약 호출하기 위해 필요하다 () 새로운 T를 . 모델 클래스에 기본 생성자가 없거나 생성자에 인수를 추가해야하는 경우 다음을 사용할 수 있습니다.

private T defaultInstance = (T)Activator.CreateInstance(typeof(T), new object[] { "args" });

보기에는 다음과 같은 @model 행이 있습니다.

@model CustomList<Namespace.Of.PersonNameViewModel.Model>

참고 DisplayNameFor결코 실제로 호출 get은 인스턴스를 만드는 경우는 중요하지 않습니다, 그래서 속성.
NetMage

1

대체 솔루션으로 다음을 시도 할 수 있습니다.

@Html.DisplayNameFor(x => x.GetEnumerator().Current.ItemName)

목록이 비어 있어도 작동합니다!


Tim S의 솔루션 대신이 솔루션을 사용해야하는 이유는 무엇입니까?
EKanadily
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.