ASP.NET MVC 3 - เทมเพลตบางส่วนกับ Display Template เทียบกับ Template Editor


303

ดังนั้นชื่อควรพูดเพื่อตัวเอง

ในการสร้างส่วนประกอบที่ใช้งานซ้ำได้ใน ASP.NET MVC เรามี 3 ตัวเลือก (อาจเป็นอย่างอื่นที่ฉันไม่ได้กล่าวถึง)

มุมมองบางส่วน:

@Html.Partial(Model.Foo, "SomePartial")

เทมเพลตแก้ไขที่กำหนดเอง:

@Html.EditorFor(model => model.Foo)

เทมเพลตการแสดงผลที่กำหนดเอง:

@Html.DisplayFor(model => model.Foo)

ในแง่ของการดู / HTML การใช้งานทั้งสามนั้นเหมือนกัน:

@model WebApplications.Models.FooObject

<!-- Bunch of HTML -->

ดังนั้นคำถามของฉันคือ - เมื่อใด / คุณตัดสินใจเลือกหนึ่งในสามที่จะใช้

สิ่งที่ฉันกำลังมองหาจริงๆคือรายการคำถามที่ถามตัวเองก่อนสร้างคำถามซึ่งสามารถใช้คำตอบเพื่อตัดสินใจว่าจะใช้เทมเพลตใด

นี่คือ 2 สิ่งที่ฉันค้นพบได้ดีขึ้นด้วย EditorFor / DisplayFor:

  1. พวกเขาเคารพลำดับชั้นของแบบจำลองเมื่อเรนเดอร์ HTML helpers (เช่นถ้าคุณมีวัตถุ "Bar" ในโมเดล "Foo" ของคุณองค์ประกอบ HTML สำหรับ "Bar" จะแสดงผลด้วย "Foo.Bar.ElementName" ในขณะที่บางส่วนจะมี " ElementName ")

  2. มีประสิทธิภาพมากขึ้นเช่นหากคุณมีList<T>สิ่งใดสิ่งหนึ่งใน ViewModel ของคุณคุณสามารถใช้งาน@Html.DisplayFor(model => model.CollectionOfFoo)ได้และ MVC นั้นฉลาดพอที่จะเห็นว่าเป็นคอลเลกชันและแสดงหน้าจอเดียวสำหรับแต่ละรายการ (ตรงข้ามกับ Partial ซึ่งต้องมีความชัดเจน ห่วง)

ฉันเคยได้ยิน DisplayFor แสดงเทมเพลต "อ่านอย่างเดียว" แต่ฉันไม่เข้าใจ - ฉันไม่สามารถโยนแบบฟอร์มลงไปที่นั่นได้หรือไม่

มีใครบอกฉันด้วยเหตุผลอื่นได้ไหม มีรายการ / บทความที่เปรียบเทียบทั้งสามบ้างไหม?


แนวคิดที่อยู่เบื้องหลังตัวแก้ไขและเทมเพลตการแสดงนั้นมีการกำหนดไว้อย่างชัดเจนในเอกสารประกอบสำหรับ asp.net mvc 2 เทมเพลตเป็นส่วนหนึ่งที่ยึดตามข้อกำหนดเฉพาะ สถานการณ์ที่ทำให้เทมเพลตดีขึ้นหรือแย่ลงกว่าเดิมส่วนใหญ่จะขึ้นอยู่กับว่าการประชุมนั้นคุ้มค่าหรือไม่ในการสมัครของคุณ
Nick Larsen

คำตอบ:


301

EditorForvs DisplayForเป็นเรื่องง่าย ความหมายของวิธีการคือการสร้างมุมมองแก้ไข / แทรกและแสดง / อ่านอย่างเดียว (ตามลำดับ) ใช้DisplayForเมื่อแสดงข้อมูล (เช่นเมื่อคุณสร้าง divs และช่วงที่มีค่ารุ่น) ใช้EditorForเมื่อแก้ไข / แทรกข้อมูล (เช่นเมื่อคุณสร้างแท็กอินพุตภายในฟอร์ม)

วิธีการดังกล่าวเป็นแบบจำลองเป็นศูนย์กลาง ซึ่งหมายความว่าพวกเขาจะคำนึงถึงข้อมูลเมตาของโมเดล (ตัวอย่างเช่นคุณสามารถใส่คำอธิบายประกอบคลาสโมเดลของคุณด้วย[UIHintAttribute]หรือ[DisplayAttribute]และสิ่งนี้จะมีผลต่อเทมเพลตที่ได้รับเลือกเพื่อสร้าง UI สำหรับโมเดลพวกเขามักใช้สำหรับโมเดลข้อมูลเช่น แสดงแถวในฐานข้อมูล ฯลฯ )

ในทางตรงกันข้ามPartialมุมมองเป็นศูนย์กลางในการที่คุณส่วนใหญ่กังวลกับการเลือกมุมมองบางส่วนที่ถูกต้อง มุมมองไม่จำเป็นต้องมีรูปแบบการทำงานอย่างถูกต้อง มันสามารถมีมาร์กอัปชุดทั่วไปที่นำกลับมาใช้ซ้ำทั่วทั้งไซต์ แน่นอนบ่อยครั้งที่คุณต้องการส่งผลกระทบต่อพฤติกรรมของบางส่วนนี้ซึ่งในกรณีนี้คุณอาจต้องการส่งผ่านโมเดลการดูที่เหมาะสม

คุณไม่ได้ถามเกี่ยวกับ@Html.Actionสิ่งที่สมควรได้รับการกล่าวถึงที่นี่ คุณอาจคิดว่ามันเป็นเวอร์ชันที่มีประสิทธิภาพมากกว่าPartialในการที่จะเรียกใช้แอคชันลูกของคอนโทรลเลอร์จากนั้นแสดงมุมมอง (ซึ่งโดยปกติจะเป็นมุมมองบางส่วน) สิ่งนี้มีความสำคัญเนื่องจากการกระทำของเด็กสามารถดำเนินการตรรกะทางธุรกิจเพิ่มเติมที่ไม่ได้อยู่ในมุมมองบางส่วน ตัวอย่างเช่นมันสามารถแสดงส่วนประกอบตะกร้าสินค้า เหตุผลในการใช้เพื่อหลีกเลี่ยงการทำงานเกี่ยวกับรถเข็นสินค้าในทุกคอนโทรลเลอร์ในแอปพลิเคชันของคุณ

ในที่สุดทางเลือกขึ้นอยู่กับว่าคุณกำลังสร้างโมเดลในใบสมัครของคุณคืออะไร โปรดจำไว้ว่าคุณสามารถผสมและจับคู่ ตัวอย่างเช่นคุณอาจมีมุมมองบางส่วนที่เรียกEditorForผู้ช่วย ขึ้นอยู่กับว่าแอปพลิเคชันของคุณคืออะไรและจะคำนึงถึงปัจจัยอย่างไรเพื่อกระตุ้นการใช้รหัสซ้ำสูงสุดในขณะที่หลีกเลี่ยงการทำซ้ำ


4
นั่นเป็นคำตอบที่ยอดเยี่ยมสิ่งที่ฉันกำลังมองหา ในความเป็นจริงฉันเป็นธนาคารในความจริงที่คุณต้องการและตอบ :) ขอบคุณ marcin
RPM1984

คุณจะใช้คำอธิบายประกอบเพื่อระบุเทมเพลตการแสดงผลและเทมเพลตการแก้ไขสำหรับคุณสมบัติเดียวได้อย่างไร
stormwild

3
@stormwild ใช้แบบแผนและตั้งชื่อแม่แบบของคุณหลังจากโมเดลที่เกี่ยวข้องกับ (/Views/DisplayTemplates/MyModel.cshtml) หรือบังคับให้มีคำอธิบายประกอบ UIHint อย่างชัดเจน
Tom Wayson

คำแนะนำในการเลือกสร้างวิซาร์ด "register user" ที่นำกลับมาใช้ใหม่ได้หรือไม่? ฉันต้องการสร้างมุมมองเหล่านี้ (และตัวควบคุม) ในชุดประกอบแยกต่างหากถ้าเป็นไปได้ Aka เป็นวิธีการแจกจ่ายต่อระหว่างหลาย ๆ ทีมในรูปแบบ / คอนโทรลเลอร์ mVC ที่ปรับค่าได้เหล่านี้ (เราได้สร้างวิธีการเดียวในการจัดการผู้ใช้ / การจัดเก็บ (บริการ webapi) ... แต่แต่ละทีมกำลังสร้างหน้า mvc ของตัวเอง: <ขอบคุณ
granadaCoder

คุณเก็บเทมเพลตเหล่านั้นไว้ที่ไหน ฉันต้องจัดเก็บไว้ใน Shared / EditorTemplates หรือเป็นไปได้หรือไม่ที่จะเก็บไว้ในโฟลเดอร์คอนโทรลเลอร์ปัจจุบันโดยตรง (เมื่อฉันต้องการเฉพาะที่นั่น)
Santhos

15

แน่นอนคุณสามารถปรับแต่งDisplayForเพื่อแสดงแบบฟอร์มที่แก้ไขได้ แต่การประชุมสำหรับการDisplayForที่จะเป็นreadonlyและEditorForจะเป็นสำหรับการแก้ไข การยึดกับการประชุมจะทำให้แน่ใจได้ว่าไม่ว่าคุณจะผ่านอะไรไปDisplayForก็ตามมันก็จะทำสิ่งเดียวกัน


2
ฉันไม่คิดว่าจะมีคำถาม / ข้อสงสัยใด ๆ ว่าเมื่อใดควรใช้เทมเพลตการแสดงผลเทียบกับเทมเพลตการแก้ไข คำถามที่แท้จริงดูเหมือนจะเป็นเมื่อคุณควรใช้แม่แบบ vs partials คำตอบของคุณหายไปอย่างสมบูรณ์
Joshua Hayes

19
@ โจชัว - ฉันคิดว่ามีคำถามบางอย่างที่: "ฉันยังได้ยิน DisplayFor ทำให้แม่แบบ" อ่านอย่างเดียว "แต่ฉันไม่เข้าใจว่า - ฉันไม่สามารถโยนแบบฟอร์มที่นั่นได้หรือไม่"
Robert Levy

13

เพียงแค่ให้มูลค่า 2c ของฉันโครงการของเราใช้มุมมองบางส่วนกับแท็บ jQuery หลายแท็บและแต่ละแท็บจะแสดงฟิลด์ด้วยมุมมองบางส่วนของตัวเอง สิ่งนี้ทำงานได้ดีจนกระทั่งเราเพิ่มคุณลักษณะโดยที่แท็บบางตัวใช้ร่วมกันในฟิลด์ทั่วไป วิธีแรกของเราในการทำเช่นนี้คือการสร้างมุมมองบางส่วนด้วยฟิลด์ทั่วไปเหล่านี้ แต่วิธีนี้มีความซับซ้อนมากเมื่อใช้ EditorFor และ DropDownListFor เพื่อแสดงฟิลด์และดรอปดาวน์ ในการรับรหัสและชื่อที่ไม่ซ้ำกันเราต้องแสดงฟิลด์ด้วยคำนำหน้าโดยขึ้นอยู่กับมุมมองบางส่วนของผู้ปกครองที่แสดงผล:

    <div id="div-@(idPrefix)2" class="toHide-@(idPrefix)" style="display:none">
    <fieldset>
        <label for="@(idPrefix).Frequency">Frequency<span style="color: #660000;"> *</span></label>

        <input name="@(idPrefix).Frequency"
               id="@(idPrefix)_Frequency"
               style="width: 50%;"
               type="text"
               value="@(defaultTimePoint.Frequency)"
               data-bind="value: viewState.@(viewStatePrefix).RecurringTimepoints.Frequency"
               data-val="true"
               data-val-required="The Frequency field is required."
               data-val-number="The field Frequency must be a number."
               data-val-range-min="1"
               data-val-range-max="24"
               data-val-range="The field Frequency must be between 1 and 24."
               data-val-ignore="true"/>

        @Html.ValidationMessage(idPrefix + ".Frequency")

        ... etc

    </fieldset>
</div>

สิ่งนี้ค่อนข้างน่าเกลียดดังนั้นเราจึงตัดสินใจใช้เทมเพลตแก้ไขแทนซึ่งใช้งานได้ดีกว่ามาก เราเพิ่มโมเดลมุมมองใหม่พร้อมฟิลด์ทั่วไปเพิ่มเทมเพลตแก้ไขที่ตรงกันและแสดงฟิลด์โดยใช้เทมเพลตแก้ไขจากมุมมองพาเรนต์ที่แตกต่างกัน เทมเพลต Editor อย่างถูกต้องแสดงรหัสและชื่อ

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


1
ผมมีปัญหาที่คล้ายกันโดยใช้แท็บและจบลงด้วยการใช้สตีฟ Sanderson ของ BeginCollectionItem ซึ่งจะสร้างรหัสการควบคุมที่ไม่ซ้ำกันสำหรับคุณ: blog.stevensanderson.com/2010/01/28/...
Wilky

1

ใช้_partialวิธีการดูหาก:

  1. ดู Centric Logic
  2. สิ่งที่ต้องเก็บ_partialมุมมอง HTML ที่เกี่ยวข้องทั้งหมดไว้ในมุมมองนี้เท่านั้น ในวิธีเทมเพลตคุณจะต้องเก็บ HTML บางส่วนไว้นอกมุมมองเทมเพลตเช่น "ส่วนหัวหลักหรือเส้นขอบ / การตั้งค่าภายนอกใด ๆ
  3. ต้องการที่จะทำให้มุมมองบางส่วนกับตรรกะ (จากตัวควบคุม) URL.Action("action","controller")โดยใช้

เหตุผลที่ใช้เทมเพลต:

  1. ForEach(Iterator)ต้องการลบ เทมเพลตเพียงพอที่จะระบุ Model เป็นชนิดรายการ มันจะทำมันโดยอัตโนมัติ
  2. ตัวแบบ Centric Logic หากพบหลายมุมมองในโฟลเดอร์ displayfor เดียวกันนั้นการเรนเดอร์จะขึ้นอยู่กับ Passed Model

1

ความแตกต่างอีกอย่างที่ยังไม่ได้กล่าวถึงก็คือมุมมองบางส่วนไม่ได้เพิ่มคำนำหน้าแบบในขณะที่แม่แบบทำ นี่คือปัญหา

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