ViewModel หรือ Model ใน MVVM ควรใช้ INotifyPropertyChanged หรือไม่


165

ส่วนใหญ่ตัวอย่าง MVVM ฉันได้ทำงานผ่านได้มีรุ่นใช้ INotifyPropertyChangedแต่ในจอชสมิ ธ CommandSink ตัวอย่าง ดำเนิน ViewModelINotifyPropertyChanged

ฉันยังคงรวบรวมแนวความคิด MVVM เข้าด้วยกันอย่างมีสติดังนั้นฉันไม่รู้ว่า:

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

อะไรคือประสบการณ์ของผู้อื่นในโครงการ MVVM ที่คุณได้ทำ?


4
หากคุณติดตั้ง INPC ให้ลองgithub.com/Fody/Propertyลองเปลี่ยนมันจะช่วยให้คุณประหยัดเวลาในการพิมพ์เป็นสัปดาห์
— คนเจ้าเล่ห์ CAD

คำตอบ:


104

ฉันจะบอกว่าค่อนข้างตรงข้ามฉันมักจะใส่INotifyPropertyChangedViewModel ของฉันไว้ - คุณไม่ต้องการที่จะสร้างมลพิษให้กับแบบจำลองของคุณด้วยฟีเจอร์เฉพาะอย่าง WPF อย่างเช่นINotifyPropertyChangedสิ่งที่ควรนั่งใน ViewModel

ฉันแน่ใจว่าคนอื่นจะไม่เห็นด้วย แต่นั่นเป็นวิธีที่ฉันทำงาน


84
คุณจะทำอย่างไรถ้ามีการเปลี่ยนแปลงคุณสมบัติในโมเดล? คุณต้องนำมันไปใช้กับโมเดลมุมมอง คำถามที่ซื่อสัตย์ฉันจัดการกับปริศนานี้ในขณะนี้
— Roger Lipscombe

4
EventAggregator ในรหัส Prism เป็นทางเลือกที่ดีในการ INotifyPropertyChanged ในรูปแบบด้วยคุณสมบัติที่กำหนดเองเปลี่ยนประเภทเหตุการณ์ รหัสเหตุการณ์ในโครงการดังกล่าวสนับสนุนการส่งต่อเหตุการณ์ระหว่างพื้นหลังและเธรด UI ซึ่งบางครั้งอาจมีปัญหา
— Steve Mitcham

51
INotifyProperyChanged ไม่ได้เป็น WPF เฉพาะมันอาศัยอยู่ใน System.ComponentModel namespace ฉันได้ใช้มันในแอปพลิเคชัน WinForms และ INotifyPropertyChanged ได้อยู่ใน. Net ตั้งแต่ 2.0, WPF มีเพียงประมาณ 3.0
— benPearce

40
ฉันเป็นแฟนตัวยงของ INotifyProperty เปลี่ยนแปลงทั้งใน MODEL และ VIEWMODEL ฉันไม่สามารถคิดเหตุผลที่จะไม่ทำเช่นนี้ มันเป็นวิธีที่สวยงามในการแจ้ง VIEWMODEL เมื่อการเปลี่ยนแปลงพื้นหลังเกิดขึ้นใน MODE ของคุณที่ส่งผลกระทบต่อ VIEWMODEL เช่นเดียวกับที่ใช้เพื่อแจ้ง VIEWMODEL และมีการเปลี่ยนแปลง VIEWMODEL
— ScottCher

6
@Steve - เกี่ยวกับการแจ้งให้ ViewModel ทราบว่าคุณสมบัติของ Model มีการเปลี่ยนแปลงดูเหมือนว่า INotifyPropertyChanged จะทำงานได้ดีเนื่องจาก "เหตุการณ์ที่ viewmodel สามารถเชื่อมต่อได้" ทำไมไม่ใช้มัน?
— skybluecodeflier

146

INotifyPropertyChangedผมเห็นด้วยอย่างยิ่งกับแนวคิดที่ว่ารุ่นไม่ควรดำเนินการ อินเทอร์เฟซนี้ไม่ได้เฉพาะ UI! เพียงแจ้งการเปลี่ยนแปลง อันที่จริง WPF ใช้สิ่งนี้อย่างหนักเพื่อระบุการเปลี่ยนแปลง แต่นั่นไม่ได้หมายความว่ามันเป็นส่วนต่อประสาน UI ฉันจะเปรียบเทียบกับความคิดเห็นต่อไปนี้: " ยางเป็นอุปกรณ์เสริมในรถยนต์ " แน่นอนว่ามันเป็น แต่จักรยานรถโดยสาร ฯลฯ ก็ใช้เช่นกัน โดยสรุปอย่าใช้ส่วนต่อประสานนั้นเป็นสิ่งที่ UI

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

อย่างไรก็ตามมีวิธีต่าง ๆ ในการบรรลุสิ่งต่าง ๆ แต่ฉันมักจะเถียงในความเรียบง่ายและหลีกเลี่ยงความซ้ำซ้อน

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

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

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

ฉันหวังว่าฉันจะมีเวลามากขึ้นในการอธิบาย MVVM ที่หลากหลายและวิธีการแก้ปัญหาที่พบบ่อยซึ่งส่วนใหญ่จัดทำโดยนักพัฒนารายอื่น แต่ฉันคิดว่าฉันจะต้องทำอีกครั้ง


7
คิดแบบนี้ หากคุณในฐานะนักพัฒนาใช้. dll ที่มีนางแบบในตัวคุณคุณจะไม่ต้องเขียนใหม่เพื่อรองรับ INotifyPropertyChanged
— Lee Treveil

2
เห็นด้วยอย่างยิ่งกับคุณ เช่นเดียวกับคุณคุณอาจจะยินดีที่พบว่าเอกสาร MVVM อย่างเป็นทางการ < msdn.microsoft.com/en-us/library/gg405484%28v=pandp.40%29.aspx > (ส่วนรุ่น) เห็นด้วยกับเรา :-)
— Noldorin

"อย่างไรก็ตามวิธีต่าง ๆ ของการบรรลุสิ่งต่าง ๆ แต่ฉันมักจะเถียงในความเรียบง่ายและหลีกเลี่ยงความซ้ำซ้อน" สำคัญมาก.
— Bastien Vandamme

1
INotifyPropertyChangedเป็นส่วนหนึ่งของSystem.ComponentModelเนมสเปซซึ่งมีไว้สำหรับ "ลักษณะการทำงานในขณะใช้งานและเวลาออกแบบของส่วนประกอบและตัวควบคุม " ห้ามใช้ INotifyPropertyChangedในรุ่นต่างๆเพียงใน ViewModels เชื่อมโยงไปยังเอกสาร: docs.microsoft.com/en-us/dotnet/api/system.componentmodel
— Igor Popov

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

30

ใน MV-VM การใช้งาน ViewModel เสมอ (รุ่นไม่จำเป็นเสมอไป) INotifyPropertyChanged

ตรวจสอบ MV-VM แม่แบบโครงการ / Toolkit จากhttp://blogs.msdn.com/llobo/archive/2009/05/01/download-mv-vm-project-template-toolkit.aspx มันใช้DelegateCommandสำหรับคำสั่งและมันควรจะเป็นแม่แบบเริ่มต้นที่ดีสำหรับโครงการ MV-VM ของคุณ


ประโยคแรกนั้นรวมเอาออปชั่นของคำตอบอื่น ๆ เอาไว้ดี imo => UPVOTE!
— j00hi

13

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

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

DataModel -------- DataController ------ View
                  /
Business --------/

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


3
ดีมากถ้าข้อมูลของคุณเปลี่ยนเฉพาะเมื่อ DataController เปลี่ยน หากข้อมูลมาจากฐานข้อมูลหรือที่เก็บข้อมูลอื่นที่สามารถให้ทางเลือกอื่นสำหรับการเปลี่ยนแปลงคุณอาจต้องมีวิธีแจ้ง VIEWMODEL (DataController ในรูปแบบของคุณ) และ VIEW เมื่อเกิดขึ้น คุณสามารถสำรวจความคิดเห็นโดยใช้ DataController หรือส่งจากกระบวนการภายนอกไปยัง DataModel ของคุณและอนุญาตให้ DataModel ของคุณส่งการแจ้งเตือนการเปลี่ยนแปลงไปยัง DataController ของคุณ
— ScottCher

4
คุณพูดถูก การออกแบบ patters อยู่ในระดับสูงมาก เวลาส่วนใหญ่ที่รูปแบบการออกแบบจะทำให้คุณทำสิ่งที่ถูกต้อง แต่ทุกครั้งที่พวกเขาเปลี่ยนคุณไปในทางที่ผิด คุณไม่ควรหลีกเลี่ยงการทำสิ่งที่ถูกต้องเพราะมันอยู่นอกรูปแบบการออกแบบของคุณ
— Rhyous

คุณจะผลักดันไปยัง DataController ของคุณในขณะที่มันควบคุมและรูปแบบข้อมูลและจะบอกให้ปรับปรุง
— Rhyous

นอกจากนี้ Model ใน MVVM ควรได้รับการรักษาเฉพาะตามที่ UI ต้องการ (เช่น DTO) ดังนั้นฐานข้อมูลหรือตรรกะทางธุรกิจที่ซับซ้อนควรเกิดขึ้นในเลเยอร์ที่แตกต่างกันและจากนั้นควรให้ข้อมูลที่หยาบคายผ่านโมเดลมุมมอง
— ชื่อรหัส Jack

9

ขึ้นอยู่กับว่าคุณใช้โมเดลของคุณอย่างไร บริษัท ของฉันใช้วัตถุธุรกิจคล้ายกับวัตถุ CSLA ของ Lhotka และใช้ประโยชน์อย่างกว้างขวางINotifyPropertyChangedทั่วทั้งโมเดลธุรกิจ

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

เรายังมีมุมมองโมเดลที่เผยแพร่การเปลี่ยนแปลงจากโมเดลในกรณีที่จำเป็น แต่ตัวโมเดลมุมมองเองกำลังฟังการเปลี่ยนแปลงโมเดลพื้นฐาน


3
คุณเผยแพร่ OnPropertyChanged ของ Model ไปยัง OnPropertyChanged ของ ViewModel ได้อย่างไร ฉันมีปัญหาเมื่อ ViewModel มีชื่อคุณสมบัติที่แตกต่างจากรุ่น - การแมปชื่อต่อชื่อบางประเภทจะต้องใช่ไหม?
— Martin Konicek

มันไม่ซับซ้อนอะไรจริง ๆ เราแค่ส่งต่อเหตุการณ์ ฉันคิดว่าชื่อต่างจากนั้นสามารถใช้ตารางการค้นหาได้ หากการเปลี่ยนแปลงไม่ใช่การทำแผนที่แบบหนึ่งต่อหนึ่งคุณสามารถขอเหตุการณ์ได้แล้วเริ่มเหตุการณ์ที่จำเป็นในตัวจัดการ
— Steve Mitcham

6

ฉันเห็นด้วยกับคำตอบของเปาโลการดำเนินการINotifyPropertyChangedในแบบจำลองนั้นเป็นที่ยอมรับโดยสมบูรณ์และเป็นที่แนะนำโดย Microsoft -

โดยปกติแล้วตัวแบบจะใช้สิ่งอำนวยความสะดวกที่ทำให้ง่ายต่อการเชื่อมโยงกับมุมมอง ซึ่งมักจะหมายความว่ารองรับคุณสมบัติและการแจ้งเตือนการเปลี่ยนแปลงคอลเลกชันผ่านINotifyPropertyChangedและ INotifyCollectionChangedอินเทอร์เฟซ คลาสรุ่นที่แสดงคอลเลกชันของวัตถุมักจะได้รับมาจาก ObservableCollection<T>คลาสซึ่งมีการใช้งาน INotifyCollectionChangedอินเทอร์เฟซ

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

เกิดอะไรขึ้นถ้าคลาสโมเดลของคุณไม่ใช้อินเตอร์เฟสที่จำเป็น?

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

นำมาจาก - http://msdn.microsoft.com/en-us/library/gg405484(PandP.40).aspx

ฉันได้ทำงานในบางโครงการที่เราไม่ได้นำไปใช้INotifyPropertyChangedในแบบจำลองของเราและด้วยเหตุนี้เราจึงประสบปัญหามากมาย จำเป็นต้องทำสำเนาคุณสมบัติที่ไม่จำเป็นใน VM และในเวลาเดียวกันเราต้องอัพเดตออบเจ็กต์ต้นแบบ (ด้วยค่าที่อัปเดต) ก่อนส่งผ่านไปยัง BL / DL

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


3

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


3

ฉันคิดว่าคำตอบนั้นค่อนข้างชัดเจนหากคุณต้องการปฏิบัติตาม MV-VM

ดู: http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx

ในรูปแบบ MVVM มุมมองจะห่อหุ้ม UI และตรรกะ UI ใด ๆ โมเดลมุมมองจะสรุปตรรกะและสถานะของงานนำเสนอ

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


4
คำพูดเปิดให้ตีความ ฉันคิดว่าคุณควรเพิ่มการตีความของคุณเพื่อให้คำตอบของคุณชัดเจน :-)
— Søren Boisen

@John D: บทความนั้นให้การตีความ MVVM เพียงครั้งเดียวและวิธีการใช้มันไม่ได้นิยาม MVVM
— akjoshi

ยิ่งไปกว่านั้นถ้าคุณอ่านบทความฉบับเต็มมันจะกำหนดคลาสของโมเดลดังนี้: "โดยทั่วไปแล้วโมเดลจะใช้สิ่งอำนวยความสะดวกที่ทำให้ง่ายต่อการเชื่อมโยงกับมุมมองซึ่งมักจะหมายความว่ามันรองรับคุณสมบัติและการแจ้งเตือนที่เปลี่ยนไป คลาสรุ่นที่แสดงถึงคอลเลกชันของวัตถุมักจะได้รับมาจากคลาส ObservableCollection <T> ซึ่งให้การใช้งานอินเทอร์เฟซ INotifyCollectionChanged
— akjoshi

2

ฉันจะพูดใน ViewModel ของคุณ มันไม่ได้เป็นส่วนหนึ่งของโมเดลเนื่องจาก Model เป็น UI ที่ไม่เชื่อเรื่องพระเจ้า โมเดลควรเป็น 'ทุกอย่างยกเว้นผู้ไม่เชื่อเรื่องพระเจ้า'


2

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


1

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

ฉันสังเกตเห็นข้อดีและข้อเสียหลายประการ:

ข้อดี

ตัวแจ้งเตือนอยู่ในรูปแบบธุรกิจ

  1. ตามโดเมนขับเคลื่อนมันถูกต้อง ควรตัดสินใจว่าจะยกระดับและเมื่อใด

ข้อเสีย

โมเดลมีคุณสมบัติ (จำนวน, อัตรา, ค่าคอมมิชชั่น, ยอดรวม) Totalfrieght คำนวณโดยใช้จำนวนอัตราการเปลี่ยนแปลงค่าคอมมิชชั่น

  1. ในการโหลดค่าจาก db การคำนวณ frieght ทั้งหมดเรียกว่า 3 ครั้ง (จำนวน, อัตรา, คอมมิชชั่น) มันควรจะเป็นครั้งเดียว

  2. ถ้า rate จะมีการกำหนดจำนวนจำนวนในเลเยอร์ธุรกิจระบบจะเรียกตัวแจ้งอีกครั้ง

  3. ควรมีตัวเลือกในการปิดการใช้งานนี้อาจจะอยู่ในชั้นฐาน อย่างไรก็ตามผู้พัฒนาสามารถลืมที่จะทำเช่นนี้


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

1

ฉันคิดว่ามันทั้งหมดขึ้นอยู่กับกรณีการใช้งาน

เมื่อคุณมีโมเดลที่เรียบง่ายพร้อมคุณสมบัติมากมายคุณสามารถให้มันใช้งาน INPC ได้ โดยง่ายผมหมายถึงว่ารุ่นนี้มีลักษณะค่อนข้างเหมือนPOCO

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

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

ปัญหาอื่นกับ INPC คุณควรออกแบบแอพของคุณให้เป็นนามธรรม โดยทั่วไปจะใช้อินเทอร์เฟซ

ลองมาดูการใช้งาน 2 อย่างที่แตกต่างกันของสิ่งที่เป็นนามธรรม:

public class ConnectionStateChangedEventArgs : EventArgs
{
    public bool IsConnected {get;set;}
}

interface IConnectionManagerINPC : INotifyPropertyChanged
{
    string Name {get;}
    int ConnectionsLimit {get;}
    /*

    A few more properties

    */
    bool IsConnected {get;}
}

interface IConnectionManager
{
    string Name {get;}
    int ConnectionsLimit {get;}
    /*

    A few more properties

    */
    event EventHandler<ConnectionStateChangedEventArgs> ConnectionStateChanged;
    bool IsConnected {get;}
}

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

ในทางตรงกันข้ามความตั้งใจของ IConnectionManager นั้นชัดเจน: "ฉันสามารถบอกคุณได้ว่ามูลค่าของทรัพย์สิน IsConnected ของฉันอาจมีการเปลี่ยนแปลง"


1

เพียงแค่ใช้INotifyPropertyChangeในโมเดลโมเดลของคุณและไม่ใช่ในโมเดล

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


1
แล้วรุ่นที่มีคุณสมบัติหลายอย่างล่ะ? คุณกำลังทำซ้ำรหัสใน VM
— Luis

0

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

ดังนั้นสิ่งที่ฉันทำคือการให้วัตถุเองที่จะแจ้งให้ทุกคนเมื่อค่าในการเปลี่ยนแปลงสถานที่ให้บริการและในมุมมองของฉันฉันจะใช้ผูกเหมือนObject.Property1, Object.Property2และ OnPropertyChanged("Object")ในแบบที่ถ้าฉันเพียงแค่ต้องการที่จะเปลี่ยนวัตถุที่จะยังคงอยู่ในขณะนี้ในมุมมองของฉันฉันเพียงแค่ทำ

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


0

ปกติ ViewModel INotifyPropertyChangedจะดำเนินการ โมเดลสามารถเป็นอะไรก็ได้ (ไฟล์ xml ฐานข้อมูลหรือแม้แต่วัตถุ) Model ใช้เพื่อให้ข้อมูลแก่ viewmodel ซึ่งแพร่กระจายไปยังมุมมอง

ดูที่นี่


1
emm .. ไม่ โมเดลไม่สามารถเป็นไฟล์หรือฐานข้อมูล xml และรูปแบบไม่ได้ใช้เพื่อให้ข้อมูล มิฉะนั้นควรเรียกว่าไม่ใช่ "model" แต่เป็น "data" .. ? Model ใช้อธิบายข้อมูล อธิบายตนเองได้ค่อนข้างใช่ไหม :)
— Taras

1
หากคุณมีคำตอบที่ดีกว่ากรุณาแบ่งปัน! เราทุกคนอยู่ที่นี่เพื่อแบ่งปันความรู้และไม่แข่งขัน
— Adam

0

imho ฉันคิดว่าอุปกรณ์เสริม viewmodel INotifyPropertyChangeนั้นสามารถใช้การแจ้งเตือนใน "ระดับ" ที่แตกต่างกันได้

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

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


0

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

[การใช้ชุดเครื่องมือ MVVM Light ฉันให้พวกมันสืบทอดจาก ViewModelBase]

โมเดลถือเป็นตรรกะทางธุรกิจ แต่ไม่มีอะไรเกี่ยวข้องกับมุมมอง ดังนั้นจึงไม่จำเป็นต้องมีอินเทอร์เฟซ INotifyPropertyChanged

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