INMifyPropertyChanged बनाम DependencyProperty में ViewModel


353

जब एक मॉडल-व्यू-व्यूमॉडल आर्किटेक्चर WPF एप्लिकेशन में ViewModel को लागू करते हैं, तो यह दो प्रमुख विकल्प प्रतीत होता है कि इसे कैसे डाटाइंडेबल बनाया जा सकता है। मैंने उन कार्यान्वयनों को देखा है जो DependencyPropertyगुणों के लिए उपयोग करते हैं, दृश्य इसके विरुद्ध बाध्य होने वाले हैं और मैंने INotifyPropertyChangedइसके बजाय ViewModel को कार्यान्वित करते हुए देखा है ।

मेरा सवाल यह है कि मुझे एक पर दूसरे को कब पसंद करना चाहिए? क्या कोई प्रदर्शन अंतर हैं? क्या WPM को ViewModel निर्भरता देना वास्तव में एक अच्छा विचार है? डिजाइन निर्णय लेने पर मुझे और क्या विचार करने की आवश्यकता है?


11
stackoverflow.com/questions/1329138/… को INTifyPropertyhanhanged को लागू करने के संकलित तरीके के लिए देखें । मैजिक स्ट्रिंग के रूप में प्रॉपर्टी के नाम रखने से बचें।
इयान रिंगरोज 11

10
आम तौर पर एक निर्भरता संपत्ति और एक वर्ग में एक सामान्य संपत्ति के बीच एक बड़ा अंतर होता है जो INotifyPropertyChanged को लागू करता है। निर्भरता गुण डेटा बाइंडिंग में स्रोत या लक्ष्य हो सकते हैं लेकिन INotifyPropertyChanged समर्थन के साथ सामान्य गुण केवल स्रोत के रूप में उपयोग किए जा सकते हैं। तो ये समाधान पूरी तरह से विनिमेय नहीं हैं। डेटा बाइंडिंग इन्फ्रास्ट्रक्चर को काम करने के लिए लक्ष्य के रूप में एक डीपी की आवश्यकता होती है, लेकिन स्रोत या तो INotifyPropertyChanged समर्थन या एक सामान्य DP के साथ एक सामान्य गुण हो सकता है।
मुस्तफा रज़ाई

4
कार्यान्वयन के लिए .net 4.5 तरीके के लिए stackoverflow.com/a/10595688/200442 देखें INotifyPropertyChanged
डैनियल लिटिल

सबसे अच्छी तरह से यहाँ समझाया गया stackoverflow.com/a/3552550/366064
बिशन

जवाबों:


214

केंट ने इस विषय के बारे में एक दिलचस्प ब्लॉग लिखा: मॉडल देखें: POCOs बनाम निर्भरताऑब्जेक्ट

संक्षिप्त सारांश:

  1. DependencyObjects को क्रमिक रूप से चिह्नित नहीं किया जाता है
  2. DependencyObject वर्ग बराबरी () और GetHashCode () विधियों को ओवरराइड और सील करता है
  3. एक DependencyObject में थ्रेड एफिनिटी है - इसे केवल उस थ्रेड पर एक्सेस किया जा सकता है जिस पर इसे बनाया गया था

मैं पोको दृष्टिकोण को पसंद करता हूं। PresentationModel (उर्फ ViewModel) के लिए एक बेस क्लास जो INotifyPropertyChanged इंटरफ़ेस को लागू करता है वह यहां पाया जा सकता है: http://compositeextensions.codeplex.com


24
DependencyObject भी WPF पुस्तकालयों पर निर्भरता लेता है, जबकि POCO आपके दृश्य मॉडल को कुछ अन्य UI स्टैक को चलाने की अनुमति नहीं देता है जहां WPF उपलब्ध नहीं है (कॉम्पैक्ट फ्रेमवर्क, मोनो)।
कोडकाइजन

26
यह स्पष्ट है कि, डिपेंडेसी गुण केवल UI के लिए बनाए गए हैं और व्यावसायिक परत के लिए नहीं।
आंद्रेई रोनेया

11
डिपेंडेंसी गुणों के लिए एक डिपेंडेंसी ऑबजेक्ट पैरेंट की भी आवश्यकता होती है। आपका ViewModel वास्तव में DependencyObject से वारिस नहीं होना चाहिए।
गुस्सोर

38

WPF प्रदर्शन गाइड के अनुसार, DependencyObjects निश्चित रूप से INCOifyPropertyChanged को लागू करने वाले POCO से बेहतर प्रदर्शन करते हैं:

http://msdn.microsoft.com/en-us/library/bb613546.aspx


1
: मुझे लगता है कि एक ;-) पर सहमत होना होगा blog.lexique-du-net.com/index.php?post/2010/02/24/...
Jonatha ANTOINE

यदि आप .NET फ्रेमवर्क संस्करण 4 का चयन करते हैं, तो लिंक अभी भी काम करता है। यह सिर्फ "वर्तमान संस्करण" के लिए उपलब्ध नहीं है।
डबल यू

इसे इंगित करने के लिए धन्यवाद, देवों के बारे में बहुत सारे गलत तरीके से गलत जानकारी दी गई है, जिससे यह दावा किया जा रहा है कि INotifyPropertyChanged तेजी से या डीपी से कम ओवरहेड को उकसाता है और यह केवल निराधार है। डीपी वर्चुअल (डेटा) ट्री को संरचनात्मक रूप से परिभाषित करने के लिए तेज, सुरुचिपूर्ण और शक्तिशाली तरीके हैं।
टार्टरी

डिपेंडेंसी ऑबजेक्ट्स में एक छिपी हुई बुराई है। उन्हें उसी धागे पर बनाने की जरूरत है जिस तरह के नियंत्रण उन्हें बांधते हैं। इसका मतलब है GUI थ्रेड। इसका मतलब है कि आपको सृजन को उस धागे तक पहुंचाना होगा। आप उन चीजों को उदाहरण के लिए DB से कुछ बैकग्राउंड थ्रेड पर लोड और निर्मित नहीं कर सकते। जब तक आप सृजन को प्रेषण नहीं करते। पागल।
ed22

28

चुनाव पूरी तरह से आपके व्यापार तर्क और यूआई अमूर्त स्तर पर आधारित है। यदि आप एक अच्छा अलगाव नहीं चाहते हैं तो डीपी आपके लिए काम करेगा।

डिपेंडेंसीप्राइपरेटी मुख्य रूप से विजुअलइलिश स्तर पर लागू होगी इसलिए यह अच्छा विचार नहीं होगा यदि हम अपनी प्रत्येक व्यावसायिक आवश्यकताओं के लिए बहुत सारी डीपी बनाते हैं। इसके अलावा एक INotifyPropertyChanged की तुलना में DP के लिए अधिक लागत है। जब आप WPF / Silverlight डिज़ाइन करते हैं तो UI और ViewModel को पूरी तरह से अलग करने की कोशिश करें ताकि किसी भी समय हम लेआउट और UI नियंत्रणों को बदल सकें (विषय और शैलियों के आधार पर)

इस पोस्ट को भी देखें - /programming/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel । लिंक में मॉडल-व्यू-व्यूमॉडल पैटर्न का बहुत संदर्भ है, जो इस चर्चा के लिए बहुत प्रासंगिक है।


9
Jbe द्वारा पोस्ट मतभेदों का अधिक सटीक उत्तर देता है। सिर्फ इसलिए कि एक VM (या प्रस्तुतकर्ता) DependencyObject से विरासत में मिला है, इसका मतलब यह नहीं है कि इसे स्टाइल नहीं किया जा सकता है या तार्किक रूप से व्यू से अलग नहीं है, इसका सिर्फ इतना मतलब है कि संपत्ति मूल्यों के लिए भंडारण स्पष्ट रूप से घोषित क्षेत्रों से अलग है। पोको शैली। कहा जा रहा है, क्रमबद्धता, तार्किक समानता, और धागा संबंध वास्तविक मुद्दे हैं, जिन्हें DepedencyObject- आधारित VMs से निपटना पड़ता है।
micahtan

"इसके अलावा एक INotifyPropertyChanged की तुलना में डीपी के लिए एक बड़ी लागत है" - इस पर आपके सबूत का स्रोत कहां है? बहुत सारे देवता बिना किसी सबूत के इसका समर्थन करने के लिए यह दावा करते हैं। MSDN के अनुसार यह सच नहीं है। "यूआई और व्यूमॉडल को पूरी तरह से अलग करने की कोशिश करें ताकि किसी भी समय हम लेआउट और यूआई नियंत्रण को बदल सकें" - फिर, इसका पीओसीओ / प्रोपरचेंज बनाम डीओ / डीपी के साथ कोई लेना-देना नहीं है। यदि कुछ है, तो DO / DP में परावर्तन और पथ रजिस्ट्री दृश्य पक्ष पर काम करने की आपकी क्षमता में सुधार करती है।
बजे

20

एक अभिव्यक्ति के दृष्टिकोण से, मैं पूरी तरह से निर्भरता के गुणों का उपयोग करने और विचार करने के दौरान ऐंठन का आनंद लेता हूं INotifyPropertyChanged। इसके अलावा stringसंपत्ति के नाम और संभव मेमोरी लीक घटना सदस्यता की वजह से, INotifyPropertyChangedएक और अधिक स्पष्ट व्यवस्था है।

निर्भरता गुण "जब यह होता है, तो ऐसा करें" आसानी से समझे जाने वाले स्थिर मेटाडेटा का उपयोग करें। यह एक घोषणात्मक दृष्टिकोण है जो मेरे वोट को लालित्य के लिए प्राप्त करता है।


1
स्ट्रिंग भाग में अब nameof ऑपरेटर के साथ एक समाधान है।
न्यूटोपियन

@ न्यूटोपियन: सच है। इसके साथ कुछ रोचक बातें भी संभव हैं [CallerMemberName]
ब्रायन वत्स

डीओ / डीपी मॉडल बनाम एक पीओसीओ का उपयोग करते समय डब्ल्यूपीएफ और सीएलआर में संपत्ति पंजीकरण (प्रतिबिंब) के लाभों का उल्लेख नहीं करना।
टार्टी

16

INotifyPropertyChanged जब इस्तेमाल किया जाता है तो यह आपको अपने गेटर्स और अपने गुणों के सेटर में अधिक तर्क जोड़ने की क्षमता देता है।

DependencyProperty उदाहरण:

public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) );

public String Name
{
    set { SetValue( NameProperty, value ); }
    get { return ( String ) GetValue( NameProperty ); }
}

आपके गेटटर और सेटर में --- आप बस इतना कर सकते हैं कि क्रमशः सेटवैल्यू और गेटवैलू कॉल करें, फ्रेमवर्क के अन्य भागों में बी / सी को गेट्टर / सेटर नहीं कहा जाता है, इसके बजाय यह सीधे सेटवैल्यू, गेटव्यू कॉल करता है, इसलिए आपकी संपत्ति तर्क नहीं होगी मज़बूती से निष्पादित किया गया।

INotifyPropertyChangedकिसी घटना को परिभाषित करने के साथ :

public event PropertyChangedEventHandler PropertyChanged;

और फिर आपके कोड में कहीं भी कोई तर्क है, तो कॉल करें:

// ...
// Something cool...
// ...

if( this.PropertyChanged != null )
{
    PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) );
}

// More cool stuff that will reliably happen...

यह एक गेटटर / सेटर में, या कहीं और भी हो सकता है।


11
आप DependencyProperties से भी सूचनाएं बदल सकते हैं। देखें PropertyMetadata.PropertyChangedCallback। उदाहरण पर: msdn.microsoft.com/en-us/library/ms745795.aspx
जो व्हाइट

2
इसके अलावा, आप संपत्ति के अंदर से ही नहीं, कहीं से भी सेटवैल्यू को कॉल कर सकते हैं
aL3891

यह भ्रामक और असत्य है - डीपी पर घटनाओं को बदलने के कई तरीके हैं, भले ही इसे 'आंतरिक रूप से' बदल दिया गया हो। उनमें से एक जो जो व्हाइट
टार्टी

16

निर्भरता गुणों का उद्देश्य यूआई तत्वों पर बाध्यकारी (एक लक्ष्य के रूप में) का समर्थन करना है, डेटा बाइंडिंग के स्रोत के रूप में नहीं, यह वह जगह है जहां INotifyProperty आती है। शुद्ध दृष्टिकोण से आपको DPM का उपयोग ViewModels पर नहीं करना चाहिए।

"एक बंधन का स्रोत होने के लिए, एक संपत्ति को एक निर्भरता संपत्ति होने की आवश्यकता नहीं है; आप किसी भी CLR संपत्ति को बाध्यकारी स्रोत के रूप में उपयोग कर सकते हैं। हालांकि, एक बंधन का लक्ष्य होने के लिए, संपत्ति एक संपत्ति होनी चाहिए। निर्भरता संपत्ति। प्रभावी होने के लिए एक-तरफ़ा या दो-तरफ़ा बाइंडिंग के लिए, स्रोत प्रॉपर्टी को बाइंडिंग सिस्टम और इस प्रकार लक्ष्य के लिए प्रचार करने वाली सूचनाओं का समर्थन करना चाहिए। कस्टम CLR बाइंडिंग स्रोतों के लिए, इसका अर्थ है कि संपत्ति INotifyProTtyChanged का समर्थन करना चाहिए। संग्रह को INotifyCollectionChanged का समर्थन करना चाहिए। "

सभी निर्भरता वाली वस्तुओं को अनुक्रमित नहीं किया जा सकता है (यह ViewModels और DTO (POCO) के उपयोग में बाधा उत्पन्न कर सकता है।

WPF की तुलना में सिल्वरलाइट के भीतर DP के बीच अंतर हैं।

http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx

http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx


मैं बिना किसी समस्या के 2009 से क्रमबद्ध निर्भरता वाली वस्तुओं का उपयोग कर रहा हूं, इसलिए यह सुनिश्चित नहीं करें कि आप किस बारे में बात कर रहे हैं जब आप कहते हैं कि "सभी निर्भरता वाली वस्तुओं को अनुक्रमित नहीं किया जा सकता है" - हाँ वे कर सकते हैं। वास्तव में कई विकल्प हैं: codeproject.com/Articles/61440/… emphess.net/2008/2008/11/25/dependencyproperty-serialization और मेरे निजी पसंदीदा में से एक: बस अपने सभी DP के लिए बैकिंग स्टोर प्रदान करें और उन सीरियल बनाने योग्य ( Google पर खोज करने के 2 मिनट में कोई अच्छा सरल उदाहरण आसानी से उपलब्ध नहीं था, लेकिन मैं आपको यह काम करने का आश्वासन देता हूं)।
टार्टरी

7

मुझे भी हाल ही में इस फैसले पर विचार करना था।

मैंने पाया कि INotifyPropertyChanged तंत्र ने मेरी आवश्यकताओं को बेहतर तरीके से अनुकूल किया क्योंकि इसने मुझे अपने GUI को मौजूदा व्यावसायिक तर्क ढांचे में बिना राज्य की नक़ल उतारने की अनुमति दी। मैं जिस फ्रेमवर्क का उपयोग कर रहा था, उसका अपना पर्यवेक्षक पैटर्न था और आगे के लिए अधिसूचना के एक स्तर को अग्रेषित करना आसान था। मेरे पास बस एक वर्ग था जिसने अपने व्यावसायिक तर्क ढांचे और इनोटिफ़प्रोपरेटी चैंज किए गए इंटरफ़ेस से पर्यवेक्षक इंटरफ़ेस लागू किया।

डीपी के साथ आप उस बैकएंड को परिभाषित नहीं कर सकते हैं जो राज्य को खुद स्टोर करता है। मुझे लगता है कि मुझे उस राज्य के प्रत्येक आइटम की एक प्रतिलिपि .net कैश करनी होगी। यह एक अनावश्यक ओवरहेड की तरह लग रहा था - मेरा राज्य बड़ा और जटिल है।

इसलिए यहाँ मुझे INIifyifyPropertyChanged को व्यापार तर्क से GUI के गुणों को उजागर करने के लिए बेहतर पाया गया।

यह कहा जा रहा है कि जहां मुझे एक संपत्ति को उजागर करने के लिए कस्टम GUI विजेट की आवश्यकता थी और अन्य GUI विजेट को प्रभावित करने के लिए उस संपत्ति में परिवर्तन के लिए DP ने सरल समाधान साबित किया।

इसलिए मैंने GUI के लिए GUI सूचना के लिए DP को उपयोगी पाया।


6

क्या WPM को ViewModel निर्भरता देना वास्तव में एक अच्छा विचार है?

.NET 4.0 में System.Xaml.dll होगा, इसलिए इसका उपयोग करने के लिए आपको एक मनमानी रूपरेखा पर निर्भरता नहीं लेनी होगी। अपने पीडीसी सत्र के बारे में रॉब रेलीया की पोस्ट देखें ।

मेरा स्वीकार कर लेना

XAML वस्तुओं का वर्णन करने के लिए एक भाषा है, और WPF एक ढांचा है जिसका वर्णित ऑब्जेक्ट UI तत्व हैं।

उनका संबंध सी # के समान है, तर्क का वर्णन करने के लिए एक भाषा है, और .NET, एक ढांचा जो विशेष प्रकार के तर्क को लागू करता है।

XAML का उद्देश्य घोषणात्मक वस्तु रेखांकन है। इस प्रतिमान के लिए W * F प्रौद्योगिकियां महान उम्मीदवार हैं, लेकिन XAML उनमें से स्वतंत्र रूप से मौजूद है।

XAML और संपूर्ण निर्भरता प्रणाली को WF और WPF के लिए अलग-अलग स्टैक के रूप में लागू किया गया था, शायद उनके बीच निर्भरता (बिना किसी उद्देश्य के) बनाए बिना विभिन्न टीमों के अनुभव का लाभ उठाने के लिए।


उत्तर देकर, आप यह अनुमान लगा रहे हैं कि बिटबैंक XAML और WPF को समान मानता है। ViewModels में तार्किक पृथक्करण को बढ़ाने के लिए नहीं, बल्कि कम से कम WPF निर्भरताएँ होनी चाहिए, लेकिन कोड जटिलता को कम करने और उपयोगकर्ता नियंत्रण कोड के पीछे तर्क लिखने से जुड़े सभी मुद्दों से बचने के लिए। आप अनिवार्य रूप से ICOMand और वर्तमान व्यवहार की तरह WPF अवधारणाओं को लागू करेंगे जो केवल WPF / सिल्वरलाइट को आसानी से लपेटने में सक्षम होंगे - एक दृश्य मॉडल में चिंताओं को फैलाने वाली आपकी एकमात्र प्रस्तुति CollectionViews और ObservableCollection होनी चाहिए।
गुस्सोर

6

निर्भरता गुण कस्टम नियंत्रण निर्माण के गोंद हैं। यदि आप XAML डिज़ाइन समय पर गुण विंडो में अपने गुणों को दिखाने के लिए Intelli-sense का उपयोग करने में रुचि रखते हैं, तो आपको निर्भरता गुणों का उपयोग करना चाहिए। INPC प्रॉपर्टी विंडो में डिज़ाइन समय पर प्रॉपर्टी नहीं दिखाएगी।


4

ऐसा लगता है कि डिपेंडेंसी प्रॉपर्टीज़ का उपयोग उन नियंत्रणों में किया जाना चाहिए जो आप इस तरह के बटन बनाते हैं। XAML में गुणों का उपयोग करने के लिए और सभी WPF सुविधाओं का उपयोग करने के लिए, उन गुणों को निर्भरता गुण होना चाहिए।

हालाँकि, आपका ViewModel INotifyPropertyChanged का उपयोग करने से बेहतर है। INotifyPropertyChanged का उपयोग करने से आपको जरूरत पड़ने पर गेटटर / सेटर लॉजिक करने की सुविधा मिलेगी।

मैं एक ViewModel के लिए बेस क्लास के जोश स्मिथ के संस्करण की जाँच करने की सलाह देता हूँ जो पहले से ही INotifyPropertyhanhan को लागू करता है:

http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/

मुझे लगता है कि यह एक उत्कृष्ट उदाहरण है कि एक ViewModel कैसे करें।


4

मुझे लगता है कि डिपेंडेंसीप्रॉपर्टी और INotifyPropertyChanged का उपयोग बाइंडिंग में दो अलग-अलग चीजों के लिए किया जाता है: पहला एक संपत्ति को एक बंधन का लक्ष्य बनाने के लिए और दूसरी संपत्ति से इनपुट प्राप्त करने के लिए (उपयोग {Binding ...} संपत्ति सेट करने के लिए), अंतिम। जब आप किसी संपत्ति के मूल्य को बाध्यकारी के स्रोत के रूप में उपयोग करना चाहते हैं (बाइंडिंग पाथ एक्सप्रेशन में नाम)। तो चुनाव केवल तकनीकी है।


2
किसी भी स्थिति में एक INotifyPropertyChanged का उपयोग किया जा सकता है। आप टूवे को इसमें बांध सकते हैं। एक व्यू ऑब्जेक्ट पर किए गए कुछ कार्यों के लिए केवल तकनीकी कारणों के लिए एक डिपेंडेंसीप्रॉपर्टी की आवश्यकता होती है (उदाहरण के लिए, एक्सएएमएल में व्यू ऑब्जेक्ट को इंस्टैंट करते समय कुछ गुण सेट करना)। एक ViewModel के लिए एक DependencyProperty की आवश्यकता कभी नहीं होती है।
oillio

3

मैं एक अधिक प्रत्यक्ष दृष्टिकोण को पसंद करता हूं, जिसे मैंने प्रस्तुति मॉडल में INotifyPropertyChanged के बिना ब्लॉग किया है । डेटा बाइंडिंग के विकल्प के उपयोग से, आप बिना किसी बहीखाता कोड के सीधे सीएलआर संपत्तियों से जुड़ सकते हैं। आप अपने दृश्य मॉडल में सिर्फ सादा-पुराना .NET कोड लिखते हैं, और जब आपका डेटा मॉडल बदलता है तो यह अपडेट हो जाता है।


बिना INotifyPropertyChanged, PropertyDescriptorका उपयोग किया जाता है, जो स्मृति लीक का
तिलक

अद्यतन नियंत्रण लायब्रेरी जो मैं उस ब्लॉग पोस्ट में प्रस्तुत करता हूं, कमजोर संदर्भों का उपयोग करता है, न कि संपत्ति विवरणकों का। यह मेमोरी को लीक नहीं करता है।
माइकल एल पेरी

1
माइकल, आपकी लाइब्रेरी बहुत सारे कोड बनाती है। मुझे लाभ नहीं दिख रहा है। मैं जेनरेट किए गए प्रॉपर्टीचेंज इवेंट कॉल्स के साथ मॉडल रैपर बनाकर इसे हासिल कर सकता हूं।
डेर_मिस्टर

3

केवल एक ही चीज है कि पसंद क्यों करना चाहिए DependencyObject- बाइंडिंग बेहतर काम करेगी। बस एक साथ एक उदाहरण की कोशिश ListBoxऔर TextBoxसे डेटा के साथ पॉप्युलेट सूची, INotifyPropertyChangedसंपत्ति बनाम DependencyPropertyऔर से संपादित करें वर्तमान आइटम TextBox...


1
कोड नमूना, कृपया
हसन तारेक

1

यदि आप अन्य नियंत्रणों के लिए गुणों को उजागर करना चाहते हैं, तो आपको निर्भरता गुणों का उपयोग करना चाहिए ... लेकिन शुभकामनाएं क्योंकि उन्हें पता लगाने में थोड़ा समय लगता है ...

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.