เราควรเชื่อมโยงมุมมองกับคุณสมบัติของโมเดลหรือ ViewModel ควรมีเป็นของตัวเอง .. ?


21

ฉันเริ่มต้นโครงการด้วยสภาพแวดล้อมทางเทคนิคต่อไปนี้:. Net 4.0, Entity Framework 4.0, WPF พร้อมสถาปัตยกรรม MVVM

ฉันเห็นตัวอย่างมากมายในเน็ตหนังสือบางเล่มเกี่ยวกับสภาพแวดล้อมนี้ ในตัวอย่างที่ผู้เขียนมีความคิดนี้:

  1. Viemodel จะมีตัวอย่างของคลาส Model (Entity Framework Entity เช่น Person)
  2. ผูกคอนโทรล WPF view เข้ากับคุณสมบัติของ Model

ในขณะที่ผู้เขียนบางคนทำ:

  1. Viemodel จะเปิดเผยคุณสมบัติทั้งหมดของโมเดล
  2. เชื่อมโยงคอนโทรลมุมมอง WPF กับคุณสมบัติของ ViewModel แทนที่จะเชื่อมโยงกับโมเดลโดยตรง

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


โดยส่วนตัวแล้วฉันพบว่าการเปิดเผยคุณสมบัติของโมเดลนั้นส่งผลให้มีการแยกชั้นข้อมูลและเลเยอร์ตรรกะที่ดี
Alex Hope O'Connor

คำตอบ:


25

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

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

นอกจากนี้โมเดลส่วนใหญ่จะไม่ใช้งานINotifyPropertyChangedดังนั้นจึงอาจไม่เหมาะกับเป้าหมายการรวมหากสถานะของหน้าจอเปลี่ยนไปหลังจากการแสดงเริ่มต้น

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


ฉันชอบคำตอบของคุณ +1 สำหรับการพูดถึงการแก้ไข / บันทึกหน้าจอ .. แต่มันก็น่ากลัวที่จะเขียนคุณสมบัติสองครั้ง - หนึ่งครั้งในแบบจำลองและอีกครั้งในมุมมองแบบจำลอง มันจะเพิ่มเวลาในการพัฒนา คุณคิดว่ามันสมเหตุสมผลหรือไม่ที่จะทำเช่นนั้น ... ?
Pravin Patil

9
@Pravin Patil - fwiw ทุกครั้งที่ฉันใช้ทางลัดนั้นฉันสาปแช่งตัวเองในภายหลังเมื่อฉันต้องย้อนกลับไปแก้ไข มีความพยายามเพียงเล็กน้อยในการปรับใช้คุณสมบัติอีกครั้งบน ViewModel โดยเฉพาะอย่างยิ่งหากเป็นแบบอ่านอย่างเดียว (เนื่องจากคุณสามารถใช้คุณสมบัติที่ใช้งานอัตโนมัติกับ setter ส่วนตัว) ความจริงก็คือในกรณีส่วนใหญ่ Model เป็นโครงสร้างข้อมูลที่แตกต่างจาก ViewModel ปล่อยให้ตัวเองมีความยืดหยุ่นในการเปลี่ยนรุ่นโดยไม่ส่งผลกระทบต่อมุมมอง ยิ่งคุณต้องเปลี่ยนมุมมองให้น้อยเท่าไหร่ก็ยิ่งดีขึ้นเท่านั้นเพราะมุมมองนั้นยากที่จะทดสอบ
Scott Whitlock

4
@Scott Whitlock: ฉันได้พัฒนาแอพพลิเคชั่น WPF กับ NHibernate มาสองปีแล้วและไม่เคยมีปัญหาใด ๆ เลยที่จะผูกเข้ากับโมเดลโดยตรง ในความเป็นจริงเมื่อคุณสมบัติของโมเดลเปลี่ยนไปส่วนใหญ่จะเป็นความพยายามเดียวกันสำหรับการเปลี่ยนแปลงโดยไม่คำนึงถึงสิ่งที่คุณผูกไว้ และเมื่อฉันต้องทำการกำหนดเส้นทางบางอย่างใน ViewModel เองในภายหลังมันก็ไม่คุ้มค่าที่จะลงทุนเวลาก่อนที่ฉันจะต้องการมัน ฉันทำตามแนวทางของ YAGNI (ยัง) และไม่มีปัญหา ฉันคิดว่าคุณและคนอื่น ๆ ที่อยู่ที่นี่เป็นคนดื้อรั้นเล็กน้อยเกี่ยวกับปัญหานี้
Falcon

16

จุดของการให้คือว่ามันเป็นรูปแบบของการViewModelView

คุณควรจะผูกพันViewModelกับView, ไม่ใช่Modelคุณสมบัติใด ๆ(ไม่ใช่โดยตรงเลย)


8

ฉันพบว่าทั้งสองวิธียอมรับได้

การเชื่อมโยงกับ ViewModel เท่านั้นเป็นวิธีการ "MVVM-purist" และนำไปสู่การแยกที่ดีขึ้นระหว่างเลเยอร์ การผูกเข้ากับโมเดลมักจะรวดเร็วและสะดวกยิ่งขึ้น

ยกเว้นว่าฉันมีเหตุผลที่ดีในการแยกเลเยอร์ (ขนาดของโครงการความกังวลเกี่ยวกับการบำรุงรักษาในอนาคตประเภทของโมเดลที่ฉันทำงานด้วย ฯลฯ ) ฉันผูกเข้ากับโมเดล


7

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

รหัสหลอก:

 {Binding: MyViewModel.MyModel.Name}

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

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

ตอนนี้สิ่งนี้สามารถลดลงได้ในบางสถานการณ์หากโมเดลของคุณใช้อินเตอร์เฟส ดังนั้นหากอินเทอร์เฟซมี IBaseDetails ซึ่งเปิดเผยคุณสมบัติ ModuleName แล้วคุณสามารถ:

รหัสหลอก:

 {Binding: MyViewModel.MyModel.ModuleName}

ตราบใดที่นางแบบที่คุณพอใจกับอินเตอร์เฟส IBaseDetails ทองคำของคุณให้ระวังไว้ว่านี่เป็นเคสที่ขอบและโดยทั่วไปแล้วคุณจะ 90% ดีกว่าเสมอที่จะรวมโมเดลมุมมองของคุณไว้กับโมเดลใด ๆ


2

หากคุณเห็นความเสียดทานมากมายจาก Model -> ViewModel ลองใช้ AutoMapper มันจะลบความน่าเบื่อที่เกี่ยวข้องกับคุณสมบัติการคัดลอกด้วยตนเอง


1

ฉันมาถึงที่นี่เพียงเพราะฉันมีข้อสงสัยเหมือนกันและฉันก็มั่นใจว่าฉันจะผูกมัดเพื่อดูโมเดลแทนที่จะเป็นนางแบบ

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

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

เช่นเดียวกันอาจเป็นการปรับปรุงโมเดลในกรณีของการบันทึก / ยกเลิกไม่มีสิ่งใดสะอาดขึ้น


โพสต์นี้ค่อนข้างอ่านยาก (ผนังข้อความ) คุณจะช่วยแก้ไขมันให้เป็นรูปร่างที่ดีขึ้นได้ไหม
ริ้น

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