DisplayNameFor () จากรายการ <Object> ใน Model


88

ฉันเชื่อว่ามันค่อนข้างง่ายดูเหมือนฉันจะหาวิธีที่ถูกต้องในการแสดงชื่อที่แสดงสำหรับรายการภายในรายการภายในโมเดลของฉันไม่ได้

โมเดลที่เรียบง่ายของฉัน:

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

จะแตกถ้าไม่มีชื่อ มี 'วิธีที่ดีที่สุด' ในการรับชื่อที่แสดงที่นี่หรือไม่?

คำตอบ:


144

ใช้งานได้จริงแม้ไม่มีรายการในรายการ:

@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

น่าเสียดายที่สิ่งนี้ใช้ไม่ได้กับคุณสมบัติที่สามารถคำนวณได้ของ IE
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>

3

เป็นทางเลือกอื่นคุณสามารถลอง:

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

มันจะทำงานแม้ว่ารายการจะว่างเปล่า!


เหตุใดฉันจึงควรใช้โซลูชันนี้แทนโซลูชันของ Tim S
EKanadily

1

ฉันชอบวิธีแก้ปัญหาของ T-moty ฉันต้องการวิธีแก้ปัญหาโดยใช้ generics ดังนั้นวิธีแก้ปัญหาของฉันจึงเป็นดังนี้:

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

การใช้สิ่งนี้ในมุมมองก็เหมือนกับตัวอย่างของเขา ฉันจะสร้างเช่นเดียวของวัตถุว่างเปล่าดังนั้นฉันไม่ได้สร้างตัวอย่างใหม่ทุกครั้งที่ผมอ้างอิงเริ่มต้น

หมายเหตุจำเป็นต้องใช้ข้อ จำกัดใหม่ ()เพื่อเรียกT ()ใหม่ หากคลาสโมเดลของคุณไม่มีตัวควบคุมเริ่มต้นหรือคุณต้องการเพิ่มอาร์กิวเมนต์ให้กับตัวสร้างคุณสามารถใช้สิ่งนี้

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

มุมมองจะมีบรรทัด@modelดังนี้:

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

โปรดทราบว่าDisplayNameForไม่เคยเรียกใช้getสำหรับคุณสมบัติดังนั้นจึงไม่สำคัญว่าคุณจะสร้างอินสแตนซ์หรือไม่
NetMage
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.