Which CheckedListBox event triggers after a item is checked?

前端 未结 12 463
攒了一身酷
攒了一身酷 2020-11-28 13:24

I have a CheckedListBox where I want an event after an item is checked so that I can use CheckedItems with the new state.

Since ItemChecked is fired before

相关标签:
12条回答
  • 2020-11-28 13:47

    Assuming you want to preserve the arguments from ItemCheck but get notified after the model was changed it should look like that:

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

    Where CheckedItemsChanged could be:

    private void CheckedItemsChanged(object sender, EventArgs e)
    {
        DoYourThing();
    }
    
    0 讨论(0)
  • 2020-11-28 13:47

    In normal behaviour, when we check one item, the item's check state will change before the event handler is raised. But a CheckListBox has a different behaviour: The event handler is raised before the check state of the item changes and that makes it difficult to correct our jobs.

    In my opinion, to solve this problem, we should defer the event handler.

    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());}
    
    0 讨论(0)
  • 2020-11-28 13:48

    Don't know if this applies but I wanted to use a checklistbox to filter results. So as the user checked and unchecked items I wanted the list to show\hide items.

    I was having some issues which led me to this post. Just wanted to share how I did it without anything special.

    Note: I have CheckOnClick = true but it would probably still work without

    The event I use is "SelectedIndexChanged"

    the enumeration I use is ".CheckedItems"

    This give the results I think we may expect. So simplified it comes down to ....

    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
            }
       }
    
    }
    
    0 讨论(0)
  • 2020-11-28 13:52

    Derive from CheckedListBox and implement

    /// <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);
    }
    
    0 讨论(0)
  • 2020-11-28 13:54

    I tried this and it worked:

    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();        
    }
    
    0 讨论(0)
  • 2020-11-28 13:57

    There are lots of related StackOverflow posts on this... As well as Branimir's solution, here are two more simple ones:

    Delayed execution on ItemCheck (also here):

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

    Using the MouseUp event:

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

    I prefer the first option, as the second would result in false positives (i.e. firing too often).

    0 讨论(0)
提交回复
热议问题