CheckedListBox Control - Only checking the checkbo

2020-02-28 04:55发布

问题:

I'm using a CheckedListBox control in a small application I'm working on. It's a nice control, but one thing bothers me; I can't set a property so that it only checks the item when I actually check the checkbox. What's the best way to overcome this? I've been thinking about getting the position of the mouseclick, relative from the left side of the checkbox. Which works partly, but if I would click on an empty space, close enough to the left the current selected item would still be checked. Any ideas regarding this?

回答1:

Well, it is quite ugly, but you could calculate mouse hit coordinates against rectangles of items by hooking on CheckedListBox.MouseDown and CheckedListBox.ItemCheck like the following

/// <summary>
/// In order to control itemcheck changes (blinds double clicking, among other things)
/// </summary>
bool AuthorizeCheck { get; set; }

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
    if(!AuthorizeCheck)
        e.NewValue = e.CurrentValue; //check state change was not through authorized actions
}

private void checkedListBox1_MouseDown(object sender, MouseEventArgs e)
{
    Point loc = this.checkedListBox1.PointToClient(Cursor.Position);
    for (int i = 0; i < this.checkedListBox1.Items.Count; i++)
    {
        Rectangle rec = this.checkedListBox1.GetItemRectangle(i);
        rec.Width = 16; //checkbox itself has a default width of about 16 pixels

        if (rec.Contains(loc))
        {
            AuthorizeCheck = true;
            bool newValue = !this.checkedListBox1.GetItemChecked(i);
            this.checkedListBox1.SetItemChecked(i, newValue);//check 
            AuthorizeCheck = false;

            return;
        }
    }
}


回答2:

I know this thread's a bit old, but I don't think it's a problem to offer another solution:

private void checkedListBox1_MouseClick(object sender, MouseEventArgs e)
{
    if ((e.Button == MouseButtons.Left) & (e.X > 13))
    {
        this.checkedListBox1.SetItemChecked(this.checkedListBox1.SelectedIndex, !this.checkedListBox1.GetItemChecked(this.checkedListBox1.SelectedIndex));
    }
}

(With the value of CheckOnClick = True).

You could use that thingy with the rectangle, but why make it more complex the it needs to.



回答3:

Another solution is to simply use a Treeview.
Set CheckBoxes to true, ShowLines to false, and ShowPlusMinus to false and you have basically the same thing as a CheckedListBox. The items are only checked when the actual CheckBox is clicked.

The CheckedListBox is much more simplistic, but the TreeView offers a lot of options that can potentially be better suited for your program.



回答4:

I succesfully used this property:

CheckedBoxList.CheckOnClick

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.checkedlistbox.checkonclick?view=netframework-4.7.2



回答5:

The text for a checkbox in a CheckedListBox is rendered by default is to place an HTML label after the checkbox input and set the label's "for" attribute to the ID of the checkbox.

When a label is denoting an element that it is "for," clicking on that label tells the browser to focus on that element, which is what you're seeing.

Two options are to render your own list with separate CheckBox controls and text (not as the Text property of the CheckBox, as that does the same thing as the CheckBoxList) if the list is static or to use something like a Repeater if the list is dynamic.



回答6:

Try this. Declare iLastIndexClicked as a form-level int variable.

private void chklst_MouseClick(object sender, MouseEventArgs e)
{
  Point p = chklst.PointToClient(MousePosition);
  int i = chklst.IndexFromPoint(p);
  if (p.X > 15) { return; } // Body click. 
  if (chklst.CheckedIndices.Contains(i)){ return; } // If already has focus click anywhere works right.
 if (iLastIndexClicked == i) { return; } // native code will check/uncheck
  chklst.SetItemChecked(i, true);  
  iLastIndexClicked = i;
}

Just checking to see if the user clicked in the leftmost 15 pixels of the checked list (the check box area) works at all times except re-checking a currently selected item. Storing the last index and exiting without changing lets the native code handle that properly, trying to set it to checked in that case turns it on and it just turns back off when the "ItemCheck" code runs.