MVVM เป็นตัวช่วยแบนด์สำหรับเลเยอร์การผูกข้อมูลที่ออกแบบมาไม่ดี โดยเฉพาะอย่างยิ่งมันได้เห็นการใช้งานจำนวนมากในโลก WPF / silverlight / WP7 เนื่องจากข้อ จำกัด ในการผูกข้อมูลใน WPF / XAML
จากนี้ไปฉันจะสมมติว่าเรากำลังพูดถึง WPF / XAML เพราะสิ่งนี้จะทำให้สิ่งต่าง ๆ ชัดเจนยิ่งขึ้น ให้ดูที่ข้อบกพร่องบางอย่างที่ MVVM กำหนดไว้เพื่อแก้ปัญหาใน WPF / XAML
รูปร่างข้อมูลเทียบกับรูปร่าง UI
'VM' ใน MVVM สร้างชุดของวัตถุที่กำหนดใน C # ที่แมปไปยังชุดของวัตถุนำเสนอที่กำหนดใน XAML โดยทั่วไปแล้ววัตถุ C # เหล่านี้จะเชื่อมต่อกับ XAML ผ่านคุณสมบัติ DataContext บนวัตถุการนำเสนอ
ด้วยเหตุนี้กราฟวัตถุ viewmodel จำเป็นต้องแมปลงในกราฟวัตถุการนำเสนอของแอปพลิเคชันของคุณ ไม่ได้หมายความว่าการแมปจำเป็นต้องเป็นแบบหนึ่งต่อหนึ่ง แต่ถ้าการควบคุมรายการถูกควบคุมโดยตัวควบคุมหน้าต่างจะต้องมีวิธีที่จะได้รับจากวัตถุ DataContext ของหน้าต่างไปยังวัตถุที่อธิบายข้อมูลของรายการนั้น
กราฟวัตถุ viewmodel decouples กราฟวัตถุรูปแบบจากกราฟวัตถุ ui ประสบความสำเร็จ แต่ค่าใช้จ่ายของเลเยอร์ viewmodel เพิ่มเติมที่จะต้องสร้างและบำรุงรักษา
ถ้าฉันต้องการย้ายข้อมูลบางอย่างจากหน้าจอ A ไปยังหน้าจอ B ฉันต้องยุ่งกับ viewmodels ในความคิดของนักธุรกิจนี่คือการเปลี่ยนแปลง UI มันควรจะเกิดขึ้นอย่างหมดจดในโลกของ XAML น่าเศร้าที่มันไม่สามารถทำได้ ยิ่งแย่ไปกว่านั้นขึ้นอยู่กับว่าโครงสร้างมุมมองเป็นอย่างไรและการเปลี่ยนแปลงของข้อมูลเป็นอย่างไรจำเป็นต้องมีการเปลี่ยนเส้นทางข้อมูลอีกเล็กน้อยเพื่อให้การเปลี่ยนแปลงนี้ประสบผลสำเร็จ
หลีกเลี่ยงการผูกข้อมูลที่ไม่แสดงออก
การผูก WPF / XAML นั้นไม่เพียงพอ โดยทั่วไปคุณจะต้องจัดเตรียมวิธีในการเข้าถึงวัตถุพา ธ คุณสมบัติไปยังการสำรวจและตัวแปลงการเชื่อมโยงเพื่อปรับค่าคุณสมบัติของข้อมูลให้ตรงกับสิ่งที่วัตถุการนำเสนอต้องการ
หากคุณต้องการผูกคุณสมบัติใน C # กับสิ่งที่ซับซ้อนกว่านั้นคุณก็โชคไม่ดี ฉันไม่เคยเห็นแอป WPF ที่ไม่มีตัวแปลงการผูกข้อมูลที่เปลี่ยนเป็นจริง / เท็จให้เป็น Visible / Collapsed แอป WPF หลายแห่งมีแนวโน้มที่จะมีสิ่งที่เรียกว่า NegatingVisibilityConverter หรือที่คล้ายกันซึ่งพลิกขั้ว นี่ควรเป็นการปิดระฆังปลุก
MVVM ให้แนวทางในการจัดโครงสร้างรหัส C # ของคุณที่สามารถใช้เพื่อให้ราบรื่นกับข้อ จำกัด นี้ คุณสามารถแสดงคุณสมบัติใน viewmodel ของคุณที่ชื่อว่า SomeButtonVisibility และผูกเข้ากับการมองเห็นของปุ่มนั้น XAML ของคุณสวยและน่ารักตอนนี้ ... แต่คุณทำตัวเป็นเสมียนแล้ว - ตอนนี้คุณต้องแสดง + อัปเดตการเชื่อมโยงสองแห่ง (UI และรหัสใน C #) เมื่อ UI ของคุณวิวัฒนาการ หากคุณต้องการปุ่มเดียวกันบนหน้าจออื่นคุณจะต้องแสดงคุณสมบัติที่คล้ายกันในโมเดลโมเดลที่หน้าจอนั้นสามารถเข้าถึงได้ แย่กว่านั้นฉันไม่สามารถดู XAML และดูว่าปุ่มจะปรากฏให้เห็นอีกต่อไปเมื่อใด ทันทีที่การมัดกลายเป็นเรื่องไม่สำคัญฉันต้องทำงานนักสืบในรหัส C #
การเข้าถึงข้อมูลมีการกำหนดขอบเขตอย่างจริงจัง
เนื่องจากโดยทั่วไปข้อมูลเข้าสู่ UI ผ่านคุณสมบัติ DataContext จึงเป็นการยากที่จะแสดงข้อมูลทั่วโลกหรือเซสชันอย่างสม่ำเสมอตลอดทั้งแอปของคุณ
แนวคิดของ "ผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน" เป็นตัวอย่างที่ดี - นี่คือสิ่งทั่วโลกอย่างแท้จริงในอินสแตนซ์ของแอปของคุณ ใน WPF / XAML เป็นเรื่องยากมากที่จะทำให้ผู้ใช้ปัจจุบันเข้าถึงผู้ใช้ทั่วโลกในลักษณะที่สอดคล้องกัน
สิ่งที่ฉันต้องการจะทำคือใช้คำว่า "CurrentUser" ในการผูกข้อมูลอย่างอิสระเพื่ออ้างถึงผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน แต่ฉันต้องตรวจสอบให้แน่ใจว่าDataContext ทุกตัวให้วิธีในการเข้าถึงวัตถุผู้ใช้ปัจจุบัน MVVM สามารถรองรับสิ่งนี้ได้ แต่รูปแบบการดูจะไม่เป็นระเบียบเพราะพวกเขาทั้งหมดต้องให้การเข้าถึงข้อมูลทั่วโลกนี้
ตัวอย่างที่ MVVM อยู่เหนือ
สมมติว่าเรามีรายชื่อผู้ใช้ ถัดจากผู้ใช้แต่ละคนเราต้องการแสดงปุ่ม "ลบผู้ใช้" แต่เฉพาะในกรณีที่ผู้ใช้ที่เข้าสู่ระบบในปัจจุบันเป็นผู้ดูแลระบบ นอกจากนี้ผู้ใช้จะไม่ได้รับอนุญาตให้ลบตัวเอง
วัตถุโมเดลของคุณไม่ควรรู้เกี่ยวกับผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน - พวกเขาจะแสดงระเบียนผู้ใช้ในฐานข้อมูลของคุณ แต่อย่างใดผู้ใช้ที่เข้าสู่ระบบในปัจจุบันจำเป็นต้องเปิดเผยการผูกข้อมูลภายในแถวรายการของคุณ MVVM กำหนดว่าเราควรสร้างวัตถุ viewmodel สำหรับแต่ละแถวรายการที่ประกอบด้วยผู้ใช้ที่เข้าสู่ระบบในปัจจุบันด้วยผู้ใช้ที่เป็นตัวแทนของแถวรายการนั้นจากนั้นเปิดเผยคุณสมบัติที่ชื่อว่า "DeleteButtonVisibility" หรือ "CanDelete" บนวัตถุ viewmodel เกี่ยวกับตัวแปลงผูกพัน)
วัตถุนี้กำลังจะดูน่ากลัวมากเหมือนวัตถุผู้ใช้ในวิธีอื่น ๆ ส่วนใหญ่ - มันอาจต้องสะท้อนคุณสมบัติของวัตถุแบบจำลองผู้ใช้ทั้งหมดและส่งต่อการปรับปรุงไปยังข้อมูลนั้นเมื่อมีการเปลี่ยนแปลง สิ่งนี้ให้ความรู้สึกลำบากมาก - อีกครั้ง MVVM ทำให้คุณเป็นพนักงานโดยบังคับให้คุณรักษาวัตถุที่ใช้งานได้จริงของผู้ใช้นี้
พิจารณา - คุณอาจต้องแสดงคุณสมบัติของผู้ใช้ในฐานข้อมูลแบบจำลองและมุมมอง หากคุณมี API ระหว่างคุณกับฐานข้อมูลของคุณมันแย่กว่านั้นคือมันแสดงอยู่ในฐานข้อมูลเซิร์ฟเวอร์ API ไคลเอนต์ API รุ่นและมุมมอง ฉันลังเลที่จะยอมรับรูปแบบการออกแบบที่เพิ่มเลเยอร์อื่นที่ต้องสัมผัสทุกครั้งที่มีการเพิ่มหรือเปลี่ยนแปลงคุณสมบัติ
ยิ่งแย่กว่านั้นเลเยอร์นี้จะปรับตามความซับซ้อนของ UI ของคุณไม่ใช่กับความซับซ้อนของตัวแบบข้อมูลของคุณ บ่อยครั้งที่ข้อมูลเดียวกันถูกแสดงในหลาย ๆ ที่และใน UI ของคุณ - ซึ่งไม่เพียง แต่เพิ่มเลเยอร์เท่านั้น แต่ยังเพิ่มเลเยอร์ที่มีพื้นที่พื้นผิวพิเศษมากมาย!
สิ่งต่าง ๆ จะเป็นไปได้อย่างไร
ในกรณีที่อธิบายไว้ข้างต้นฉันอยากจะบอกว่า:
<Button Visibility="{CurrentUser.IsAdmin && CurrentUser.Id != Id}" ... />
ผู้ใช้ปัจจุบันจะถูกเปิดเผยทั่วโลกกับ XAML ทั้งหมดในแอปของฉัน รหัสจะอ้างถึงคุณสมบัติใน DataContext สำหรับแถวรายการของฉัน การเปิดเผยจะแปลงจากบูลีนโดยอัตโนมัติ การอัพเดตใด ๆ กับ Id, CurrentUser.IsAdmin, CurrentUser หรือ CurrentUser.Id จะทำให้เกิดการอัปเดตการมองเห็นปุ่มนี้ ง่าย peasy
แต่ WPF / XAML บังคับให้ผู้ใช้สร้างระเบียบสมบูรณ์ เท่าที่ฉันจะบอกได้นักสร้างสรรค์บล็อกเกอร์บางคนตบชื่อเรื่องนั้นและชื่อนั้นก็คือ MVVM อย่าหลงกล - มันไม่ได้อยู่ในชั้นเรียนเดียวกันกับรูปแบบการออกแบบของ GoF นี่เป็นแฮ็คที่น่าเกลียดในการหลีกเลี่ยงระบบการเชื่อมข้อมูลที่น่าเกลียด
(บางครั้งวิธีการนี้เรียกว่า "ฟังก์ชั่นการตอบโต้การเขียนโปรแกรม" ในกรณีที่คุณกำลังมองหาการอ่านเพิ่มเติม)
สรุปแล้ว
หากคุณต้องทำงานใน WPF / XAML ฉันยังไม่แนะนำ MVVM
คุณต้องการให้โค้ดของคุณมีโครงสร้างเหมือนกับตัวอย่าง "สิ่งที่เป็นไปได้" ด้านบนจะมีโค้ด - โมเดลถูกเปิดเผยโดยตรงเพื่อดูด้วยนิพจน์การเชื่อมโยงข้อมูลที่ซับซ้อน + การบังคับค่าที่ยืดหยุ่น มันเป็นวิธีที่ดีกว่า - อ่านได้เขียนได้มากกว่าและบำรุงรักษาได้มากกว่า
MVVM บอกให้คุณจัดโครงสร้างโค้ดของคุณด้วยวิธีที่ละเอียดกว่าและบำรุงรักษาได้น้อยกว่า
แทนที่จะเป็น MVVM ให้สร้างสิ่งต่าง ๆ เพื่อช่วยให้คุณประมาณประสบการณ์ที่ดี: พัฒนาข้อตกลงสำหรับการเปิดเผยสถานะทั่วโลกให้กับ UI ของคุณอย่างสม่ำเสมอ สร้างเครื่องมือของคุณเองจากตัวผูกรวมหลายพันธะ ฯลฯ ที่ช่วยให้คุณแสดงนิพจน์ที่ซับซ้อนยิ่งขึ้น สร้างห้องสมุดตัวแปลงที่มีผลผูกพันไว้ให้ตัวเองเพื่อช่วยให้คดีข่มขู่ร่วมเจ็บปวดน้อยลง
ดียิ่งขึ้น - แทนที่ XAML ด้วยสิ่งที่แสดงออกมากขึ้น XAML เป็นรูปแบบ XML ที่ง่ายมากสำหรับการทำให้วัตถุ C # เป็นอินสแตนซ์ - มันไม่ยากที่จะเกิดขึ้นกับตัวแปรที่แสดงออกมากขึ้น
คำแนะนำอื่น ๆ ของฉัน: อย่าใช้ชุดเครื่องมือที่บังคับให้ทำสิ่งต่อไปนี้ พวกเขาจะทำร้ายคุณภาพของผลิตภัณฑ์ขั้นสุดท้ายของคุณโดยผลักดันคุณไปสู่อึอย่าง MVVM แทนที่จะมุ่งเน้นไปที่ปัญหาของคุณ