views:

56

answers:

1

Hello Coders,

I want to use a CheckedListBox in an application where each item in the ListBox is the name of a folder on my hard drive and for the purpose of reading and writing text files to and from each of these folders I want to ensure that one and only one item (a folder) can be selected at any one time in the CheckedListBox

How can I achieve this via code in C#?

Thanks for reading :-)

Edit \ Update - 22/10/2010 Thanks to all who took the time to reply - especially Adrift whose updated code as requested is working perfectly.

I do appreciate what some commentators said about my usage of a checkedlistbox in this manner, however I feel it suits my purposes perfectly in that I want there to be no doubt whatsoever as to where the text files will be read from and written to.

All the best.

+2  A: 

I agree with the comments that radio buttons would be the usual UI element when only a single item is 'checked', but if you want to stick with a CheckedListBox for your UI, you can try something like this:

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
    CheckedListBox.CheckedIndexCollection checkedIndices = checkedListBox1.CheckedIndices;

    if (checkedIndices.Count > 0 && checkedIndices[0] != e.Index)
    {
        checkedListBox1.SetItemChecked(checkedIndices[0], false);
    }
}

You also might want to set CheckOnClick to true for the CheckedListBox.

Edit

Updated the code per your comment to deselect an item if it is unchecked. The problem is that unchecking the previously checked item causes the event to fire again. I don't know whether there is a standard way to handle this, but in the code below, I detach the handler before calling SetItemCheck, then reattach the handler. It seems like a clean way to handle this, and it works. If I find that there is a recommended way to handle this, I will update my answer.

HTH

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
    CheckedListBox.CheckedIndexCollection checkedIndices = checkedListBox1.CheckedIndices;

    if (checkedIndices.Count > 0)
    {
        if (checkedIndices[0] != e.Index)
        {
            // the checked item is not the one being clicked, so we need to uncheck it.  
            // this will cause the ItemCheck event to fire again, so we detach the handler, 
            // uncheck it, and reattach the handler
            checkedListBox1.ItemCheck -= checkedListBox1_ItemCheck;
            checkedListBox1.SetItemChecked(checkedIndices[0], false);
            checkedListBox1.ItemCheck += checkedListBox1_ItemCheck;
        }
        else
        {
            // the user is unchecking the currently checked item, so deselect it
            checkedListBox1.SetSelected(e.Index, false);
        }
    }
}
adrift
Thanks adrift. I have pasted your code above into Form1.cs and then added this.checkedListBox1_ItemCheck += new System.Windows.Forms.ItemCheckEventArgs(this.checkedListBox1_ItemCheck); to Form1.Designer.cs, but it is looking for another argument - I have tried "object sender" and also "sender" but neither seems to work. Any suggestions?
The Thing
@The Thing, you don't need to add this manually to Form1.Designer.cs. If you remove the line you added, you can go to the property sheet, click the button to list Events for the checkedListBox, and in the ItemCheck event, you should be able to choose this event handler from a drop down.
adrift
@The Thing, if you just want to fix up the line you added manually, it should look like this: `this.checkedListBox1.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.checkedListBox1_ItemCheck);`
adrift
@Adrift, Thanks, I have your code as posted working now :-) But... I would like to enhance it a little more - currently when I untick a checkbox the item will remain highlighted - I would like to remove this and only have an item higlighted when it is ticked. I have tried the following - checkedListBox1.SetSelected(checkedIndices[0], false); both before and after your code within the braces - before is not working correctly and after is giving me an IndexOutOfRangeException. What am I doing wrong?
The Thing
@The Thing, I've updated my answer - hopefully that will do what you want :)
adrift
@Adrift, Thanks again. Your updated code is working perfectly !!! :-)
The Thing