Home > Mobile >  How can I toggle the checkbox of an item in a CheckedListbox if CheckOnClick is True, but SelectionM
How can I toggle the checkbox of an item in a CheckedListbox if CheckOnClick is True, but SelectionM

Time:05-16

How can I toggle the checkbox of an item in a CheckedListbox if CheckOnClick is True, but SelectionMode is None..?

If I set SelectionMode to One it works as expected, but I would like to prevent items in the list from being selected. The only purpose of the CheckedListbox is to use the checkboxes; having items selected is not desired.

I tried a bit of code with the various Click and Mouse events, but none of them seem to report the item in the list that was clicked. If I could determine that, it would be a simple matter to toggle the checkbox of the clicked item.

CodePudding user response:

The MouseClick event will tell you when the control was clicked and where. Determine whether the click was on an item and which one, then toggle it:

Private Sub CheckedListBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles CheckedListBox1.MouseClick
    Dim clickedIndex = CheckedListBox1.IndexFromPoint(e.X, e.Y)

    If clickedIndex <> ListBox.NoMatches Then
        CheckedListBox1.SetItemChecked(clickedIndex, Not CheckedListBox1.GetItemChecked(clickedIndex))
    End If
End Sub

CodePudding user response:

After a little testing, I would say that you need to consider “how” you want to achieve the non-selection mode you describe. As you have noted, if you set the CheckedListBoxes SelectionMode to None… then basically the check boxes become unusable.

The user cannot check or un-check any check box, as you already know… and this is why you want “your” code to change the check boxes checked state. So, you have now inherited the job of changing the check boxes check state because you set its “SelectionMode” to “None" … ? …

In addition, when the selection mode is set to “None” … then many “typical” properties of the CheckedListBox will lose functionality and become useless. Example, the checked list boxes SelectedItem property will always be null and its SelectedIndex property will most likely always be -1. Meaning, most “selection” type events will need to find what item was clicked by using the mouse location as shown in another answer.

The main point here is that when you decided to set the checked list boxes selection mode to “None”, then you basically open the door for more coding/responsibility on your part as far as “managing” the checked list box. I am just saying that the out-of-the-box .Net CheckedListBox is not feature rich and is a basic control. I am guessing there “may” be a third-party CheckedListBox Control that may have this “non-selected” functionality built-in.

So… I suggest another approach… however… it also has some drawbacks… basically you have to create a new Class MyCheckedListBox type “Control” that inherits from the CheckedListBox and then override its draw method to paint the cell the way we want.

I tend to avoid creating new controls. However, this will allow us to “keep” the CheckedListBoxes “selection functionality” by keeping its SelectionMode set to One. In addition to removing the job of “your” code having to manage each check box’s check state… we can also use all the checked list boxes “selection” events and use them as we typically would using the list boxes “selection” properties.

Below is a crude example of how to override the CheckedListBox’s Draw method to keep the “selected” items back color to the same color of the non-selected items.

class CheckedListBox_NoSelect : CheckedListBox {
  protected override void OnDrawItem(DrawItemEventArgs e) {
    DrawItemEventArgs new_e_Args = new DrawItemEventArgs
       (e.Graphics,
        e.Font,
        new Rectangle(e.Bounds.Location, e.Bounds.Size),
        e.Index,
        (e.State & DrawItemState.Focus) == DrawItemState.Focus ? DrawItemState.Focus : DrawItemState.None,
        this.ForeColor,
        this.BackColor);
    base.OnDrawItem(new_e_Args);
  }
}

The code above is a simplified version of this SO question… enter image description here

The CheckedListBox on the left is a regular CheckedListBox and uses the approach from user18387401‘s answer. The CheckedListBox on the right is our new control class CheckedListBox_NoSelect above.

For each control, the SelectedIndexChanged event is wired up to demonstrate that the checked list box on the left with its SelectionMode set to None will always have its SelectedItem set to null and its SelectedIndex will always be set to -1. However, it is not difficult to figure out “which” item was selected using user18387401‘s approach. This index is also displayed in its SelectedIndexChanged event.

private void Form1_Load(object sender, EventArgs e) {
  checkedListBox1.SelectionMode = SelectionMode.None;
  checkedListBox1.Items.Add("Item 1");
  checkedListBox1.Items.Add("Item 2");
  checkedListBox1.Items.Add("Item 3");
  checkedListBox1.Items.Add("Item 4");
  checkedListBox1.Items.Add("Item 5");
  checkedListBox1.CheckOnClick = true;
  // Leave default selection mode to "One"
  checkedListBox_NoSelect1.Items.Add("Item 1");
  checkedListBox_NoSelect1.Items.Add("Item 2");
  checkedListBox_NoSelect1.Items.Add("Item 3");
  checkedListBox_NoSelect1.Items.Add("Item 4");
  checkedListBox_NoSelect1.Items.Add("Item 5");
  checkedListBox_NoSelect1.CheckOnClick = true;
}


private void checkedListBox1_MouseClick(object sender, MouseEventArgs e) {
  int clickedIndex = checkedListBox1.IndexFromPoint(e.X, e.Y);
  if (clickedIndex != -1) {
    checkedListBox1.SetItemChecked(clickedIndex, !checkedListBox1.GetItemChecked(clickedIndex));
    Debug.WriteLine("LEFT: MouseClick Selected Index: "   clickedIndex);
  }
}


private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e) {
  Debug.WriteLine(" LEFT ->  Item: "   (checkedListBox1.SelectedItem == null ? "Null" : checkedListBox1.SelectedItem));
  Debug.WriteLine(" LEFT -> Index: "   checkedListBox1.SelectedIndex);
}

private void checkedListBox_NoSelect1_SelectedIndexChanged(object sender, EventArgs e) {
  Debug.WriteLine("RIGHT ->  Item: "   (checkedListBox_NoSelect1.SelectedItem == null ? "Null" : checkedListBox_NoSelect1.SelectedItem));
  Debug.WriteLine("RIGHT -> Index: "   checkedListBox_NoSelect1.SelectedIndex);
}

I hope this makes sense and helps. Sorry that I did this in C#. If you can not convert the code to a VB version, then let me know and I will add a VB version.

  • Related