DisplayNameFor () From List <Object> trong Model


87

Tôi tin rằng điều này khá đơn giản, dường như tôi không thể tìm ra cách phù hợp để hiển thị tên hiển thị cho một mục trong danh sách trong mô hình của mình.

Mô hình đơn giản của tôi:

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

và Tên:

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

Bây giờ tôi muốn tạo một bảng để hiển thị tất cả tên của một người và lấy DisplayNameFor FullName. Chắc chắn,

@Html.DisplayNameFor(model => model.Names.FullName);

sẽ không hoạt động, và

@Html.DisplayNameFor(model => model.Names[0].FullName);  

sẽ phá vỡ nếu không có tên. Có cách nào tốt nhất để lấy tên hiển thị ở đây không?

Câu trả lời:


143

Điều này thực sự hoạt động, ngay cả khi không có các mục trong danh sách:

@Html.DisplayNameFor(model => model.Names[0].FullName)

Nó hoạt động vì MVC phân tích cú pháp biểu thức thay vì thực thi nó. Điều này cho phép nó tìm thấy thuộc tính và thuộc tính phù hợp mà không cần phải có một phần tử trong danh sách.

Cần lưu ý rằng tham số ( modelở trên) thậm chí không cần được sử dụng. Điều này cũng hoạt động:

@Html.DisplayNameFor(dummy => Model.Names[0].FullName)

Như thế này:

@{ Namespace.Of.PersonNameViewModel dummyModel = null; }
@Html.DisplayNameFor(dummyParam => dummyModel.FullName)

Tôi giả định rằng nếu thay vì một List<PersonNameViewModel>bạn có một IEnumerable<PersonNameViewModel>, thì cũng an toàn để sử dụng biểu thức model => model.Names.First().FullName. Điều này có chính xác? Điều đó nói rằng, tôi nghĩ tôi thích dummyModelví dụ nhất trong ba người. Nếu không, bạn có thể có một số thuộc tính mà bạn cần nhập hoặc dán model.Names[0].. Sau đó, một lần nữa, có thể bạn nên cấu trúc lại phần này thành một chế độ xem một phần chấp nhận Listhoặc IEnumerablenhư mô hình của nó.
aaaantoine

6
Tôi đã thử nghiệm và FirstOrDefault()làm việc với một danh sách trống.
Josh K

Thật không may, điều này không hoạt động trên thuộc tính IEnumerable.
Willy David Jr

7

Có một cách khác để làm điều đó và tôi đoán điều đó rõ ràng hơn:

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

Và sau đó, trong chế độ xem:

@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ôi thích giải pháp của T-moty. Tôi cần một giải pháp sử dụng generic nên giải pháp của tôi về cơ bản là:

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

Sử dụng điều này trong khung nhìn cũng giống như ví dụ của anh ấy. Tôi tạo một phiên bản duy nhất của một đối tượng trống vì vậy tôi không tạo một phiên bản mới mỗi khi tôi tham chiếu đến Default .

Lưu ý, ràng buộc new () là cần thiết để gọi T () mới . Nếu lớp mô hình của bạn không có hàm tạo mặc định hoặc bạn cần thêm đối số vào hàm tạo, bạn có thể sử dụng cách này:

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

Chế độ xem sẽ có dòng @model như:

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

Lưu ý rằng DisplayNameForkhông bao giờ thực sự gọi thuộc tính getcho thuộc tính, vì vậy không quan trọng nếu bạn tạo một phiên bản.
NetMage

1

Là một giải pháp thay thế bạn có thể thử:

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

Nó sẽ hoạt động ngay cả khi danh sách trống!


tại sao tôi nên sử dụng giải pháp này thay vì giải pháp của Tim S?
EKanadily
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.