किसी आइटम की जाँच के बाद कौन सा CheckedListBox ईवेंट ट्रिगर होता है?


96

मेरे पास एक CheckedListBox है जहां मैं एक आइटम की जांच के बाद एक घटना चाहता हूं ताकि मैं नए राज्य के साथ CheckedItems का उपयोग कर सकूं।

चूंकि ItemChecked को CheckedItems से पहले निकाल दिया गया है, इसलिए यह बॉक्स से बाहर काम नहीं करेगा।

CheckedItems अपडेट होने पर मैं किस प्रकार की विधि या घटना को अधिसूचित करने के लिए उपयोग कर सकता हूं?

जवाबों:


89

आप ItemCheckईवेंट का उपयोग कर सकते हैं , यदि आप उस आइटम की नई स्थिति की भी जांच करते हैं जिसे क्लिक किया जा रहा है। इस घटना args में उपलब्ध है, के रूप में e.NewValue। यदि NewValueजाँच की जाती है, तो अपने तर्क में संग्रह के साथ-साथ वर्तमान आइटम को भी शामिल करें:

    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
    {                     
        List<string> checkedItems = new List<string>();
        foreach (var item in checkedListBox1.CheckedItems)
            checkedItems.Add(item.ToString());

        if (e.NewValue == CheckState.Checked)
            checkedItems.Add(checkedListBox1.Items[e.Index].ToString());
        else
            checkedItems.Remove(checkedListBox1.Items[e.Index].ToString());

        foreach (string item in checkedItems)
        {
            ...
        }
    }

एक अन्य उदाहरण के रूप में, यह निर्धारित करने के लिए कि इस मद के बाद संग्रह खाली हो जाएगा (अन-) की जाँच की गई:

private void ListProjects_ItemCheck(object sender, ItemCheckEventArgs args)
{
    if (ListProjects.CheckedItems.Count == 1 && args.NewValue == CheckState.Unchecked)
        // The collection is about to be emptied: there's just one item checked, and it's being unchecked at this moment
        ...
    else
        // The collection will not be empty once this click is handled
        ...
}

3
प्रत्येक के लिए पहली में, हमें एक शर्त जोड़ने की आवश्यकता हो सकती है ..if not item = checkedListBox1.Items[e.Index].ToString()
लेनिन राज राजसेकरन

8
समस्या यह है कि चेक संसाधित होने से पहले ItemCheck इवेंट निकाल दिया जाता है। आपके समाधान में अपनी सूची रखना अनिवार्य रूप से मानक कोड की नकल करना होगा। डनक का पहला सुझाव (मदचेक पर विलंबित निष्पादन) फक के सवाल का सबसे साफ जवाब है, क्योंकि इसमें किसी भी अतिरिक्त हैंडलिंग की आवश्यकता नहीं है।
बेरेंड एंगेलब्रैच

35

इस पर संबंधित StackOverflow पोस्ट के बहुत सारे हैं ... साथ ही साथ ब्रानिमिर के समाधान, यहाँ दो और सरल हैं:

मदचेक पर विलंबित निष्पादन ( यहां भी ):

    void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        this.BeginInvoke((MethodInvoker) (
            () => Console.WriteLine(checkedListBox1.SelectedItems.Count)));
    }

माउसअप घटना का उपयोग करना :

    void checkedListBox1_MouseUp(object sender, MouseEventArgs e)
    {
        Console.WriteLine(checkedListBox1.SelectedItems.Count);
    }

मैं पहला विकल्प पसंद करता हूं, क्योंकि दूसरा झूठी सकारात्मकता का परिणाम देगा (यानी अक्सर फायरिंग)।


13
दूसरी विधि भी कीबोर्ड के माध्यम से चेक या अनचेक की जा रही वस्तुओं को याद करेगी।

1
बिगिनवोक वास्तव में वही था जिसकी मुझे जरूरत थी क्योंकि मेरी घटना वास्तव में एक इंटरफेस को बुला रही थी, जिसे पता नहीं था कि यह किस तरह के नियंत्रण के साथ काम कर रहा था। स्वीकृत जवाब केवल मामलों में काम करता है जबकि तर्क को घटना हैंडलर के भीतर किया जा सकता है, या सीधे घटना हैंडलर से कुछ कहा जा सकता है। मेरे लिए ऐसा नहीं था। इस भयानक अभी तक सरल समाधान के लिए धन्यवाद।
जेसी

Thx, BeginInvoke के साथ पहला विकल्प मेरे लिए काम करता है। शायद एक मूर्ख टिप्पणी करने वाले लोग .. लेकिन 2010 में शुरू किए गए एक विषय में 2018 में हल क्यों नहीं किया गया है ??
आकर्षण आते

1
@Goodies सहमत थे, हालांकि मुझे लगता है कि अगर Microsoft ने अब व्यवहार को बदल दिया तो यह बहुत सारे कोड तोड़ सकता है। डॉक्स स्पष्ट रूप से यह The check state is not updated until after the ItemCheck event occurs। एक अलग घटना या गैर-मनमाना वर्कअर्म अच्छा IMO होगा।
डनक

24

मैंने यह कोशिश की और यह काम किया:

private void clbOrg_ItemCheck(object sender, ItemCheckEventArgs e)
{
    CheckedListBox clb = (CheckedListBox)sender;
    // Switch off event handler
    clb.ItemCheck -= clbOrg_ItemCheck;
    clb.SetItemCheckState(e.Index, e.NewValue);
    // Switch on event handler
    clb.ItemCheck += clbOrg_ItemCheck;

    // Now you can go further
    CallExternalRoutine();        
}

8
यह! ... सही उत्तर होना चाहिए, जो सबसे दुर्भाग्यपूर्ण है। यह एक हास्यास्पद हैक है जो काम करता है क्योंकि एम $ पर कोई व्यक्ति ItemCheckedघटना को लागू करने के लिए भूल गया , और किसी ने कभी भी संबोधित नहीं किया कि यह मौजूद नहीं था।
RLH

हालाँकि यह परिभाषा नहीं है कि यह बग मुझे लगता है कि इसे लागू किया जाना चाहिए, यदि आप +1 पर क्लिक करके इस बग रिपोर्ट का समर्थन करने पर विचार करते हैं: connect.microsoft.com/VisualStudio/feedback/details/1759293
SCBuergel .eth

@ सेबस्टियन - यहां फिक्स के लिए मत पूछो। इसका कोई भी "समाधान" बाहर निकलने के समाधान को तोड़ देगा। अगर वहाँ दो घटनाओं थे: ItemChecking, ItemChecked, तो आप बाद के किसी एक का उपयोग कर सकता है। लेकिन अगर केवल एक को लागू किया जाता है ( ItemCheck) यह चीजों को सही तरीके से कर रहा है, अर्थात मान से पहले घटना की फायरिंग की जाती है, तो नए मान और पैरामीटर के रूप में आपूर्ति किए गए सूचकांक के साथ जांच की जाती है। जो भी "परिवर्तन के बाद" घटना चाहते हैं, वे बस ऊपर का उपयोग कर सकते हैं। यदि Microsoft को कुछ सुझाते हैं, तो एक नई घटना का सुझाव दें ItemChecked, मौजूदा के परिवर्तन का नहीं: diimdeep का उत्तर देखें
miroxlav

इस तरह, लेकिन एक मामूली विकल्प जो मैं हर समय उपयोग करता हूं वह है किसी प्रकार का "स्किप" ध्वज सेट करने के लिए ताकि SetItemCheckState उसी घटना को फिर से ट्रिगर न करे। या तो एक साधारण वैश्विक, या मुझे जो करना पसंद है वह टैग के बारे में सुनिश्चित करना है। उदाहरण के लिए, यदि कोई myCheckListBox.Tag! = null में एक्शन को लपेटता है, और फिर इवेंट Delete \ Add के स्थान पर, बस टैग को कुछ (यहां तक ​​कि एक खाली स्ट्रिंग) पर सेट करें और फिर इसे वापस चालू करने के लिए वापस करने के लिए नल करें।
दा_जोकर

10

से CheckedListBoxलागू करें और लागू करें

/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.CheckedListBox.ItemCheck"/> event.
/// </summary>
/// <param name="ice">An <see cref="T:System.Windows.Forms.ItemCheckEventArgs"/> that contains the event data.
///                 </param>
protected override void OnItemCheck(ItemCheckEventArgs e)
{           
    base.OnItemCheck(e);

    EventHandler handler = AfterItemCheck;
    if (handler != null)
    {
        Delegate[] invocationList = AfterItemCheck.GetInvocationList();
        foreach (var receiver in invocationList)
        {
            AfterItemCheck -= (EventHandler) receiver;
        }

        SetItemCheckState(e.Index, e.NewValue);

        foreach (var receiver in invocationList)
        {
            AfterItemCheck += (EventHandler) receiver;
        }
    }
    OnAfterItemCheck(EventArgs.Empty);
}

public event EventHandler AfterItemCheck;

public void OnAfterItemCheck(EventArgs e)
{
    EventHandler handler = AfterItemCheck;
    if (handler != null)
        handler(this, e);
}

BeginInvokeदूसरे जवाब से समाधान का उपयोग करते समय आप बहुत सारे अतिरिक्त कोड छोड़ सकते हैं।
17ukasŁ Fronczyk

4

हालांकि आदर्श नहीं है, आप चेकडाइम को गणना कर सकते हैं जो कि ItemCheckघटना के माध्यम से पारित किए गए तर्कों का उपयोग करते हैं । यदि आप MSDN पर इस उदाहरण को देखते हैं , तो आप यह पता लगा सकते हैं कि क्या नई बदली गई वस्तु की जाँच की गई है या अनियंत्रित है, जो आपको वस्तुओं के साथ काम करने के लिए उपयुक्त स्थिति में छोड़ती है।

आप एक नया ईवेंट भी बना सकते हैं, जो किसी आइटम की जाँच के बाद फायर करता है, जो आपको वही देगा जो आप चाहते हैं।


1
क्या आपको कोई विशिष्ट विचार मिला है कि यह नया ईवेंट कैसे बनाया जा सकता है, मुझे कैसे पता चलेगा जब ItemChecke ईवेंट के बाद CheckedItems को अपडेट किया गया है?
हॉल्टकविस्ट

4

कुछ परीक्षणों के बाद, मैं देख सकता था कि इवेंट ItemCheck के बाद इवेंट SelectIndexChanged चालू हो गया है। संपत्ति CheckOnClick सच रखें

बेस्ट कोडिंग


आप सही हैं, यह सबसे आसान तरीका है। लेकिन यह अभी भी एक हैक की तरह कुछ है, क्योंकि यह अनिर्दिष्ट और अस्पष्टीकृत व्यवहार है। Microsoft में कोई भी नया व्यक्ति सोच सकता है: ओह ठीक है, क्यों केवल चयनित चेकस्टैट में परिवर्तन होने पर SelectIndexChanged में आग लग जाती है। चलो कि अनुकूलन करते हैं। और बैंग आपका कोड चला जाता है :(
रॉल्फ

इसके अतिरिक्त, जब आप चेक स्टेट को प्रोग्रामेटिक रूप से बदलते हैं तो SelectIndexChanged फायर नहीं करता है।
रॉल्फ

1
और जब आप स्पेस की के साथ चेक स्टेट को बदलते हैं तो यह फायर नहीं करता है। इसका उपयोग करना गलत है।
एल्म्यू

2

यह काम करता है, हालांकि यह सुनिश्चित नहीं है कि यह कितना सुंदर है!

Private Sub chkFilters_Changed(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkFilters.ItemCheck
    Static Updating As Boolean
    If Updating Then Exit Sub
    Updating = True

    Dim cmbBox As CheckedListBox = sender
    Dim Item As ItemCheckEventArgs = e

    If Item.NewValue = CheckState.Checked Then
        cmbBox.SetItemChecked(Item.Index, True)
    Else
        cmbBox.SetItemChecked(Item.Index, False)
    End If

    'Do something with the updated checked box
    Call LoadListData(Me, False)

    Updating = False
End Sub

1

पता नहीं कि यह लागू होता है, लेकिन मैं परिणामों को फ़िल्टर करने के लिए एक चेकलिस्टबॉक्स का उपयोग करना चाहता था। इसलिए जैसा कि उपयोगकर्ता ने चेक किया और अनियंत्रित आइटम मैं सूची को आइटम छिपाने के लिए दिखाना चाहता था।

मैं कुछ मुद्दों पर चल रहा था, जो मुझे इस पद तक ले गए। बस यह साझा करना चाहता था कि मैंने इसे बिना किसी विशेष के कैसे किया।

नोट: मेरे पास CheckOnClick = true है, लेकिन यह शायद अभी भी बिना काम करेगा

मेरे द्वारा उपयोग की जाने वाली घटना " SelectIndexChanged " है

मेरे द्वारा उपयोग की जाने वाली गणना " .CheckedItems " है

यह उन परिणामों को देता है जो मुझे लगता है कि हम उम्मीद कर सकते हैं। तो सरलीकृत यह नीचे आता है ...।

private void clb1_SelectedIndexChanged(object sender, EventArgs e)
{
   // This just spits out what is selected for testing
   foreach (string strChoice in clb1.CheckedItems)
   {
      listBox1.Items.Add(strChoice);
   }

   //Something more like what I'm actually doing
   foreach (object myRecord in myRecords)
   {
        if (clb1.CheckItems.Contains(myRecord["fieldname"])
        {
            //Display this record
        }
   }

}

जब उपयोगकर्ता स्थान की कुंजी के साथ चेक स्टेट को बदलता है, तो SelectIndexChanged फायर नहीं करता है।
एल्म्यू

कॉल में कोई आइटम चेक या अनचेक करने के लिए Callin SetItemChecked करने पर SelectIndexChanged में आग नहीं लगती।
bkqc

1

यह मानते हुए कि आप ItemCheckमॉडल को बदलने के बाद तर्कों को संरक्षित करना चाहते हैं, लेकिन इस तरह दिखना चाहिए:

CheckedListBox ctrl = new CheckedListBox();
ctrl.ItemCheck += (s, e) => BeginInvoke((MethodInvoker)(() => CheckedItemsChanged(s, e)));

कहां CheckedItemsChangedहो सकता है:

private void CheckedItemsChanged(object sender, EventArgs e)
{
    DoYourThing();
}

0

मैंने यह कोशिश की और यह काम किया:

    private List<bool> m_list = new List<bool>();
    private void Initialize()
    {
        for(int i=0; i < checkedListBox1.Items.Count; i++)
        {
            m_list.Add(false);
        }
    }

    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        if (e.NewValue == CheckState.Checked)
        {
            m_list[e.Index] = true;
            checkedListBox1.SetItemChecked(e.Index, true);
        }
        else
        {
            m_list[e.Index] = false;
            checkedListBox1.SetItemChecked(e.Index, false);
        }
    }

सूची के सूचकांक द्वारा निर्धारित।


-1

मैं इस समस्या को हल करने के लिए एक टाइमर का उपयोग करता हूं। ItemCheck इवेंट के माध्यम से टाइमर को सक्षम करें। टाइमर की टिक घटना में कार्रवाई करें।

यह काम करता है कि आइटम को माउस क्लिक के माध्यम से चेक किया गया है या स्पेस-बार दबाकर। हम इस तथ्य का लाभ उठाएंगे कि आइटम केवल चेक किया गया (या अन-चेक किया गया) हमेशा चयनित आइटम है।

टाइमर का अंतराल 1. जितना कम हो सकता है, टिक इवेंट के उठने तक, नया चेक किया गया स्टेटस सेट हो जाएगा।

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

इसलिए हम सबसे पहले ItemCheck इवेंट में टाइमर को अक्षम करते हैं। अक्षम करें फिर अंतराल अवधि को फिर से शुरू करने के लिए सक्षम करें।

Private Sub ckl_ItemCheck(ByVal sender As Object, _
                          ByVal e As System.Windows.Forms.ItemCheckEventArgs) _
    Handles ckl.ItemCheck

tmr.Enabled = False
tmr.Enabled = True

End Sub


Private Sub tmr_Tick(ByVal sender As System.Object, _
                     ByVal e As System.EventArgs) _
    Handles tmr.Tick

tmr.Enabled = False
Debug.Write(ckl.SelectedIndex)
Debug.Write(": ")
Debug.WriteLine(ckl.GetItemChecked(ckl.SelectedIndex).ToString)

End Sub

1
साझा करने के लिए आपको धन्यवाद। दूसरे तरीके पर, शायद आप अन्य उत्तरों से बेहतर समाधान सीख सकते हैं। टाइमर का उपयोग करना अपेक्षाकृत जटिल है और इस मामले में यह काम के लिए गलत उपकरण है, क्योंकि आप वास्तव में पहले से ही पैरामीटर के रूप में नए मान प्राप्त कर रहे हैं। तो आप या तो इस उत्तर का उपयोग एकतरफा समाधान के लिए कर सकते हैं या यह व्यवस्थित समाधान के लिए। एक ऑनलाइन रूपांतरण उपकरण का उपयोग करके उन्हें C # से VB में कनवर्ट करें।
miroxlav

-1

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

मेरी राय में, इस समस्या को हल करने के लिए, हमें ईवेंट हैंडलर को स्थगित करना चाहिए।

private void _clb_ItemCheck(object sender, ItemCheckEventArgs e) {
 // Defer event handler execution
 Task.Factory.StartNew(() => {
     Thread.Sleep(1000);
     // Do your job at here
 })
 .ContinueWith(t => {
     // Then update GUI at here
 },TaskScheduler.FromCurrentSynchronizationContext());}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.