69

Windows Forms' CheckBox control implements both CheckedChanged and CheckStateChanged events. As far as I can tell, both fire when the checked status of the checkbox is changed.

CheckedChanged precedes CheckStateChanged, but other than that I see no difference. Am I missing something? Should one be preferred over another?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BojanG
  • 1,872
  • 1
  • 15
  • 23

6 Answers6

79

CheckState (and thus CheckStateChanged) allow for using a checkbox that can have three values: it can be checked, unchecked or 'indeterminate' - i.e. it has ThreeState set to true.

If you're not using ThreeState, then CheckedChanged is all you need.

stuartd
  • 70,509
  • 14
  • 132
  • 163
  • 3
    Its true! very simple, 2 step ( checked, unchecked ) use CheckedChanged, 3 step (checked, unchecked, indeterminate) use CheckStateChanged – Rizkiramadhani Aug 31 '19 at 08:26
  • What is `indeterminate` ??? The checkbox is either unchecked or checked, so what's the `indeterminate` thing? – Legends Oct 17 '19 at 18:10
  • See the link in the answer regarding the `ThreeState` property - _"[ThreeState] gets or sets a value indicating whether the CheckBox will allow **three check states** rather than two."_ The third state is [CheckState.Indeterminate](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.checkstate) - if i remember correctly, the checkbox gets filled in with a light gray colour when in that state. – stuartd Oct 17 '19 at 18:23
21

My guess would be that it has to do with tri-state checkboxes. This is the guts of the CheckState setter:

 if (this.checkState != value)
 {
   bool flag = this.Checked;
   this.checkState = value;
   if (base.IsHandleCreated)
   {
     base.SendMessage(0xf1, (int) this.checkState, 0);
   }
   if (flag != this.Checked)
   {
     this.OnCheckedChanged(EventArgs.Empty);
   }
   this.OnCheckStateChanged(EventArgs.Empty);
 }
Jacob G
  • 3,645
  • 1
  • 20
  • 25
14

The two events are effectively the same unless you set the ThreeState property to true. Without having set ThreeState, both will fire when the check box is checked or unchecked and both will fire after the value has changed.

The main difference is when you do set ThreeState to true, which adds the Indeterminate CheckState:

  • The control considers Indeterminate to be "checked". (Checked == true).
  • Transitioning between Checked and Unchecked is the same as before.
  • Transitioning between Checked and Indeterminate does not fire the CheckedChanged event, because Checked stays true.
  • Transitioning between Unchecked and Indeterminate does fire the CheckedChanged event, because Checked changes from false to true or vice-versa.
  • Clicking on a three state checkbox, the states transition from Unchecked to Checked to Indeterminate and back to Unchecked. You can still transition from Unchecked to Indeterminate programmatically.

(Note the difference between the Checked property, which is a two state boolean property, and the Checked state, which is one of the three possible values of the CheckState property.)

TL;DR: The main practical difference is that the CheckedChanged event doesn't fire on a three state checkbox when transitioning from CheckState.Checked to CheckState.Indeterminate or vice-versa, because both states are considered to be checked (Checked == true).

Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
0

Not an official answer to the question, but more of a follow-up comment.

I wanted to trigger 2 events when the CheckBox was clicked. In the Designer file, I could duplicate the line adding the event to the CheckedChanged, but as soon as I was modifying something in the Design screen, only the first event would be kept.

My solution was to add one event in CheckedChanged and the other to CheckStateChanged. Both events are now triggered when the CheckBox is clicked.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Marky
  • 1
-1

As far as I can tell:

CheckChanged is fired BEFORE the checked value is changed, so .Checked returns what the value WAS,

CheckStateChanged is fired AFTER the checked value is changed, so .Checkedreturns what the value IS

Frank Bryce
  • 8,076
  • 4
  • 38
  • 56
John Line
  • 77
  • 1
  • 2
-3

CheckState fires before the new value is committed. CheckStateChanged fires after the new value is committed.

If your looking for dataset.haschanges to do an update after a checkbox value modification you need to use checkstatechanged event. Just make sure to disable threestate to keep from issues with NULL getting in there.

TWood
  • 2,563
  • 8
  • 36
  • 58
  • 3
    This is false, both events fire after the value has been changed. – Dave Cousineau Jan 20 '17 at 16:58
  • @DaveCousineau I'm afraid TWood was correct. I had bound my checkbox's checked property to a public property in my form, with the binding set to update OnPropertyChange. When I tried using the CheckState event, the public property in the form had not yet updated. By the time the CheckStateChanged fired, however, the public property had been updated. Tangentially, the Click event fired after the two check-state events. For some reason, I thought it would fire first (from the general to the specific). – RobertSF Mar 09 '22 at 18:37
  • @RobertSF it's very easy to confirm. I suspect you and possibly this answer are referring to the WPF `CheckBox` which is not the same as the WinForms `CheckBox`. `OnPropertyChanged` is WPF as far as I know. But both of you refer to the non-existent `CheckState` event. There is no such event on either the WinForms or WPF `CheckBox` class or at least I can't find one. – Dave Cousineau Mar 09 '22 at 23:48
  • @DaveCousineau My bad for the careless wording. I do mean WinForms, but the events are `CheckedChanged` and `CheckedStateChanged`. If you bind the checkbox's `Checked` property to a public property in your form (to allow external access without making the control itself public), setting the public property to update `DataSourceUpdateMode.OnPropertyChanged` you should observe that `CheckedChanged` fires first, then the public property updates, and then `CheckedStateChanged` fires. Maybe I shouldn't access public properties from within their own class. Then this wouldn't be an issue. :) – RobertSF Mar 11 '22 at 04:40
  • @RobertSF I'm not sure what "bind" here means but the point is that from both events, the value of the checkbox's properties have already been updated, such that if you read the value of the property from the event, it is the new value not the old value. this is not always the case with some events and can be tricky to work around (usually the new value would be in the eventargs instead). you are probably just seeing your events fire in the order that you hooked them up. I may try to confirm or disconfirm tomorrow. – Dave Cousineau Mar 11 '22 at 07:42
  • @RobertSF reading the code, which Jacob G has also posted, it quite clearly sets the value and then raises the events. You say `CheckedChanged` fires first; well, the value was changed _before_ that event is raised, so all three of your events are occurring _after_ the value was changed. Your binding is probably working via the `CheckedChanged` event itself, and so it gets notified after your initial handler. But regardless of the order, none of these events are fired before the value is written. – Dave Cousineau Mar 11 '22 at 16:59
  • @DaveCousineau By "bind," I mean where you have a public property `public bool trimFirst { set; get; } = false;` and you bind it to the checkbox's `Checked` property with `chkTrimFirst.DataBindings.Add(new Binding("Checked", this, "trimFirst", false, DataSourceUpdateMode.OnPropertyChanged));` If you intercept the `CheckedChanged` event, the checkbox's `Checked` property will be current, but the public property won't. The public property is updated sometime after the `CheckedChanged` event and sometime before the `CheckedStateEvent`. – RobertSF Mar 12 '22 at 15:48
  • 1
    @RobertSF I'm not sure how the binding mechanism works internally, but the binding fires immediately after the property changed event fires, whichever one it is you bind to. The `CheckedChanged` event is fired before the `CheckStateChanged` event, so if you bind to `Checked`, your binding is in between the two events, but if you bind to `CheckState`, your binding is after them. But either way this is decidedly NOT before the value of the checkbox has been updated. In all cases the value of the checkbox is updated first and then various events may fire in some order, including your binding. – Dave Cousineau Mar 14 '22 at 16:25