2011-04-28 13 views
6

में ईवेंट ऑग्रेग्रेटर ईवेंट सदस्यता छोड़ें मैं PRISM और MVVM के साथ WPF का उपयोग शुरू करता हूं। मुझे जिस समस्या का सामना करना पड़ रहा है वह यह है कि मुझे व्यूमोडेल में सब्सक्राइब किए गए इवेंटएग्रेगेटर ईवेंट की सदस्यता समाप्त करने के लिए एक अच्छी जगह/सर्वोत्तम अभ्यास नहीं मिल रहा है। निम्नलिखित समाधान - विनाशक में सदस्यता छोड़ना - बहुत देर हो चुकी है। यह सिर्फ अगले कचरा संग्रह के साथ चल रहा है।व्यूमोडल्स

public class ViewModel : ViewModelBase 
{ 
    public ViewModel() 
    { 
     var eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>(); 
     eventAggregator.GetEvent<SeriesSelectionChangedEvent>().Subscribe(OnSeriesSelectionChanged); 
    } 

    ~ViewModel() 
    { 
     var eventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>(); 
     eventAggregator.GetEvent<SeriesSelectionChangedEvent>().Unsubscribe(OnSeriesSelectionChanged); 
    } 

    void OnSeriesSelectionChanged(SeriesSelectionChangedEventArgs e) 
    { 
    } 
} 

उत्तर

3

यह आप पर निर्भर है! यदि आपका एप्लिकेशन ViewModel को सूचित कर सकता है जब इसकी आवश्यकता नहीं है, तो आपको वहां सदस्यता समाप्त करनी चाहिए।

उदाहरण के लिए, हमारे प्रोजेक्ट में हमारे पास IViewDisposeService है। यदि देखें (या उसके मॉडल) को निर्धारिक अंतिम रूप की आवश्यकता है, तो यह दिखाते समय IViewDisposeService में स्वयं पंजीकृत होता है। फिर कोर उन क्षेत्रों से हटा दिए जाने पर पंजीकृत दृश्यों को सूचित करने के लिए एक ही सेवा का उपयोग करते हैं।

आदेशों का उपयोग करने का एक और तरीका है। आपका मॉडल कमांड का पर्दाफाश करता है जिसे इसे बंद होने पर एक दृश्य द्वारा बुलाया जाना चाहिए। ViewModel सदस्यता रद्द करने के लिए कमांड हैंडलर का उपयोग कर सकता है।

वैसे, अगर आप चिंता करते हैं कि EventAggregator आपके व्यूमोडेल को पकड़ लेगा, तो यह कोई समस्या नहीं है, क्योंकि प्रिज्म के इवेंटएग्रेगेटर कमजोर संदर्भों का उपयोग करते हैं।

+2

घटनाओं के लिए पंजीकरण करते समय आप मजबूत संदर्भ भी चुन सकते हैं। –

+0

यह मेरे ऊपर है - यही मुझे संदेह है। मुझे लगता है कि आपका दूसरा सुझाव - दृश्य के माध्यम से एक आदेश को ट्रिगर करना - मेरी ज़रूरतों के अनुरूप है। बहुत बढ़िया जवाब! –

+0

@ Daniel: ओह, मैं इसके बारे में भूल गया। यह बहुत समय पहले था, जब मैंने अपनी परियोजनाओं में आखिरी कार्यक्रम जोड़ा :) :) –

3

कुछ समय पहले, मुझे भी एक ही समस्या का सामना करना पड़ा। यहां हमने जो किया है (डब्ल्यूपीएफ ऐप)। UserControl, IDisposable: DisposableUserControl -

  1. एक नया आधार वर्ग बनाएँ। इसमें उपयोगकर्ता नियंत्रण का निपटान करने का तर्क होगा। कोड अंत में जोड़ा गया।
  2. DisposableUserControl के साथ अपने एप्लिकेशन में सभी उपयोगकर्ता नियंत्रण बदलें। जैसे < एप्लिकेशन: DisposableUserControl ....> </app.DisposableUserControl>
  3. ViewModelBase में एक OnDispose विधि (वर्चुअल) जो निपटान() अपने अनुप्रयोग के VM.Each ViewModel की विधि में कहा जाता है में इस OnDispose विधि ओवरराइड करना चाहिए जोड़ें जो आप अपनी घटनाओं की सदस्यता छोड़ देंगे। कुछ ऐसा-
    ऑनडिस्पेप() {बेस। डिस्प्ले(); सदस्यता छोड़ें (abcEventSubscribername); }

कोड

/// <summary> 
    /// Falg used to avoid calling dispose multiple times on same user control 
    /// </summary> 
    private bool isDisposed; 



    /// <summary> 
    /// Dispose 
    /// </summary> 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this);   
    } 

    /// <summary> 
    /// If disposing equals true, the method has been called directly 
    /// or indirectly by a user's code. Managed and unmanaged resources 
    /// can be disposed. If disposing equals false, the method has been called by the 
    /// runtime from inside the finalizer and you should not reference 
    /// other objects, only unmanaged resources can be disposed. 
    /// </summary> 
    /// <param name="disposing"></param> 
    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.isDisposed) 
     { 
      this.isDisposed = true; 
      if (disposing) 
      { 
       UtilityFunctions.DisposeChildDisposableUserControls(this); 

       if (this.DataContext != null && this.DataContext is IDisposable) 
       { 
        var parent = LogicalTreeHelper.GetParent(this); 

        if (parent == null || ((parent as FrameworkElement).DataContext != this.DataContext)) 
        { 
         (this.DataContext as IDisposable).Dispose(); 
        } 
        BindingOperations.ClearAllBindings(this); 
        this.DataContext = null; 
       } 
      } 
     } 
    } 
2

आप देखें ViewModel सूचना प्राप्त कर सकता है जब यह उतार दिया जाता है (या एक खिड़की के मामले में जब यह बंद कर दिया है)। फिर व्यूमोडेल में अनलोड किए गए/बंद हैंडलर में आप सदस्यता रद्द कर सकते हैं। मैं अपने आवेदन में ऐसा ही करता हूं।

+0

यह अनिवार्य रूप से मारत की तुलना में एक समान सुझाव है। मुझे लगता है कि जाने का रास्ता है। –

+0

मैं एमवीवीएम फ्रेमवर्क के रूप में सिंच v2 का उपयोग करता हूं। यह स्वचालित रूप से लोडिंग/अनलोडिंग आदि के लिए ईवेंट जोड़ता है। –

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