Using the WinForms ListView, you are using a kind of dinosaur; it has its quirks. To get the result you want, this solution deals with those quirks:
private CheckState preCheckState;
private bool codeChangesCheckState = false;
private bool dontRecurse = false;
private bool initializing = true;
private void Form1_Load(object sender, System.EventArgs e)
{
initializing = false;
}
private void listView1_ItemCheck(object sender, ItemCheckEventArgs e)
{
if(! initializing && ! codeChangesCheckState) preCheckState = e.CurrentValue;
}
private void listView1_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (codeChangesCheckState || dontRecurse || initializing) return;
dontRecurse = true;
e.Item.Checked = preCheckState == CheckState.Checked;
dontRecurse = false;
}
Here's how/why this works:
1. the 'initialize flag is set to 'true, and prevents the quirk of the stupid ListView from not accurately displaying ALL the ListView Items which have been checked by the programmer at design-time when the app is run. Yes, that's a bug in the ListView.
2. the 'codeChangesCheckState flag is used to distinguish the user trying to change the CheckState of ListView Items at run-time, and your changing the value in your code.
3. the 'dontRecurse flag is used to avoid runaway recursion (stupid LIstView) when the CheckState change is "undone" in the 'ItemChecked event.
4. when the user changes the CheckState
at run-time, the Item's existing CheckState is recorded in the ItemCheck event, and the saved CheckState restored in the ItemChecked event.
In a better world all this would not be necessary: you would be able to cancel the CheckChange Event in the 'ItemCheck EventHandler ... as you can do with other WinForms Controls that provide Before_ and After_ EventHandlers :)