简体   繁体   中英

C# checkedlistbox with radiobutton behavior

The last couple of days I've been looking for a solution to this problem but haven't found a proper solution yet. I've made a WinForm with a checkedlistbox that must behave as a radiobuttongroup. I know it's not preferable but I haven't chosen this myself. I'm trying to expand my knowledge on WinForm so I grabbed a program and try to mimic the behavior so please stay with me.

Radiobutton properties I want in my checkedlistbox:

  • You can only check one item. (Easy to do, see code below)
  • One item is always checked. (This is the source of my problem)
  • When you click the checkbox/bullet it checks with one click, clicking on the text doesn't change anything. (I've figured that one out as well)

Checkedlistbox properties I need:

  • Selectable text behind checkbox. (Used for renaming and deleting items in list)

I works most of the time except when a item is selected and another item is unchecked. That's when every item in the list can be unchecked.

This is the code for the ItemCheck event.

private string _checkedName = "";
bool _autorizeCheck {get; set;}

private void OnItemCheck(object sender, ItemCheckEventArgs e)
{
            var list = sender as CheckedListBox;

            #region//Click checkbox
            if (!_authorizeCheck)
            {
                e.NewValue = e.CurrentValue;
            }
            #endregion

            #region//Radiobutton config
            if (e.CurrentValue == CheckState.Unchecked)
            {
                for (int i = 0; i < list.Items.Count; i++)
                {
                    if (i != e.Index)
                    {
                        _checkedName = list.Items[e.Index].ToString();
                        list.SetItemChecked(i, false);
                    }
                }
            }
            else if(e.CurrentValue == CheckState.Checked && _checkedName == list.Items[e.Index].ToString())
            {
                if (list.CheckedItems.Count == 1)
                {
                    e.NewValue = e.CurrentValue;
                }
            }
            #endregion
}

This is the code for clicking the checkbox:

private void OnMouseDown_checkedListBox(object sender, MouseEventArgs e)
        {
            #region//Check if checkbox is clicked
            var checkedListBox = sender as CheckedListBox;
            var location = checkedListBox.PointToClient(Cursor.Position);
            for (int i = 0; i < checkedListBox.Items.Count; i++)
            {
                var rec = checkedListBox.GetItemRectangle(i);
                rec.Width = 16;

                if (rec.Contains(location))
                {
                    _authorizeCheck = true;
                    bool newValue = !checkedListBox.GetItemChecked(i);
                    checkedListBox.SetItemChecked(i, newValue); 
                    _authorizeCheck = false;

                    return;
                }
            }
            #endregion
        }

Make a new class Form2, paste this over it:

public partial class Form2 : Form
{
    private int index = 0; //helper to track the selected index
    public Form2()
    {
        InitializeComponent();
        checkedListBox1.SetItemChecked(0, true); //check at least one item
    }

    //this fires before an item is checked. Really, Microsoft should perhaps have called it ItemCheckChanging
    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
    {
        if (index == -1) //programmatic change, exit early; see below
            return;
        else if (index == e.Index)
            e.NewValue = CheckState.Checked; //undo an attempt to uncheck the checked item
        else
        {
            var oldIndex = index; //what item do we want to uncheck
            index = -1; //prevent event handler firing again when we..
            checkedListBox1.SetItemChecked(oldIndex, false); //..uncheck th old
            index = e.Index; //track the newly checked
        }
    }
}

By the way, your life might be simpler if you use a datagridview bound to a table with 2 columns, a bool and a text..

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