简体   繁体   中英

How to disable a checkbox in a checkedlistbox?

I have some items in a CheckedListBox , I want to disable the CheckBox of first item in it.
ie I want to disable the first item in the CheckedListBox , because I want to tell the user visually that option is not available.

Combining 2 of the above partial answers worked great for me. Add your items to the list with:

myCheckedListBox.Items.Add(myItem, myState);

Where myState is CheckState.Indeterminate for items that should be disabled. Then add an event handler to keep those items from being changed:

myCheckedListBox.ItemCheck += (s, e) => { if (e.CurrentValue == CheckState.Indeterminate) e.NewValue = CheckState.Indeterminate; };

This does not allow you to use 'Indeterminate' in this list for its normal purpose but it does give a look very similar to what one would expect for a disabled item and it provides the correct behavior!

Though this post is pretty old, the last added answer has been submitted in April this year,
and I hope this will help someone.
I was after something similar : a checked list box that behaves like a lot of installers, which offer a list of options where some features are required and thus are both checked and disabled.
Thanks to this post ( Can I use a DrawItem event handler with a CheckedListBox? ) I managed to do that, subclassing a CheckedListBox control.
As the OP in the linked post states, in the CheckedListBox control the OnDrawItem event is never fired, so subclassing is necessary.
It's very basic, but it works. This is what it looks like (the CheckBox above is for comparison) :

选中的列表框

NOTE : the disabled item is really disabled : clicking on it has no effects whatsoever (as far as I can tell).

And this is the code :

public class CheckedListBoxDisabledItems : CheckedListBox {
    private List<string> _checkedAndDisabledItems = new List<string>();
    private List<int> _checkedAndDisabledIndexes = new List<int>();

    public void CheckAndDisable(string item) {
        _checkedAndDisabledItems.Add(item);
        this.Refresh();
    }

    public void CheckAndDisable(int index) {
        _checkedAndDisabledIndexes.Add(index);
        this.Refresh();
    }

    protected override void OnDrawItem(DrawItemEventArgs e) {
        string s = Items[e.Index].ToString();

        if (_checkedAndDisabledItems.Contains(s) || _checkedAndDisabledIndexes.Contains(e.Index)) {
            System.Windows.Forms.VisualStyles.CheckBoxState state = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedDisabled;
            Size glyphSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, state);
            CheckBoxRenderer.DrawCheckBox(
                e.Graphics,
                new Point(e.Bounds.X + 1, e.Bounds.Y + 1), // add one pixel to align the check gliph properly
                new Rectangle(
                    new Point(e.Bounds.X + glyphSize.Width + 3, e.Bounds.Y), // add three pixels to align text properly
                    new Size(e.Bounds.Width - glyphSize.Width, e.Bounds.Height)),
                s,
                this.Font,
                TextFormatFlags.Left, // text is centered by default
                false,
                state); 
        }
        else {
            base.OnDrawItem(e);
        }
    }

    public void ClearDisabledItems() {
        _checkedAndDisabledIndexes.Clear();
        _checkedAndDisabledItems.Clear();
        this.Refresh();
    }
}

Use it like this:

checkedListBox.Items.Add("Larry");
checkedListBox.Items.Add("Curly");
checkedListBox.Items.Add("Moe");

// these lines are equivalent
checkedListBox.CheckAndDisable("Larry");
checkedListBox.CheckAndDisable(0);

Hope this can help someone.

Disabling items isn't a great idea, the user will have no good feedback that click the check box won't have any effect. You cannot use custom drawing to make it obvious. Best thing to do is to simply omit the item.

You can however easily defeat the user with the ItemCheck event:

    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
        if (e.Index == 0) e.NewValue = e.CurrentValue;
    }

To disable any particular item use following:

checkedListBox1.SetItemCheckState(0, CheckState.Indeterminate);

SetItemCheckState takes index of item and CheckState Enum Indeterminate is used to show shaded appearance

I know it has been a while, but I found this in my search for a list box and thought I would add it to the discussion.

If you have a listbox and want to disable all of the checkboxes so they cannot be clicked, but not disable the control so the user can still scroll etc. you can do this:

listbox.SelectionMode = SelectionMode.None

The CheckedListBox will not work in this way. CheckedListBox.Items is a collection of strings so they cannot be "disabled" as such.

Here are some discussions about possible solutions that might help you: here and here .

The solution is to use the event ItemChecking :

_myCheckedListBox.ItemChecking += (s, e) => e.Cancel = true;

This will cancel all the checking on every item, but you can always do more refined solution but testing the current .SelectedItem

This works for me:

checkedListBox1.SelectionMode = SelectionMode.None;

Which means no items can be selected

None: No items can be selected.

For more info, you can check it here: SelectionMode Enumeration .

Here's how I did it in a helpdesk application I wrote:

First, I made it so the check box was greyed out as I added it to the list during form load:

    private void frmMain_Load(object sender, EventArgs e)
    {
        List<string> grpList = new List<string>();
        ADSI objADSI = new ADSI();

        grpList = objADSI.fetchGroups();

        foreach (string group in grpList)
        {
            if (group == "SpecificGroupName")
            {
                chkLst.Items.Add(group, CheckState.Indeterminate);

            }
            else
            {
                chkLst.Items.Add(group);
            }

        }

Then I used an event so that when clicked it ensures it stays clicked:

    private void chkLst_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (chkLst.SelectedItem.ToString() == "SpecificGroupName")
        {
            chkLst.SetItemCheckState(chkLst.SelectedIndex, CheckState.Indeterminate);
        }
    }

The idea here is that on my form it's set so that the box checks on item click/select. This way I could kill two birds with one stone. I could keep this event from causing problems when the item is first checked and added during form load. Plus making it check on select allows me to use this event instead of the item checked event. Ultimately the idea is to keep it from messing up during the load.

You'll also notice that it doesn't matter what the index number is, that variable is unknown because in my app it's grabbing a list of groups from AD that exist in a specific OU.

As to whether this is a good idea or not, that's dependent on the situation. I have another app where the item to disable is dependent on another setting. In this app I just want the helpdesk to see that this group is required so they don't go removing them from it.

Try Below Code:

Private Sub CheckedListBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles CheckedListBox1.MouseUp
        If (Condition) Then
         Me.CheckedListBox1.SelectedIndex = -1
        End If
End Sub

I think an alternative solution, is using Telerik components.

A RadListControl can give you that option:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM