2010-11-10 8 views
8

के रूप में एक ईवेंट पास करना मुझे किसी फ़ंक्शन के पैरामीटर के रूप में एक ईवेंट पास करने की आवश्यकता है। क्या इसे करने का कोई तरीका है?वीबीएनईटी - एक पैरामीटर

कारण यह है कि मेरे पास कोड की दो पंक्तियों का अनुक्रम है जो मेरे पूरे कार्यक्रम में घिरा हुआ है, जहां मैं गतिशील रूप से एक ईवेंट में हैंडलर को हटा देता हूं, और फिर हैंडलर को फिर से सेट करता हूं। मैं इसे कई अलग-अलग आयोजनों और ईवेंट हैंडलर के लिए कर रहा हूं, इसलिए मैंने ऐसा फ़ंक्शन लिखने का निर्णय लिया है जो ऐसा करता है।

उदाहरण के लिए, मान लीजिए कि मैं ComboBox1 बुलाया मेरी कोड में एक combobox है, और मुझे हैंडलर indexChangedHandler बुलाया डालते हैं। मेरी कोड के कई स्थानों में, मैं दो पंक्तियों निम्नलिखित है:

RemoveHandler combobox1.SelectedIndexChanged, AddressOf indexChangedHandler 
AddHandler combobox1.SelectedIndexChanged, AddressOf indexChangedHandler 

अब, मैं कोड (या समान) मेरे सभी कार्यक्रम से अधिक की ऊपर दो पंक्तियों दोहराते रखने के लिए नहीं करना चाहते हैं, तो मैं ' मीटर यह करने के लिए एक रास्ता तलाश:

setHandler(combobox1.SelectedIndexChanged, AddressOf indexChangedHandler) 

अब तक:

Private Sub setHandler(evt As Event, hndler As eventhandler) 
    RemoveHandler evt, hndler 
    AddHandler evt, hndler 
End Sub 

ताकि हर जगह जहां कोड (या समान) के उन दो पंक्तियों मेरा कार्यक्रम में पाए जाते हैं, मैं सिर्फ उन लोगों के साथ की जगह ले सकता ए के "घटना के रूप में evt" भाग सेट हैंडलर फ़ंक्शन का rgument एक त्रुटि दे रहा है।

पी.एस: मैं अन्य मंचों के एक जोड़े पर इस प्रश्न पूछा और कहा जा रहा रखने के कारण है कि मैं इसे हटाने के तुरंत बाद हैंडलर सेट करना चाहते हैं है। इसका कारण यह है कि ईवेंट ईवेंट होने पर गतिशील रूप से एक ईवेंट हैंडलर एन-टाइम्स को हैंडलर को एन-बार निष्पादित करने का कारण बनता है। इससे बचने के लिए, यह सुनिश्चित करने के लिए कि ईवेंट होने पर हैंडलर को केवल एक बार निष्पादित किया जाता है, मैं हर बार हैंडलर को गतिशील रूप से जोड़ना चाहता हूं।

आप पूछ सकते हैं कि हैंडलर को पहली बार क्यों कई बार जोड़ा जाएगा ... कारण यह है कि मैं केवल एक विशेष घटना के बाद हैंडलर जोड़ता हूं, ई 1 कहता हूं, मेरे फॉर्म में हुआ है (मैं हैंडलर जोड़ता हूं घटना ई 1 के हैंडलर के भीतर)। और घटना ई 1 मेरे रूप में कई बार हो सकती है। यदि मैं इसे फिर से जोड़ने से पहले हर बार हैंडलर को नहीं हटाता, तो हैंडलर जोड़ा जाता है और इस प्रकार कई बार निष्पादित किया जाता है।

जो भी मामला, प्रसंस्करण समारोह के भीतर होने नहीं मेरे लिए परम महत्व के इस समय है, बल्कि सिर्फ एक पैरामीटर के रूप में एक घटना में उत्तीर्ण होने की व्यवस्था होनी चाहिए।

+1

क्या आप हमें बता सकते हैं कि त्रुटि क्या है? –

+0

इस प्रोग्राम को करने का कोई वास्तविक तरीका नहीं है, क्योंकि आप किसी ईवेंट सदस्य के संदर्भ पास नहीं कर सकते हैं। मुझे यह भी बिल्कुल यकीन नहीं है कि सेटहैंडलर क्या करना चाहता है ... क्या आप स्पष्टीकरण दे सकते हैं कि आपको इवेंट हैंडलर को हटाने की आवश्यकता क्यों होगी और फिर इसे फिर से जोड़ें? – cdhowie

+0

@cdhowie मैं अपनी पोस्ट को संपादित करने की प्रक्रिया में था, यह समझाने के लिए कि मुझे ऐसा करने की आवश्यकता क्यों है, बाधित हो गया है, वापस आ गया है और संपादन पूरा कर लिया है और सबमिट कर लिया है, इससे पहले कि आप पहले से ही सवाल पूछ चुके हैं। लंबी कहानी छोटी, कारण अब मूल पोस्ट में शामिल है :) – Tracer

उत्तर

10
पाठ्यक्रम आप के आसपास की घटनाओं पारित कर सकते हैं के

... वैसे आप Action(Of EventHandler) पारित कर सकते हैं जो आप क्या चाहते हैं कर सकते हैं।

आप एक वर्ग है कि इतनी तरह की एक घटना को परिभाषित करता है है:

Public Class ComboBox 
    Public Event SelectedIndexChanged As EventHandler 
End Class 

आप तो बना सकते हैं ComboBox का एक उदाहरण तो तरह & निकालें हैंडलर कार्यों जोड़ने को देखते हुए: (

Dim combobox1 = New ComboBox() 

Dim ah As Action(Of EventHandler) 
    = Sub (h) AddHandler combobox1.SelectedIndexChanged, h 
Dim rh As Action(Of EventHandler) 
    = Sub (h) RemoveHandler combobox1.SelectedIndexChanged, h 

अब, यह वीबीएनईटी 4.0 कोड है, लेकिन आप इसे AddressOf का उपयोग करके 3.5 में कर सकते हैं और इसके बारे में थोड़ा और मजाक कर सकते हैं।)

तो अगर मैं हा

Public Sub Foo(ByVal sender as Object, ByVal e As EventArgs) 
    Console.WriteLine("Over here with Foo!") 
End Sub 

और ComboBox पर एक Raise विधि मैं अब यह कर सकते हैं: कोई हैंडलर Foo ve "! फू के साथ यहाँ से अधिक"

ah(AddressOf Foo) 
combobox1.Raise() 
rh(AddressOf Foo) 

यह संदेश लिखते हैं जैसा सोचा था।

मैं भी इस विधि बना सकते हैं:

Public Sub PassActionOfEventHandler(ByVal h As Action(Of EventHandler)) 
    h(AddressOf Foo) 
End Sub 

मैं बहुत तरह ईवेंट हैंडलर कदमों के अनुसार पारित कर सकते हैं:

PassActionOfEventHandler(ah) 
combobox1.Raise() 
PassActionOfEventHandler(rh) 

कौन सा फिर से संदेश लिखते हैं, "फू के साथ यहाँ से अधिक!"।

अब, एक समस्या यह हो सकती है कि समस्या हो सकती है कि आप गलती से जोड़ों को स्वैप कर सकते हैं और कोड हैंडलर प्रतिनिधियों को कोड में हटा सकते हैं - आखिरकार वे एक ही प्रकार के हैं। तो यह सिर्फ ऐड के लिए दृढ़ता से टाइप प्रतिनिधियों को परिभाषित करने और इसलिए जैसे कार्यों को हटाने के लिए आसान है:

Public Delegate Sub AddHandlerDelegate(Of T)(ByVal eh as T) 
Public Delegate Sub RemoveHandlerDelegate(Of T)(ByVal eh as T) 

प्रतिनिधि उदाहरणों को परिभाषित करने के प्रतिनिधि प्रकार के लिए छोड़कर नहीं बदलता है कोड:

Dim ah As AddHandlerDelegate(Of EventHandler) 
    = Sub (h) AddHandler combobox1.SelectedIndexChanged, h 
Dim rh As RemoveHandlerDelegate(Of EventHandler) 
    = Sub (h) RemoveHandler combobox1.SelectedIndexChanged, h 

तो यह अब आपको बहुत रचनात्मक बनने देता है। आप एक ऐसे फ़ंक्शन को परिभाषित कर सकते हैं जो एड हैंडलर प्रतिनिधि, हटाए हैंडलर प्रतिनिधि और एक ईवेंट हैंडलर लेगा, जो एक ईवेंट हैंडलर को वायर-अप करेगा, और उसके बाद आपको IDisposable पर वापस लौटाएगा जिसे आप बिना किसी आवश्यकता के हैंडलर को हटाने के लिए उपयोग कर सकते हैं घटना हैंडलर के लिए एक संदर्भ बनाए रखें। यह Using कथन का उपयोग करने के लिए आसान है।

Function SubscribeToEventHandler(
    ByVal h as EventHandler, 
    ByVal ah As AddHandlerDelegate(Of EventHandler), 
    ByVal rh As RemoveHandlerDelegate(Of EventHandler)) As IDisposable 

तो यह समारोह अब मैं यह कर सकता हूँ दिया:

यहाँ हस्ताक्षर है

combobox1.Raise() 
Using subscription = SubscribeToEventHandler(AddressOf Foo, ah, rh) 
    combobox1.Raise() 
    combobox1.Raise() 
End Using 
combobox1.Raise() 

और यह संदेश लिखते हैं, "फू के साथ यहाँ से अधिक!" केवल दो बार पहली और आखिरी Raise कॉल ईवेंट हैंडलर की सदस्यता के बाहर हैं।

आनंद लें!

+1

यदि मैं इस अधिकार को समझता हूं, तो आप प्रश्न में पूछे गए अनुसार 'घटनाक्रम' नहीं, बल्कि 'डेलीगेट्स' पास कर रहे हैं। फिर भी एक बहुत अच्छा जवाब। – Bobby

+0

इनिग्मैटीविटी, आपके विस्तृत उत्तर के लिए धन्यवाद। यद्यपि मुझे समझने के लिए कुछ मुश्किल था, क्योंकि मैंने आपकी पोस्ट में कुछ अजीब दिखने वाली संरचनाएं देखी हैं (इस तरह के वाक्यविन्यास को देखने का मेरा पहला समय, तो कृपया मेरे साथ बेकार)। लेकिन जो मैंने समझा है, उससे मुझे हमेशा "आह" और "rh" में ऑब्जेक्ट और ईवेंट को स्पष्ट रूप से परिभाषित करना होगा? मैं क्या जानना चाहता हूं, वैसे भी "आह" की परिभाषा को "combobox1.selectedIndexChanged" तक सीमित नहीं किया गया है, ताकि मैं हैंडलर को एक अलग ऑब्जेक्ट (cbx2) पर सेट करने के लिए थैम फ़ंक्शन का उपयोग कर सकूं, कहें, " cbx2.selectedIndexChanged "। – Tracer

+0

@ 'ट्रैसर' - हां। बस प्रतिनिधियों की परिभाषाओं को 'पब्लिक डिलीगेट सब एडहैंडलर डिलेगेट (टी में) में बदलें (टी द्वारा वीवल एएच, कॉम्बोबॉक्स कॉम्बोबॉक्स के रूप में)' और आप इसे किसी भी 'कॉम्बोबॉक्स' के लिए काम कर सकते हैं। यदि आपको अन्य कार्यक्रम करना है तो मैं प्रतिनिधि को 'AddSelectedIndexChangedHandler' आदि को कॉल करने का सुझाव दूंगा। प्रत्येक ईवेंट और नियंत्रण के लिए प्रतिनिधि जोड़ें और निकालें। – Enigmativity

2

आप घटनाओं को पारित नहीं कर सकते हैं। Event एक प्रकार का नहीं है, यह एक ऐसा कीवर्ड है जो कक्षाओं के ईवेंट सदस्य की स्थिति को बदलने के लिए उपयोग की जाने वाली विधियों की एक जोड़ी को जोड़ता है और हटा देता है। वे इस संबंध में गुणों की तरह बहुत अधिक हैं (जो प्राप्त और सेट विधियां हैं)।

गुण की तरह

, जोड़ और निकाल तरीकों जो चाहो कर सकते हैं। आम तौर पर, ये एक प्रतिनिधि उदाहरण बनाए रखने के अलावा कुछ भी नहीं करेंगे, जो स्वयं MulticastDelegate है या दूसरे शब्दों में, प्रतिनिधियों की एक सूची जो घटना को उठाए जाने पर एक-एक करके बुलाया जा रहा है।

आप स्पष्ट रूप से सी #, जहां यह AddHandler/RemoveHandler साथ नकाबपोश नहीं है में इस संरचना देख सकते हैं, लेकिन आप सीधे संबद्ध संचालकों की सूची को संपादित: myObject.Event += new Delegate(...);

और, फिर गुण की तरह, एक वर्ग है कि वास्तव में दो अलग अलग तरीकों सार सदस्य होने, यह संभव नहीं सचमुच एक वस्तु के रूप में एक घटना पारित करने के लिए है।

+0

उस स्पष्टीकरण के लिए धन्यवाद, बॉबी। – Tracer

2

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

एकमात्र ऐसी स्थिति जहां मैं देख सकता हूं कि आपके द्वारा वर्णित एक घटना को पारित करने के लिए उपयोगी हो सकता है, जो IDisposable ऑब्जेक्ट की तरह होगा जो लंबे समय तक रहने वाली वस्तुओं से होने वाली घटनाओं की सदस्यता लेता है, और जिसके लिए सभी को सदस्यता समाप्त करने की आवश्यकता है इसकी घटनाओं का निपटारा होने पर। उस स्थिति में, प्रत्येक ईवेंट के लिए निकालने-प्रतिनिधि विधि लाने के लिए प्रतिबिंब का उपयोग करना सहायक हो सकता है, और उसके बाद ऑब्जेक्ट का निपटारा होने पर सभी हटा-प्रतिनिधि विधियों को कॉल करें। दुर्भाग्यवश, मुझे स्ट्रिंग अक्षर के अलावा पुनर्प्राप्त किए जाने वाले ईवेंट का प्रतिनिधित्व करने का कोई तरीका नहीं है, जिसका वैधता रन-टाइम तक चेक नहीं किया जा सका।