2010-01-05 14 views
15

चलो कुछ सार ViewModel आधार कक्षा में कहते हैं कि मैं एक सादे पुराने संपत्ति के रूप में इस करते हैं:परिवर्तन सूचना

public Size Size 
{ 
    get { return _size; } 
    set 
    { 
     _size = value; 
     OnPropertyChanged("Size"); 
    } 
} 

मैं तो बनाने के एक अधिक विशिष्ट ViewModel, पिछले एक, जिसमें से इनहेरिट निम्नलिखित संपत्ति:

public Rect Rectangle 
{ 
    get { return new Rect(0, 0, _size.Width, _size.Height); } 
} 

अब, कुछ वर्ग दृश्य में मैं ऊपर उल्लिखित ViewModel के Rectangle संपत्ति के लिए बाध्य। सब कुछ ठीक काम करता है, जब तक कि मैं आकार बदल नहीं जाता। जब Size परिवर्तन, Rectangle इसके बारे में नहीं पता है और परिवर्तन दृश्य को प्रसारित नहीं करता है। और Rectangle बच्चे वर्ग में है, इसलिए मैं OnPropertyChanged("Rectangle") को Size सेटर में बस जोड़ नहीं सकता।

अब कल्पना करें कि मेरे पास Rectangle जैसी कई अलग-अलग गुण हैं, जो सभी बेस-क्लास गुणों पर निर्भर करते हैं, और इनमें से कोई भी परिवर्तन प्रचारित नहीं किया जा रहा है। मुझे परिवर्तन अधिसूचनाओं को चुनने के कुछ हल्के और सुरुचिपूर्ण तरीके की ज़रूरत है, अधिमानतः एक जिसे बहुत सारे कोड की आवश्यकता नहीं होती है और मुझे निर्भरता गुणों का उपयोग करने में मजबूर नहीं करती है।

स्पष्ट रूप से यहां बहुत सारे बदसूरत समाधान हैं- जो मैं ढूंढ रहा हूं वह कुछ साफ और चालाक है। ऐसा लगता है कि यह एक बहुत ही आम परिदृश्य होगा, और ऐसा लगता है कि ऐसा करने के लिए एमवीवीएम-अनुकूल हो सकता है।

उत्तर

9

मैंने हाल ही में इस सटीक समस्या के बारे में ब्लॉग किया है। मैं आयताकार के साथ [DependsUpon("Size")] विशेषता शामिल करता हूं। मैं वास्तव में इस दृष्टिकोण की तरह हूं, क्योंकि यह निर्भरता ज्ञान को उस कोड के साथ रखता है जो निर्भरता बनाता है, न कि दूसरी तरफ।

एक नज़र डालें: http://houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx

+0

महान विचार। मैंने इसे निर्माण समय (प्रदर्शन कारणों के लिए) में एक शब्दकोश बनाने के लिए थोड़ा सा बदल दिया, लेकिन अवधारणा ध्वनि है। – Charlie

3

आप बस इतना की तरह ली गई ViewModel में OnPropertyChanged ओवरराइड कर सकते हैं:

protected override void OnPropertyChanged(string propertyName) { 
    base.OnPropertyChanged(propertyName); 
    if (propertyName == "Size") { 
     base.OnPropertyChanged("Rectangle"); 
    } 
} 

एक और संभावना है ... कुछ समय पहले मैं एक साथ रखा एक बहुत अच्छा ViewModel आधार वर्ग इस तरह के गुणों पर विशेषताओं का समर्थन करता है:

[DependsOn("Size")] 
public Rect Rectangle { 
    get { new Rect(0,0,Size.Width, Size.Height); } 
} 

फिर व्यूमोडेल बेस क्लास इन DependsOnAttribute को रनटाइम पर एकत्र करता है और इसकी ऑनप्रॉपर्टी चेंज विधि में मूल रूप से यह देखने लगता है कि संपत्ति बदलने पर अन्य गुणों को अमान्य करने की आवश्यकता है ई होता है।

+0

ऑनप्रॉपर्टी ओवरराइडिंग निश्चित रूप से एक समाधान है, लेकिन एक सुरुचिपूर्ण नहीं है। हालांकि, मैं आपका दूसरा सुझाव बेहतर पसंद करता हूं। – Charlie

+0

सभी समाधान लालित्य के लिए कॉल नहीं करते हैं। OnProperty ओवरराइडिंग बहुत सरल है और मैं अभी भी कई मामलों में ऐसा करता हूं जब तक कि निर्भरता बालों वाली न हो, जिससे मुझे दूसरा दृष्टिकोण करने का मौका मिला। – Josh

+0

आप सही हैं, लेकिन मेरे प्रश्न में याद है मैंने विशेष रूप से कहा था, "अब कल्पना करें कि मेरे पास आयत जैसे कई अलग-अलग गुण हैं, जो सभी बेस-क्लास गुणों पर निर्भर करते हैं, और इनमें से कोई भी परिवर्तन प्रचारित नहीं किया जा रहा है।" तो धारणा यह है कि पदानुक्रम पहले ही बालों वाली हो रही है। – Charlie

1

एक साफ MVVM तरीका एक Messenger की सदस्यता लेने/सूचित तंत्र का उपयोग किया जाएगा (में की तरह जोश स्मिथ के MvvmFoundation)

एक सिंगलटन मैसेंजर वस्तु कहीं बनाएँ - मुख्य अनुप्रयोग वर्ग हमेशा इस

के लिए एक अच्छी जगह है
public partial class App : Application 
{ 
    private static Messenger _messenger; 
    public static Messenger Messenger 
    { 
     get 
     { 
      if (_messenger == null) 
      { 
       _messenger = new Messenger(); 
      } 
      return _messenger; 
     } 
    } 
} 

आधार वर्ग से आकार सेटर में, सूचित परिवर्तन:

public Size Size 
{ 
    get { return _size; } 
    set 
    { 
     _size = value; 
     OnPropertyChanged("Size"); 

     App.Messenger.NotifyColleagues("SIZE_CHANGED"); 
    } 
} 

अब आप अपने विरासत में मिला है दृश्य दे सकते हैं मॉडल के रूप में उपयुक्त PropertyChanged घटनाओं बढ़ा इन बदलावों को सुनने, और ...

public MyViewModel : MyViewModelBase 
{ 
    public MyViewModel() 
    { 
     App.Messenger.Register("SIZE_CHANGED",() => OnPropertyChanged("Rectangle")); 
    } 
} 
बेशक

- वापस करने के लिए अधिसूचित किया जाना प्रत्येक गुण परिवर्तन की जरूरत है के लिए एक - आप इस संदेश को आप की जरूरत के रूप में के रूप में कई सदस्यता जोड़ सकते हैं देखें ...

आशा इस मदद करता है :)

+0

यह बिल्कुल ठीक है जैसा कि माता-पिता में बच्चे के लिए ऑनप्रॉपर्टी चैन किया गया है, सुनिश्चित नहीं है कि यह वास्तव में इसे कोई क्लीनर बनाता है – AwkwardCoder

+0

यह बिल्कुल बुरा विचार नहीं है, लेकिन मुझे कुछ और हल्का वजन चाहिए। – Charlie

+0

मैसेंजर दृष्टिकोण का उपयोग करने का लाभ उन मामलों में हो सकता है जहां आपके पास गहन घोंसला वाले पदानुक्रम हैं जहां यह असुविधाजनक और संपत्ति परिवर्तन घटनाओं को श्रृंखला में अक्षम करने के लिए अक्षम होगा। – jpierson

0

शायद क्योंकि im एक वीबी पुरुष है, लेकिन अपने आयत कोड में ऐसा लगता है कि आप सार्वजनिक आकार संपत्ति के बजाय निजी _size घोषणा जो OnPropertyChanged ईवेंट सक्रिय नहीं होता सचेत करने के लिए तक पहुँच रहे हैं दृश्य

इसके अलावा मैं आधार से दूर हो सकता हूं, लेकिन आयत वास्तविक वस्तु नहीं होनी चाहिए जबकि आकार उस वस्तु की संपत्ति है? हो सकता है कि आप यही कर रहे हैं..कुछ सी # पद्धतियां अभी भी मेरे लिए वास्तव में विदेशी हैं।

+0

मैं निजी _size घोषणा का उपयोग कर रहा हूं लेकिन यह अप्रासंगिक है। वह एक गेटर है, एक सेटटर नहीं। दृश्य को अधिसूचित करने की आवश्यकता है कि आकार बदलते समय आयताकार बदल रहा है, न कि जब आयताकार का उपयोग किया जा रहा हो। – Charlie

4

मैं जोश स्मिथ के PropertyObserver, जो आप http://mvvmfoundation.codeplex.com/ में अपने MVVM फाउंडेशन पुस्तकालय से प्राप्त कर सकते हैं का उपयोग करें।

उपयोग:

_viewmodel_observer = new PropertyObserver<OtherViewModel>(_OtherViewModel) 
    .RegisterHandler(m => m.Size, m => RaisePropertyChanged(Rectangle); 

ब्रायन की विशेषता दृष्टिकोण भी अच्छा है। प्रॉपर्टी ऑब्सर्वर के बारे में मुझे एक चीज़ पसंद है कि मैं मनमानी कोड निष्पादित कर सकता हूं; मुझे ऐसी स्थितियों की जांच करने की इजाजत दी गई है जो मुझे उठाने या अन्य कार्यों को एक साथ करने से रोक सकती हैं।

संबंधित मुद्दे