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.