2009-02-17 21 views
5

में घटनाओं को अनदेखा करने के लिए जब एक पंक्ति सारांश: Silverlight2 में UserControl के निर्माता में बनाए गए ईवेंट हैंडलर के लिए सबसे अच्छा अभ्यास क्या है?सिल्वरलाइट

पृष्ठभूमि: मैं वर्तमान में सिल्वरलाइट 2 में एक व्यापार-व्यवसाय-व्यवसाय का निर्माण कर रहा हूं। चूंकि सिल्वरलाइट एक ब्राउज़र प्लगइन है, विंडो की कोई अवधारणा नहीं है - सबकुछ UserControls के भीतर किया जाता है। जिस तरह से मैं एप्लिकेशन में अलग-अलग "रूपों" को संभालने का तरीका हूं, एक शीर्ष-स्तरीय उपयोगकर्ता नियंत्रण होना चाहिए जिसमें व्यूबॉक्स शामिल है। विभिन्न रूपों को दिखाने के लिए, मैंने व्यूबॉक्स की चाइल्ड प्रॉपर्टी को अलग-अलग UserControls पर सेट किया है। मेरे ऐप में सिंगलटन पेजमैनेजर क्लास है जिसे फॉर्म खोलने और बंद करने के लिए बुलाया जाता है। रूपों (UserControls) एक ढेर में संग्रहीत हैं। एक फॉर्म खोलना इसे स्टैक के शीर्ष पर रखता है, इसे बंद करने से इसे ढेर से हटा दिया जाता है और नीचे वाला एक दिखाता है।

मैं मॉडल-व्यू-व्यू मॉडेल पैटर्न का पालन करने की कोशिश कर रहा हूं। प्रत्येक रूप में (UserControl से व्युत्पन्न), मेरे पास एक व्यूमोडेल है जो दृश्य के लिए सभी डेटा प्रबंधित करता है। व्यूमोडेल घटनाओं को उजागर करता है ताकि यूआई को अधिसूचित किया जा सके जब लोड और सेवमेंट जैसे ऑपरेशन पूरे हो गए हों।

मेरी रूप में, मैं, निर्माता में घटना की सदस्यता के बाद मैं ViewModel

public partial class MyPage : UserControl 
{ 

    public MyViewModel ViewModel{get; set;} 

    // other constructors, which create the viewmodel and call the constructor below. 

    public MyPage(MyViewModel viewModel) 
    { 
     InitializeComponent(); 
     ViewModel = viewModel; 
     this.LayoutRoot.DataContext = this.ViewModel; 

     // subscribe to event so we can do stuff 
     this.ViewModel.LoadCompleted += new MyViewModel.LoadCompletedEventHandler(ViewModel_LoadCompleted); 
    } 

मेरा प्रश्न है मिल गया है: अब है कि मैं इस घटना के लिए सदस्यता ले लिया है, जब मैं निकालूँ हैंडलर? क्या मैं एक विनाशक बना देता हूं और वहां करता हूं, या क्या वह चिकन-अंडे की स्थिति पैदा करता है जहां कचरा कलेक्टर ऑब्जेक्ट को तब तक नष्ट नहीं करेगा जब तक सभी संदर्भ (यानी: ईवेंट हैंडलर) नहीं जाते? क्या मैं एक इंटरफ़ेस बना सकता हूं कि फ़ॉर्म को कार्यान्वित करना चाहिए जो UnhookEvents फ़ंक्शन निर्दिष्ट करता है जिसे पृष्ठ मैनेजर द्वारा फ़ॉर्म बंद होने पर कहा जाता है?

संपादित करें: प्रतिक्रियाओं के लिए धन्यवाद। उस स्थिति के बारे में क्या है जहां ViewModel फ़ॉर्म (UserControl) से अधिक लंबा रहता है? मेरे ऐप का एक हिस्सा उपयोगकर्ताओं को एक जटिल संरचना बनाने की अनुमति देता है, लेकिन 95% मामलों में यह बहुत आसान है। मैंने जो किया है वह 2 रूपों का निर्माण करता था जो एक ही व्यूमोडेल का उपयोग करते हैं। उपयोगकर्ता सरल फॉर्म भरना शुरू कर सकते हैं, फिर उन्नत मोड पर स्विच कर सकते हैं, जो एक नया फॉर्म बनाता है, इसे व्यूमोडेल पास कर देता है।

साधारण सेटअप रूप में:

private void AdvancedSessionSetupButton_Click(object sender, RoutedEventArgs e) 
    { 
     PageManager.GetPageManager().Close(this); 
     PageManager.GetPageManager().Open(new CreateSessionPage(this.ViewModel), "Create Session"); 
    } 

उन्नत सेटअप रूप में:

private void BasicSessionSetupButton_Click(object sender, RoutedEventArgs e) 
    { 
     PageManager.GetPageManager().Close(this); 
     PageManager.GetPageManager().Open(new CreateBasicSessionPage(this.ViewModel), "Create Session"); 
    } 

PageManager.Close, केवल बातें प्रपत्र को संदर्भित करने के बाद ViewModel भीतर प्रतियोगिताएं हैं। मुझे लगता है कि वह जगह है जहां मुझे उन्हें अनदेखा करना चाहिए।

उत्तर

2

एक नाशक, और अधिक सामान्यतः के रूप में सी # प्रोग्रामर के लिए जाना जाता है:

this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted; 

आप एक नाशक लागू कर सकते हैं अंतिम मामले, इस मामले में आवश्यक नहीं है। यह मानते हुए कि ViewModel_LoadCompleted एक सदस्य फ़ंक्शन है, इसमें "यह" के लिए एक पॉइंटर होता है जिसे आप ViewModel ऑब्जेक्ट को दे रहे हैं जो पूरी तरह से "इस" द्वारा निहित है। कचरा कलेक्टर समझदारी से इसे अनदेखा करना चाहिए।

इस मामले में, सही काम करने के लिए उन्हें बाध्य करने का समय बर्बाद नहीं करना है।

आम तौर पर, जब आप "इस" (स्पष्ट रूप से, या निहित) को किसी ऑब्जेक्ट में पास करते हैं तो आपको किसी ईवेंट हैंडलर को अनबिंड करने की आवश्यकता होती है जो उस संदर्भ को "इस" के इच्छित जीवनकाल से अधिक समय तक रखेगी। उदाहरण के लिए, यदि आप अभिभावक नियंत्रण की घटना पर हैंडलर सेट करते हैं। अब माता-पिता के पास हैंडलर के साथ-साथ अपने बच्चों के नियंत्रण संग्रह में भी आपका संदर्भ है। इस मामले में, जब आप माता-पिता से हटाए जाते हैं तो आपको अनबिंड करना चाहिए।

संदेह में, निपटान करने के लिए कॉल में IDISposable और unbind लागू करें()।

+0

टाइपो, "अवरोधक" –

+0

क्या होगा यदि मेरा व्यूमोडेल उपयोगकर्ता नियंत्रण से अधिक समय तक रहता है? (मैं यह दिखाने के लिए प्रश्न संपादित करूंगा कि कैसे) – geofftnz

+0

यदि आपका मॉडल उपयोगकर्ता नियंत्रण से अधिक समय तक चलता है, तो आपको या तो अनबाइंडिंग के बारे में चिंता करने की आवश्यकता नहीं है। मॉडल को नियंत्रण का संदर्भ नहीं होना चाहिए। जब नियंत्रण गुंजाइश से बाहर हो जाता है, तो यह कचरा इकट्ठा किया जाएगा और अब मॉडल को इंगित नहीं करेगा। –

1

कचरा कलेक्टर आपके ऑब्जेक्ट के माध्यम से चला जाता है जब ईवेंट स्वचालित रूप से अनबाइंड होते हैं।

लेकिन आप स्पष्ट रूप से उन्हें निकल सकते हैं - किसी भी समय वाक्य रचना "=":

~MyPage 
{ 
    this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted; 
}