MVVM ไม่มีจุดหมายหรือไม่? [ปิด]


91

การใช้ MVVM แบบดั้งเดิมนั้นไม่มีจุดหมายหรือไม่? ฉันกำลังสร้างแอปพลิเคชันใหม่และฉันพิจารณา Windows Forms และ WPF ฉันเลือก WPF เพราะเป็นหลักฐานในอนาคตและมีความยืดหยุ่นมากมาย มีโค้ดน้อยลงและทำการเปลี่ยนแปลงที่สำคัญกับ UI ของคุณได้ง่ายขึ้นโดยใช้ XAML

เนื่องจากตัวเลือกสำหรับ WPF นั้นชัดเจนฉันจึงคิดว่าฉันสามารถไปได้ทุกทางโดยใช้ MVVM เป็นสถาปัตยกรรมแอปพลิเคชันของฉันเนื่องจากมีความสามารถในการผสมผสานความกังวลในการแยกและการทดสอบหน่วย ในทางทฤษฎีดูเหมือนว่าจะสวยงามเหมือนจอกศักดิ์สิทธิ์ของการเขียนโปรแกรม UI การผจญภัยสั้น ๆ นี้ อย่างไรก็ตามได้กลายเป็นอาการปวดหัวอย่างแท้จริง ตามที่คาดไว้ในทางปฏิบัติฉันพบว่าฉันได้แลกเปลี่ยนปัญหาหนึ่งสำหรับอีกปัญหาหนึ่ง ฉันมักจะเป็นโปรแกรมเมอร์ที่หมกมุ่นอยู่กับการที่ฉันต้องการทำสิ่งต่างๆให้ถูกต้องเพื่อที่ฉันจะได้ผลลัพธ์ที่ถูกต้องและอาจจะกลายเป็นโปรแกรมเมอร์ที่เก่งขึ้น รูปแบบ MVVM ทำให้การทดสอบประสิทธิภาพการทำงานของฉันล้มเหลวและเพิ่งกลายเป็นการแฮ็กที่ยิ่งใหญ่!

กรณีที่ชัดเจนคือการเพิ่มการสนับสนุนสำหรับกล่องโต้ตอบ Modal วิธีที่ถูกต้องคือวางกล่องโต้ตอบและผูกเข้ากับโมเดลมุมมอง การทำงานนี้เป็นเรื่องยาก เพื่อให้ได้รับประโยชน์จากรูปแบบ MVVM คุณต้องแจกจ่ายโค้ดในหลาย ๆ ที่ตลอดทั้งเลเยอร์ของแอปพลิเคชันของคุณ คุณยังต้องใช้โครงสร้างการเขียนโปรแกรมที่ลึกลับเช่นเทมเพลตและนิพจน์ lamba สิ่งที่ทำให้คุณจ้องหน้าจอเกาหัว สิ่งนี้ทำให้การบำรุงรักษาและการแก้จุดบกพร่องเป็นฝันร้ายที่รอให้เกิดขึ้นเมื่อฉันเพิ่งค้นพบ ฉันมีกล่องโต้ตอบเกี่ยวกับการทำงานที่ดีจนกระทั่งฉันได้รับข้อยกเว้นในครั้งที่สองที่ฉันเรียกมันโดยบอกว่ามันไม่สามารถแสดงกล่องโต้ตอบได้อีกเมื่อปิดแล้ว ฉันต้องเพิ่มตัวจัดการเหตุการณ์สำหรับฟังก์ชันปิดหน้าต่างโต้ตอบ อีกอันหนึ่งในการใช้งาน IDialogView และสุดท้ายอีกอันใน IDialogViewModel ฉันคิดว่า MVVM จะช่วยเราจากการแฮ็กเกอร์ที่ฟุ่มเฟือยเช่นนี้!

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

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


8
ฉันตั้งคำถามมาตลอดว่า MVVM นั้นเกินวิศวกรรมหรือไม่ คำถามที่น่าสนใจ
Taylor Leese

12
รูปแบบเช่น MVVM และ MVC ดูเหมือนว่าจะทำงานหนักเกินไปจนกว่าคุณจะต้องทำการปรับเปลี่ยนบางอย่างหรือเปลี่ยนส่วนประกอบ ครั้งแรกที่ต้องทำพิธีทั้งหมดจ่ายเอง
Robert Harvey

42
Lambdas เป็นความลับ? ข่าวกับฉัน
Ray Booysen

6
@ เรย์ - ฮาฮา +1 คอมเม้นท์นั้น! : D
Venemo

8
ดังที่ Alan Cooper ได้ชี้ให้เห็นเมื่อสิบปีก่อนในAbout Faceหากคุณกำลังออกแบบ UI และกล่องโต้ตอบโมดอลไม่ใช่กรณีที่สำคัญคุณอาจทำอะไรผิด
Robert Rossney

คำตอบ:


61

ขอโทษด้วยถ้าคำตอบของฉันสั้นไปหน่อย แต่อย่าโทษฉัน! คำถามของคุณก็ยาวเช่นกัน

โดยสรุป MVVM ไม่ได้ไร้จุดหมาย

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

ใช่มันเป็นอย่างแท้จริง
อย่างไรก็ตาม MVVM มีวิธีแยกลักษณะที่ปรากฏของ UI ออกจากตรรกะ ไม่มีใครบังคับให้คุณใช้มันทุกที่และไม่มีใครถือปืนแนบหน้าผากของคุณเพื่อให้คุณสร้าง ViewModel แยกต่างหากสำหรับทุกสิ่ง

นี่คือวิธีแก้ปัญหาของฉันสำหรับตัวอย่างนี้:
วิธีที่ UI จัดการอินพุตบางอย่างไม่ใช่ธุรกิจของ ViewModel ฉันจะเพิ่มโค้ดลงในไฟล์. xaml.cs ของ View ซึ่งสร้างอินสแตนซ์กล่องโต้ตอบและตั้งค่าอินสแตนซ์ ViewModel เดียวกัน (หรืออย่างอื่นถ้าจำเป็น) เป็น DataContext

เพื่อให้ได้รับประโยชน์จากรูปแบบ MVVM คุณต้องแจกจ่ายโค้ดในหลาย ๆ ที่ตลอดทั้งเลเยอร์ของแอปพลิเคชันของคุณ คุณยังต้องใช้โครงสร้างการเขียนโปรแกรมที่ลึกลับเช่นเทมเพลตและนิพจน์ lamba

คุณไม่จำเป็นต้องใช้มันในหลาย ๆ ที่ นี่คือวิธีที่ฉันจะแก้ไข:

  • เพิ่ม XAML ลงใน View และไม่มีอะไรใน. xaml.cs
  • เขียนตรรกะของแอปทุกตัว (ยกเว้นสิ่งที่จะทำงานกับองค์ประกอบ UI โดยตรง) ภายใน ViewModel
  • โค้ดทั้งหมดที่ UI ควรทำ แต่ไม่มีส่วนเกี่ยวข้องกับตรรกะทางธุรกิจจะไปอยู่ในไฟล์. xaml.cs

ฉันคิดว่าจุดประสงค์ของ MVVM คือการแยกตรรกะของแอปพลิเคชันและ UI ที่เป็นรูปธรรมเป็นหลักดังนั้นจึงทำให้สามารถปรับเปลี่ยน UI ได้ง่าย (หรือเปลี่ยนใหม่ทั้งหมด)
ฉันใช้หลักการต่อไปนี้: View สามารถรู้และสมมติว่าต้องการอะไรจาก ViewModel แต่ ViewModel สามารถรู้ว่าไม่มีอะไรเกี่ยวกับ View
WPF มีรูปแบบการผูกที่ดีซึ่งคุณสามารถใช้เพื่อให้บรรลุสิ่งนั้น

(BTW เทมเพลตและนิพจน์แลมบ์ดาไม่ใช่เรื่องลึกลับหากใช้อย่างถูกต้อง แต่ถ้าคุณไม่ต้องการอย่าใช้มัน)

สิ่งที่ทำให้คุณจ้องหน้าจอเกาหัว

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

ฉันมีกล่องทำงานได้ดี ...

ทำไมคุณต้องใส่ ViewModel ไว้ด้านหลังกล่องเกี่ยวกับ? ไม่มีประเด็นในนั้น

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

ใช่เนื่องจากความจริงที่ว่าองค์ประกอบ UI อยู่ในหน้าต่างเดียวกันหรือหน้าต่างอื่นหรือกำลังโคจรรอบดาวอังคารในขณะนี้ไม่ใช่เรื่องที่น่ากังวลของ ViewModels
การแยกความกังวล

แก้ไข:

นี่เป็นวิดีโอที่ดีมากในเรื่องของการที่เป็นสร้างกรอบ MVVM ของคุณเอง น่าชมมากครับ


3
+1 สำหรับสามคำสุดท้าย แต่คำตอบที่เหลือก็ดีเช่นกัน :)
Robert Harvey

13
+1 สำหรับคำแนะนำเกี่ยวกับการใช้ code-behind เป็นความเข้าใจผิดทั่วไปว่าการใช้โค้ดเบื้องหลังใน MVVM นั้น "ไม่ดี" ... แต่สำหรับสิ่งที่เกี่ยวข้องกับ UI ล้วนๆนั่นคือหนทางที่จะไป
Thomas Levesque

1
@ โทมัส: ใช่ฉันไม่เห็นด้วยมากกว่านี้ ฉันเคยเห็นการใช้งานหลายอย่างที่ผู้คนใส่โค้ดทั้งหมด (แม้กระทั่งที่เกี่ยวข้องกับ UI) ลงใน ViewModel เพราะ (ตามนั้น) "นั่นคือที่ที่โค้ด" มันค่อนข้างแฮ็ค
Venemo

4
@Venemo ฉันคิดว่าคุณสามารถห่อหุ้มสิ่งต่างๆมากมายที่คุณต้องการใส่ไว้ในโค้ดด้านหลังโดยใช้เทคนิคเช่นพฤติกรรมที่กำหนดเองซึ่งมีประโยชน์หากคุณพบว่าตัวเองเขียนโค้ดกาวซ้ำ ๆ โดยทั่วไปแล้วฉันคิดว่าการใช้โค้ดข้างหลังเป็นกาวดีกว่าการแฮ็ก XAML ที่น่าอึดอัดใจ ความกังวลหลักในใจของฉันคือการทำให้แน่ใจว่าไม่มีอะไรอยู่เบื้องหลังโค้ดที่ซับซ้อนเพียงพอที่จะรับประกันการทดสอบหน่วย สิ่งใดที่ซับซ้อนเพียงพอจะดีกว่าการห่อหุ้มใน ViewModel หรือคลาสส่วนขยายเช่น Behavior หรือ MarkupExtension
Dan Bryant

8
@ Thomas: คุณพูดถูกแล้วตำนานที่ยิ่งใหญ่ที่สุดเกี่ยวกับ MVVM คือจุดประสงค์ของ MVVM คือการกำจัดโค้ดที่อยู่เบื้องหลัง จุดประสงค์คือเพื่อเอา ​​ocde ที่ไม่ใช่ UI ออกจากโค้ดที่อยู่เบื้องหลัง การใส่รหัสเฉพาะ UI ใน ViewModel นั้นไม่ดีพอ ๆ กับการใส่รหัสโดเมนที่เป็นปัญหาในโค้ดด้านหลัง
Jim Reineri

8

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

สำหรับกล่องโต้ตอบโมดอลธรรมดา? คุณกำลังทำบางอย่างผิดปกติ - การติดตั้ง MVVM ไม่จำเป็นต้องซับซ้อนขนาดนั้น

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

MVVM, MVC, Document-View ฯลฯ เป็นรูปแบบตระกูลเก่า .. มีข้อบกพร่อง แต่ไม่มีข้อบกพร่องร้ายแรงแบบที่คุณอธิบาย


5

ฉันอยู่ระหว่างการพัฒนา MVVM ที่ค่อนข้างซับซ้อนโดยใช้ PRISM ดังนั้นฉันจึงต้องรับมือกับความกังวลประเภทนี้อยู่แล้ว

ข้อสรุปส่วนตัวของฉัน:

MVVM กับ MVC / PopUps & co

  • MVVM เป็นรูปแบบที่ยอดเยี่ยมจริงๆและในกรณีส่วนใหญ่มันแทนที่ MVC อย่างสมบูรณ์ด้วยการผูกข้อมูลที่ทรงพลังใน WPF
  • การเรียกชั้นบริการของคุณโดยตรงจากผู้นำเสนอเป็นการใช้งานที่ถูกต้องในกรณีส่วนใหญ่
  • แม้แต่สถานการณ์รายการ / รายละเอียดที่ค่อนข้างซับซ้อนก็สามารถนำมาใช้โดย MVVM แท้ได้ด้วยไวยากรณ์ {Binding Path = /}
  • อย่างไรก็ตามเมื่อต้องใช้การประสานงานที่ซับซ้อนระหว่างมุมมองหลาย ๆ มุมมองผู้ควบคุมจะได้รับคำสั่ง
  • อาจใช้เหตุการณ์; รูปแบบเก่าซึ่งหมายถึงการจัดเก็บอินสแตนซ์ IView (หรือ AbstractObserver) ในคอนโทรลเลอร์นั้นล้าสมัย
  • ตัวควบคุมสามารถฉีดในแต่ละผู้นำเสนอโดยคอนเทนเนอร์ IOC
  • บริการ IEventAggregator ของ Prism เป็นอีกวิธีหนึ่งที่เป็นไปได้หากการใช้คอนโทรลเลอร์เพียงอย่างเดียวคือการจัดส่งเหตุการณ์ (ในกรณีนี้สามารถแทนที่คอนโทรลเลอร์ได้ทั้งหมด)
  • หากต้องสร้างมุมมองแบบไดนามิกนี่เป็นงานที่เหมาะสมอย่างยิ่งสำหรับคอนโทรลเลอร์ (ในปริซึมคอนโทรลเลอร์จะได้รับการแทรก (IOC) เป็น IRegionManager)
  • กล่องโต้ตอบโมดอลส่วนใหญ่ล้าสมัยในแอปพลิเคชันคอมโพสิตสมัยใหม่ยกเว้นการดำเนินการปิดกั้นจริงๆเช่นการยืนยันที่จำเป็น ในกรณีเหล่านี้การเปิดใช้งานโมดอลสามารถสรุปเป็นบริการที่เรียกว่าภายในคอนโทรลเลอร์และดำเนินการโดยคลาสพิเศษซึ่งช่วยให้สามารถทดสอบหน่วยระดับการนำเสนอขั้นสูงได้ ตัวอย่างเช่นคอนโทรลเลอร์จะเรียก IConfirmationService.RequestConfirmation (“ คุณแน่ใจหรือไม่”) ซึ่งจะทริกเกอร์การแสดงไดอะล็อกโมดอลที่รันไทม์และสามารถล้อเลียนได้อย่างง่ายดายในระหว่างการทดสอบหน่วย

5

ฉันจัดการกับปัญหาไดอะล็อกโดยการโกง MainWindow ของฉันใช้อินเทอร์เฟซ IWindowServices ที่แสดงกล่องโต้ตอบเฉพาะแอปพลิเคชันทั้งหมด ViewModels อื่น ๆ ของฉันสามารถนำเข้าอินเทอร์เฟซบริการ (ฉันใช้ MEF แต่คุณสามารถส่งอินเทอร์เฟซผ่านตัวสร้างด้วยตนเองได้อย่างง่ายดาย) และใช้เพื่อทำสิ่งที่จำเป็นให้สำเร็จ ตัวอย่างเช่นนี่คือลักษณะของอินเทอร์เฟซสำหรับแอปพลิเคชั่นยูทิลิตี้เล็ก ๆ ของฉัน:

//Wrapper interface for dialog functionality to allow for mocking during tests
public interface IWindowServices
{
    bool ExecuteNewProject(NewProjectViewModel model);

    bool ExecuteImportSymbols(ImportSymbolsViewModel model);

    bool ExecuteOpenDialog(OpenFileDialog dialog);

    bool ExecuteSaveDialog(SaveFileDialog dialog);

    bool ExecuteWarningConfirmation(string text, string caption);

    void ExitApplication();
}

สิ่งนี้ทำให้การดำเนินการ Dialog ทั้งหมดรวมอยู่ในที่เดียวและสามารถแยกออกได้อย่างง่ายดายสำหรับการทดสอบหน่วย ฉันทำตามรูปแบบที่ไคลเอนต์ของกล่องโต้ตอบมีเพื่อสร้าง ViewModel ที่เหมาะสมซึ่งพวกเขาสามารถกำหนดค่าได้ตามต้องการ Execute call block และหลังจากนั้นไคลเอนต์สามารถดูเนื้อหาของ ViewModel เพื่อดูผลลัพธ์ของไดอะล็อก

การออกแบบ MVVM ที่ 'บริสุทธิ์กว่า' อาจมีความสำคัญสำหรับแอปพลิเคชันขนาดใหญ่ซึ่งคุณต้องมีฉนวนกันความร้อนที่สะอาดขึ้นและองค์ประกอบที่ซับซ้อนมากขึ้น แต่สำหรับแอปขนาดเล็กถึงขนาดกลางฉันคิดว่าแนวทางที่ใช้ได้จริงพร้อมบริการที่เหมาะสมในการเปิดเผยขอเกี่ยวที่ต้องการนั้นค่อนข้างเพียงพอ .


แต่คุณเรียกมันว่าที่ไหน? จะดีกว่าไหมหากสร้างไดอะล็อกภายในฟังก์ชันของคลาส IWindowServices แทนที่จะส่งผ่านไปด้วยวิธีนี้มุมมองโมเดลการโทรจะไม่ต้องรู้อะไรเกี่ยวกับการใช้งานไดอะล็อกโดยเฉพาะ
Joel Rodgers

อินเทอร์เฟซถูกแทรกลงในอินสแตนซ์ ViewModel ของฉันที่ต้องการเข้าถึงกล่องโต้ตอบแอปพลิเคชัน ในกรณีส่วนใหญ่ฉันกำลังส่ง ViewModel สำหรับกล่องโต้ตอบ แต่ฉันรู้สึกขี้เกียจเล็กน้อยและใช้ WPF OpenFileDialog และ SaveFileDialog สำหรับการเรียกไฟล์โต้ตอบ เป้าหมายหลักของฉันคือการแยกเพื่อวัตถุประสงค์ในการทดสอบหน่วยดังนั้นสิ่งนี้เพียงพอสำหรับเป้าหมายนั้น หากคุณต้องการการแยกที่ดีขึ้นคุณอาจต้องการสร้าง OpenFileViewModel และ SaveFileViewModel ซึ่งจะทำซ้ำคุณสมบัติที่จำเป็นสำหรับกล่องโต้ตอบ
Dan Bryant

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

5

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

รูปแบบการออกแบบไม่เคยตั้งใจที่จะปฏิบัติตามอย่างเคร่งครัด


2
แก้ไข. กล่องที่เรียบง่ายควรเรียบง่าย แต่ถ้าคุณต้องแสดงข้อมูลเช่นเวอร์ชันการออกใบอนุญาตกระบวนการทำงานชื่อ บริษัท ฯลฯ นี่คือข้อมูลทั้งหมดที่มีอยู่ที่ไหนสักแห่ง ในรูปแบบมาตรฐานคุณสามารถผูกข้อมูลทั้งหมดและดำเนินการกับข้อมูลนั้นได้ MVVM บอกว่าคุณควรสร้างแบบจำลองการดูซึ่งซ้ำซ้อน
ATL_DEV

1

เนื่องจากรูปแบบของ MVVM นั้นยอดเยี่ยมมาก แต่ไลบรารีควบคุมของ WPF ที่มาพร้อมกับการสนับสนุนการผูกข้อมูล NET 4.0 นั้นมีข้อ จำกัด มากมันดีกว่า WinForm มาก แต่ก็ยังไม่เพียงพอสำหรับ MVVM ที่ผูกได้ฉันจะบอกว่ามันมีพลังงานประมาณ 30% ของสิ่งที่จำเป็นสำหรับ MVVM แบบผูกได้
Bindable MVVM: เป็น UI ที่ ViewModel เชื่อมต่อกับ View โดยใช้การผูกข้อมูลเท่านั้น
รูปแบบ MVVM เกี่ยวกับการแสดงออบเจ็กต์ของ ViewState แต่ไม่ได้อธิบายถึงวิธีที่คุณรักษาการซิงค์ระหว่าง View และ ViewModel ใน WPF เป็นการผูกข้อมูล แต่สามารถเป็นอะไรก็ได้ และจริงๆแล้วคุณสามารถใช้รูปแบบ MVVM ในชุดเครื่องมือ UI ใดก็ได้ที่รองรับ events \ callbacks คุณสามารถใช้มันใน WinAPI ใน WinForms (ฉันทำแล้วและมันใช้งานกับ events \ callbacks ไม่ได้มากขึ้น) และคุณยังสามารถใช้ใน Text คอนโซลเช่นเขียน Norton Commander ของ DoS ใหม่โดยใช้รูปแบบ MVVM

กล่าวโดยย่อ: MVVM ไม่ได้ไร้จุดหมายมันยอดเยี่ยมมาก ไลบรารีควบคุมของ NET 4.0 WPF เป็นถังขยะ

นี่คือหลักฐานง่ายๆของแนวคิด ViewModel ซึ่งคุณไม่สามารถผูกข้อมูลในลักษณะ MVVM บริสุทธิ์โดยใช้ WPF

public class PersonsViewModel
{
    public IList<Person> PersonList;
    public IList<ColumnDescription> TableColumns;
    public IList<Person> SelectedPersons;
    public Person ActivePerson;
    public ColumnDescription SortedColumn;
}

คุณไม่สามารถผูกข้อมูลส่วนหัวคอลัมน์ DataGrid ของ WPF คุณไม่สามารถผูกข้อมูลแถวที่เลือก ฯลฯ ได้คุณจะทำด้วยวิธีง่ายๆในโค้ดหรือเขียนโค้ดแฮ็ค XAML 200 บรรทัดสำหรับ ViewModel ที่ง่ายที่สุด 5 บรรทัดเหล่านี้ คุณสามารถจินตนาการได้ว่าสิ่งต่าง ๆ เลวร้ายลงอย่างไรด้วย ViewModels ที่ซับซ้อน
ดังนั้นคำตอบจึงเรียบง่ายเว้นแต่คุณจะเขียนแอปพลิเคชัน Hello World การใช้ MVVM แบบผูกได้ใน WPF นั้นไม่มีจุดหมาย คุณจะใช้เวลาส่วนใหญ่ไปกับการแฮ็กเพื่อผูก ViewModel ของคุณ การผูกข้อมูลเป็นสิ่งที่ดี แต่พร้อมที่จะเปลี่ยนกลับเป็น 70% ของเวลาของเหตุการณ์


คุณสามารถผูกสิ่งนี้กับตัวแปลงเข้ากับ DataGrid
Cameron MacFarland

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

ฉันยอมรับว่าฉันไม่มีประสบการณ์ในการใช้ WPF DataGrid มากนัก ฉันมักจะหลีกเลี่ยงเพราะมันน่าเกลียดและไม่เหมาะกับ WPF อีกต่อไป ต้องบอกว่าการรวมกันของตัวแปลงและคุณสมบัติที่แนบมาเพื่อจัดการกับเหตุการณ์ต่างๆจะทำให้คุณได้รับสิ่งที่คุณต้องการ
Cameron MacFarland

1
อเล็กซ์ปัญหาที่คุณพบคือการออกแบบ DataGrid ไม่ใช่กับ MVVM เป็นเรื่องที่ไม่ถูกต้องที่จะพูดว่า "การผูกข้อมูลเป็นสิ่งที่ดี แต่พร้อมที่จะเปลี่ยนกลับเป็น 70% ของเวลาของกิจกรรม" ฉันได้เขียนแอพพลิเคชั่น WPF ขนาดใหญ่อย่างเป็นกลางซึ่งไม่มีตัวจัดการเหตุการณ์ใน UI แต่อย่างใดยกเว้นตัวจัดการเหตุการณ์ที่กริดข้อมูล (Telerik) ต้องการสำหรับการเริ่มต้น
Robert Rossney

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

0

ไม่มันไม่ใช่เรื่องไร้จุดหมาย แต่เป็นการยากที่จะพันศีรษะของคุณไปรอบ ๆ แม้ว่ารูปแบบนั้นจะดูเรียบง่ายอย่างน่าขันก็ตาม มีข้อมูลที่ผิดมากมายและกลุ่มต่างๆที่ต่อสู้เพื่อวิธีที่เหมาะสม ฉันคิดว่าด้วย WPF และ Silverlight คุณควรใช้ MVVM ไม่เช่นนั้นคุณจะมากกว่าการเข้ารหัสและพยายามแก้ปัญหาในรูปแบบใหม่ที่ใช้วิธีการชนะแบบ "เก่า" ซึ่งทำให้คุณมีปัญหา นี่เป็นกรณีของ Silverlight มากกว่าเนื่องจากทุกอย่างจำเป็นต้องเป็นแบบอะซิงโครนัส (แฮ็กรอบนี้เป็นไปได้ แต่คุณควรเลือกแพลตฟอร์มอื่น)

ฉันขอแนะนำให้อ่านบทความนี้การลดความซับซ้อนของ WPF TreeView โดยใช้รูปแบบ ViewModel อย่างรอบคอบเพื่อดูว่า MVVM สามารถนำไปใช้งานได้ดีและช่วยให้คุณเปลี่ยนความคิดของรูปแบบการชนะเป็นวิธีคิดใหม่ใน MVVM ในระยะสั้นเมื่อคุณต้องการทำงานให้เสร็จให้ใช้ตรรกะกับ ViewModel ก่อนไม่ใช่ View คุณต้องการเลือกรายการหรือไม่? เปลี่ยนไอคอน? อย่าทำซ้ำองค์ประกอบ UI เพียงอัปเดตคุณสมบัติของโมเดลและปล่อยให้การเชื่อมโยงข้อมูลเป็นสิ่งสำคัญ


-1

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

  • Viewมีการควบคุม GUI เฉพาะและกำหนดลักษณะของอินเทอร์เฟซผู้ใช้
  • ViewModelแสดงถึงสถานะและลักษณะการทำงานของงานนำเสนอ
  • โมเดลอาจเป็นวัตถุทางธุรกิจจากเลเยอร์โดเมนหรือบริการที่ให้ข้อมูลที่จำเป็น

แต่ที่ขาดหายไปคือ:

  • ใครเป็นผู้สร้าง ViewModels
  • ใครเป็นผู้รับผิดชอบขั้นตอนการทำงานของแอปพลิเคชัน
  • ใครเป็นสื่อกลางระหว่าง ViewModels เมื่อพวกเขาต้องการสื่อสารกัน

แนวทางของฉันคือการแนะนำ (Use-Case) Controllerซึ่งรับผิดชอบจุดที่ขาดหายไป วิธีการทำงานสามารถดูได้ที่แอปพลิเคชันตัวอย่างWPF Application Framework (WAF)


รูปแบบสื่อกลางที่ Josh Smith นำมาใช้แก้ไขปัญหาการสื่อสาร View Model ของฉันทั้งหมด Messenger.NotifyColleagues เป็นวิธีในการมีโมเดลมุมมองที่เป็นอิสระอย่างสมบูรณ์ซึ่งรู้วิธีตอบสนองต่อเหตุการณ์ทั่วโลก (หากพวกเขาใส่ใจ) โดยที่โมเดลมุมมองสองมุมมองไม่รู้เกี่ยวกัน มันช่วยเบคอนของเราได้สองสามครั้งแล้ว
JasonD
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.