Как отключить флажок в CheckListBox?

У меня есть несколько элементов в CheckedListBox, я хочу отключить CheckBox первого элемента в нем.
т. е. я хочу отключить первый элемент в CheckedListBox, потому что я хочу визуально сообщить пользователю, что эта опция недоступна.


person Subodh Bansal    schedule 06.12.2010    source источник


Ответы (11)


Объединение 2 из приведенных выше частичных ответов отлично сработало для меня. Добавьте свои товары в список с помощью:

myCheckedListBox.Items.Add(myItem, myState);

Где myState — CheckState.Indeterminate для элементов, которые следует отключить. Затем добавьте обработчик событий, чтобы эти элементы не изменялись:

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

Это не позволяет вам использовать «Неопределенный» в этом списке по его обычному назначению, но дает вид, очень похожий на то, что можно было бы ожидать от отключенного элемента, и обеспечивает правильное поведение!

person Mick Bruno    schedule 04.08.2013
comment
Только что попробовав то же самое, обратите внимание, что с помощью этого обработчика событий, как написано, вы не можете программно повторно включить флажок «отключено» после того, как вы его отключили — событие ItemCheck срабатывает, видит существующее состояние «Неопределенность» и переопределяет вас. В большинстве случаев требуется дополнительная логическая проверка, чтобы определить, было ли изменение состояния инициировано пользователем или программным. Конечно, то, как вы защищаете это логическое значение от условий гонки, является упражнением для читателя... - person jimbobmcgee; 03.08.2016

Хотя этот пост довольно старый, последний добавленный ответ был отправлен в апреле этого года,
и я надеюсь, что это кому-то поможет.
Я искал что-то подобное: проверенный список, который ведет себя как многие установщики. , которые предлагают список опций, где требуются некоторые функции, и поэтому они отмечены и отключены.
Благодаря этому сообщению (Могу ли я использовать обработчик событий DrawItem с CheckedListBox?) Мне удалось это сделать, создав подкласс элемента управления CheckedListBox.
Как говорится в OP в связанном сообщении, в элементе управления CheckedListBox событие OnDrawItem никогда не запускается, поэтому необходимо создавать подклассы.
Это очень просто, но это работает. Вот как это выглядит (выше CheckBox для сравнения):

отмеченный список

ПРИМЕЧАНИЕ: отключенный элемент на самом деле отключен: щелчок по нему не имеет никакого эффекта (насколько я могу судить).

И это код:

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();
    }
}

Используйте это так:

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

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

Надеюсь, это может помочь кому-то.

person Jack Griffin    schedule 12.07.2015

Отключение элементов — не лучшая идея, у пользователя не будет хорошего отзыва о том, что установка флажка не будет иметь никакого эффекта. Вы не можете использовать пользовательский рисунок, чтобы сделать его очевидным. Лучше всего просто пропустить этот пункт.

Однако вы можете легко победить пользователя с помощью события ItemCheck:

    private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
        if (e.Index == 0) e.NewValue = e.CurrentValue;
    }
person Hans Passant    schedule 06.12.2010
comment
спасибо, но я хочу визуально сообщить пользователю, что эта опция недоступна - person Subodh Bansal; 06.12.2010
comment
не может использовать пользовательский рисунок - неправда, но это было бы несколько сложно. Было бы проще сделать текст отключенным, и использовать приведенный здесь код отключения. - person Jon Seigel; 06.12.2010
comment
Повторная реализация пользовательского рисунка лишает смысла использование CheckedListBox, с таким же успехом можно использовать ListBox. Как уже говорилось, простой способ сделать очевидным, что параметр недоступен, — это удалить его из коллекции Items. - person Hans Passant; 06.12.2010
comment
отличный ответ. Спасибо - person Ashkan Mobayen Khiabani; 29.10.2013
comment
Как и в моем комментарии в stackoverflow.com/questions/4368618/ событие ItemCheck будет перехватывать любые попытки изменить состояние проверки, включая попытки «повторно включить» флажок. Для преодоления этого необходимы дополнительные проверки. - person jimbobmcgee; 03.08.2016
comment
Хм, нет, тот обработчик событий ItemCheck, который я опубликовал, определенно предотвращает изменение состояния проверки первого элемента. Попытайся. - person Hans Passant; 03.08.2016

Чтобы отключить какой-либо конкретный элемент, используйте следующее:

checkedListBox1.SetItemCheckState(0, CheckState.Indeterminate);

SetItemCheckState принимает индекс элемента, а CheckState Enum неопределенно используется для отображения затененного вида

person Boomer    schedule 27.11.2012
comment
Это показывает серый вид, но не мешает пользователю проверять элемент (я думаю, это можно сделать, внедрив прослушиватель) - person personne3000; 22.11.2014

Я знаю, что это было давно, но я нашел это в своем поиске списка и решил добавить его в обсуждение.

Если у вас есть список и вы хотите отключить все флажки, чтобы их нельзя было щелкнуть, но не отключать элемент управления, чтобы пользователь мог прокручивать и т. д., вы можете сделать это:

listbox.SelectionMode = SelectionMode.None
person Simon Smith    schedule 29.01.2014

CheckedListBox не будет работать таким образом. CheckedListBox.Items — это коллекция строки, чтобы их нельзя было "отключить" как таковые.

Вот несколько обсуждений возможных решений, которые могут вам помочь: здесь и здесь.

person msergeant    schedule 06.12.2010

Решение состоит в том, чтобы использовать событие ItemChecking:

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

Это отменит все проверки каждого элемента, но вы всегда можете сделать более точное решение, но протестировав текущий .SelectedItem

person Baptiste Pernet    schedule 30.04.2012

Это работает для меня:

checkedListBox1.SelectionMode = SelectionMode.None;

Это означает, что элементы не могут быть выбраны

Нет: элементы не могут быть выбраны.

Дополнительные сведения можно найти здесь: Перечисление режима выбора.

person Willy David Jr    schedule 13.10.2017

Вот как я сделал это в приложении службы поддержки, которое я написал:

Во-первых, я сделал так, чтобы флажок был неактивен, когда я добавлял его в список во время загрузки формы:

    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);
            }

        }

Затем я использовал событие, чтобы при нажатии оно оставалось нажатым:

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

Идея здесь заключается в том, что в моей форме он установлен так, чтобы флажок проверялся при нажатии/выборе элемента. Таким образом, я мог убить двух зайцев одним выстрелом. Я мог бы не допустить, чтобы это событие вызывало проблемы, когда элемент сначала проверяется и добавляется во время загрузки формы. Кроме того, проверка при выборе позволяет мне использовать это событие вместо события проверки элемента. В конечном счете, идея состоит в том, чтобы не дать ему испортиться во время загрузки.

Вы также заметите, что не имеет значения, какой номер индекса, эта переменная неизвестна, потому что в моем приложении она получает список групп из AD, которые существуют в определенной OU.

Что касается того, хорошая это идея или нет, это зависит от ситуации. У меня есть другое приложение, в котором элемент для отключения зависит от другого параметра. В этом приложении я просто хочу, чтобы служба поддержки увидела, что эта группа необходима, чтобы они не удаляли их из нее.

person Nathan McKaskle    schedule 03.10.2014

Попробуйте ниже код:

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
person Raj    schedule 05.04.2015

Я думаю, что альтернативным решением является использование компонентов Telerik.

RadListControl может дать вам такой вариант:

введите здесь описание изображения

person shA.t    schedule 05.04.2015