2013-07-09 8 views
5

पृष्ठभूमि निकाल दिया:निर्धारित जो एक घटना

मेरी WinForms रूप में, मैं एक चेक किए गए ListView और एक "मास्टर" चेकबॉक्स checkBoxAll कहा जाता है। गुरु के व्यवहार को इस प्रकार है: मास्टर जाँच या अनियंत्रित है

  • हैं, सभी ListViewItems तदनुसार को बदलना होगा।

  • यदि उपयोगकर्ता ListViewItem को अनचेक करता है, तो मास्टर को तदनुसार बदलना चाहिए।

  • यदि उपयोगकर्ता ListViewItem की जांच करता है, और अन्य सभी ListViewItems को भी चेक किया जाता है, तो मास्टर को तदनुसार बदलना चाहिए।

मैं इस व्यवहार की नकल के लिए निम्न कोड में लिखा है:

private bool byProgram = false; //Flag to determine the caller of the code. True for program, false for user. 

private void checkBoxAll_CheckedChanged(object sender, EventArgs e) 
{ 
    //Check if the user raised this event. 
    if (!byProgram) 
    { 
     //Event was raised by user! 

     //If checkBoxAll is checked, all listviewitems must be checked too and vice versa. 

     //Check if there are any items to (un)check. 
     if (myListView.Items.Count > 0) 
     { 
      byProgram = true; //Raise flag. 

      //(Un)check every item. 
      foreach (ListViewItem lvi in myListView.Items) 
      { 
       lvi.Checked = checkBoxAll.Checked; 
      } 

      byProgram = false; //Lower flag. 
     } 
    } 
} 

private void myListView_ItemChecked(object sender, ItemCheckedEventArgs e) 
{ 
    //Get the appropiate ListView that raised this event 
    var listView = sender as ListView; 

    //Check if the user raised this event. 
    if (!byProgram) 
    { 
     //Event was raised by user! 

     //If all items are checked, set checkBoxAll checked, else: uncheck him! 

     bool allChecked = true; //This boolean will be used to set the value of checkBoxAll 

     //This event was raised by an ListViewItem so we don't have to check if any exist. 
     //Check all items untill one is not checked. 
     foreach (ListViewItem lvi in listView.Items) 
     { 
      allChecked = lvi.Checked; 
      if (!allChecked) break; 
     } 

     byProgram = true; //Raise flag. 

     //Set the checkBoxAll according to the value determined for allChecked. 
     checkBoxAll.Checked = allChecked; 

     byProgram = false; //Lower flag. 
    } 
} 

इस उदाहरण में, मुझे यकीन है कि एक घटना उपयोगकर्ता द्वारा या नहीं कारण होता था बनाने के लिए एक ध्वज (byProgram) का उपयोग , इस प्रकार एक अनंत लूप को रोकता है (एक घटना दूसरे को आग लग सकती है, जो पहले बार आग लग सकती है आदि)। आईएमएचओ, यह एक हैकी समाधान है। मैंने चारों ओर खोज की लेकिन मुझे यह निर्धारित करने के लिए एक एमएसडीएन दस्तावेज विधि नहीं मिली कि उपयोगकर्ता को उपयोगकर्ता नियंत्रण कार्यक्रम सीधे निकाल दिया गया था या नहीं। जो मुझे अजीब (फिर से, आईएमएचओ) के रूप में हमला करता है।

मुझे पता है कि FormClosingEventArgs में एक फ़ील्ड है जिसका उपयोग हम यह निर्धारित करने के लिए कर सकते हैं कि उपयोगकर्ता फॉर्म बंद कर रहा है या नहीं।

वहाँ है एक तरह से (मेरे उदाहरण के अलावा अन्य) अगर एक घटना था निर्धारित करने के लिए: लेकिन जहाँ तक मुझे पता है, कि केवल EventArg कि कार्यक्षमता के इस प्रकार प्रदान करता है ...

सारांश में

तो है उपयोगकर्ता द्वारा सीधे निकाल दिया?

कृपया ध्यान दें: मेरा मतलब किसी घटना का प्रेषक नहीं है! इससे कोई फर्क नहीं पड़ता कि मैं कुछ चेकबॉक्स कोड करता हूं। चेक = सही; या मैन्युअल रूप से कुछ चेकबॉक्स सेट करें, ईवेंट का प्रेषक हमेशा कुछ चेकबॉक्स होगा। मैं यह जानना चाहता हूं कि यह निर्धारित करना संभव है कि यह उपयोगकर्ता (क्लिक) या प्रोग्राम (। चेक = सही) के माध्यम से था या नहीं।

आंड भी: इस प्रश्न को लिखने के लिए 30% समय प्रश्न और शीर्षक को सही तरीके से तैयार करना था। अभी भी यह सुनिश्चित नहीं है कि यह 100% स्पष्ट है, तो अगर आपको लगता है कि आप बेहतर कर सकते हैं तो कृपया संपादित करें :)

+0

बस एक जंगली अनुमान है, लेकिन वास्तव में EventArgs में कुछ होना चाहिए। क्या आपने रनटाइम (डीबगिंग) पर उनका निरीक्षण किया है? –

+0

क्लिक इवेंट पर एक ध्वज सेट करने के लिए यह पता है कि यह कॉल एक क्लिक से है, न कि कोड द्वारा? – MEYWD

+0

'प्रेषक' का प्रयोग करें? – DGibbs

उत्तर

2

यह कुछ मैं काफी एक बहुत कुछ के पार चलो है और मुझे क्या उपयोगकर्ता संपर्क कार्यक्रम बनाम के बीच यह विभाजित नहीं है की कोशिश करते हैं बातचीत - मैं अधिक सामान्य कोड का उपयोग करता हूं यानी यूआई अपडेट किया जा रहा है और किसी भी घटना को संभालने की आवश्यकता नहीं है। मैं आमतौर पर इसे BeginUpdate/EndUpdate विधियों के माध्यम से पैकेज करता हूं।

private int updates = 0; 

public bool Updating { get { return updates > 0; } } 

public void BeginUpdate() 
{ 
    updates++; 
} 

public void EndUpdate() 
{ 
    updates--; 
} 

public void IndividualCheckBoxChanged(...) 
{ 
    if (!Updating) 
    { 
     // run code 
    } 
} 

public void CheckAllChanged(...) 
{ 
    BeginUpdate(); 
    try 
    { 
     // run code 
    } 
    finally 
    { 
     EndUpdate(); 
    } 
} 
+1

+1, अभी भी एक ध्वज है, लेकिन अगली बार जब मुझे झंडा उठाना होगा तो मैं इस निर्माण का उपयोग करने जा रहा हूं। – Jordy

+0

@ जोर्डी यह * एक और * ध्वज नहीं है, यह अधिक संरचना और अर्थ जोड़कर आपके मौजूदा ध्वज पर एक सुधार है। 'BeginUpdate' /' EndUpdate' पैटर्न इस तरह की समस्या के लिए एक अच्छी तरह से उपयोग और अपनाया गया दृष्टिकोण है, विभिन्न विभिन्न प्लेटफ़ॉर्म (.NET शामिल) में। विचार यह है कि आप "राज्य" पर प्रतिक्रिया कर रहे हैं चाहे कोई घटना संलग्न हो या नहीं, यह अधिक पढ़ने योग्य कोड के लिए बनाता है। – James

+0

मुझे लगता है ... मुझे शायद इसे "अभी भी एक झंडा" के रूप में वर्णित नहीं किया जाना चाहिए था। लेकिन किसी कारण से मैं अपनी टिप्पणी संपादित नहीं कर सकता जब यह बहुत पुराना हो या कुछ: \ – Jordy

4

बदली हुई घटना का उपयोग करने के बजाय, आप क्लिक किए गए ईवेंट का उपयोग प्रासंगिक नियंत्रणों के माध्यम से परिवर्तन को कैस्केड करने के लिए कर सकते हैं। यह उपयोगकर्ता क्लिक के जवाब में होगा, और मूल्य को प्रोग्रामिक रूप से बदला नहीं जा रहा है।

+0

+1 एक समाधान देने के लिए जिसमें अतिरिक्त झंडे शामिल नहीं हैं। लेकिन क्या आपको पता है कि संपत्ति वास्तव में बदल गई है? इसमें पुराने मूल्यों को सही तरीके से संग्रहित करना शामिल होगा? – Jordy

+1

यदि मुझे सभी बॉक्स का चयन करने पर क्लिक किया गया ईवेंट मिलता है, तो मैं सभी चेकबॉक्स के मान सेट कर सकता हूं। यदि मुझे विकल्प आइटमों में से एक पर क्लिक किया गया ईवेंट मिलता है, तो मैं केवल विकल्पों की स्थिति के आधार पर सभी चेकबॉक्स का चयन कर रहा हूं। –

+0

आप सही हैं! मुझे मक्खन की परवाह नहीं है या मूल्य नहीं बदला है या नहीं बदला है। मैं सिर्फ उस मूल्य को देख सकता हूं जो वर्तमान में है। – Jordy

5

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

बीटीडब्ल्यू, byProgram सेट करने के बजाय आप एक और चीज कर सकते हैं।आप को हटाने और ईवेंट हैंडलर पहले जोड़ सकते हैं या, के बाद क्रमश: अपने नियंत्रण को बदल सकता है:

checkBoxAll.CheckedChanged -= checkBoxAll_CheckedChanged; 
// do something 
checkBoxAll.CheckedChanged += checkBoxAll_CheckedChanged; 
+0

यह वही है जो मैं नियमित रूप से करता हूं। – dotNET

+0

+1 एक समाधान देने के लिए जिसमें अतिरिक्त घटनाएं या झंडे शामिल नहीं हैं! – Jordy

+1

मैं तर्क दूंगा कि इस तरह से ईवेंट हैंडलरों को अलग करने/पुनः प्राप्त करने का कोई अच्छा विचार नहीं है। * मामूली * ओवरहेड के अलावा, यदि आपके पास 20 ईवेंट हैंडलर हैं तो क्या होगा? मुझे लगता है कि अवरुद्ध कोड बेहतर है क्योंकि आप "स्थिति" पर प्रतिक्रिया कर रहे हैं, चाहे कोई ईवेंट जुड़ा हुआ हो या नहीं, क्योंकि हमेशा ऐसा मौका होता है कि आप फिर से हटना या अलग करना चाहते हैं। – James

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