【问题标题】:How to disable a checkbox in a checkedlistbox?如何禁用选中列表框中的复选框?
【发布时间】:2011-05-21 02:19:20
【问题描述】:

我在 CheckedListBox 中有一些项目,我想禁用其中第一个项目的 CheckBox
即我想禁用CheckedListBox 中的第一项,因为我想直观地告诉用户该选项不可用。

【问题讨论】:

    标签: c# winforms checkboxlist


    【解决方案1】:

    结合以上两个部分答案对我来说效果很好。 将您的项目添加到列表中:

    myCheckedListBox.Items.Add(myItem, myState);
    

    其中 myState 是 CheckState.Indeterminate 用于应禁用的项目。 然后添加一个事件处理程序以防止这些项目被更改:

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

    这不允许您在此列表中出于正常目的使用“不确定”,但它确实看起来与人们对禁用项目的期望非常相似,并且它提供了正确的行为!

    【讨论】:

    • 刚刚尝试了同样的事情,请注意,使用此事件处理程序,如所写,一旦禁用“禁用”复选框,您将无法以编程方式重新启用它 - ItemCheck 事件触发,看到现有的不确定状态并覆盖您。在大多数情况下,您需要额外的布尔检查来确定状态更改是用户发起的还是程序性的。当然,如何保护布尔值免受竞争条件的影响是读者的练习......
    【解决方案2】:

    虽然这个帖子比较老了,但最后添加的答案是今年4月提交的,
    我希望这会对某人有所帮助。
    我在寻找类似的东西:一个行为类似的选中列表框 许多安装程序,它们提供了需要某些功能的选项列表,并且 因此都被检查禁用。
    感谢这篇文章 (Can I use a DrawItem event handler with a 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);
    

    希望这可以帮助某人。

    【讨论】:

      【解决方案3】:

      禁用项目不是一个好主意,用户不会有很好的反馈,点击复选框不会有任何效果。您不能使用自定义绘图使其明显。最好的办法是简单地省略该项目。

      但是,您可以使用 ItemCheck 事件轻松击败用户:

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

      【讨论】:

      • thnx,但我想直观地告诉用户该选项不可用
      • “不能使用自定义绘图”——不正确,但会有些困难。自定义将 text 绘制为禁用会更容易,使用此处提供的禁用代码。
      • 重新实现自定义绘图违背了使用 CheckedListBox 的点,还不如使用 ListBox。如前所述,使该选项明显不可用的简单方法是将其从 Items 集合中删除。
      • 很好的答案。谢谢
      • 正如我在stackoverflow.com/questions/4368618/… 中的评论一样,ItemCheck 事件将拦截任何更改检查状态的尝试,包括尝试“重新启用”复选框。需要额外的检查来克服这个问题。
      【解决方案4】:

      要禁用任何特定项目,请使用以下内容:

      checkedListBox1.SetItemCheckState(0, CheckState.Indeterminate);
      

      SetItemCheckState 获取项目索引和CheckState 枚举 Indeterminate 用于显示阴影外观

      【讨论】:

      • 这确实显示了一个灰色的外观,但不会阻止用户检查项目(我想这可以通过实现一个监听器来完成)
      【解决方案5】:

      我知道已经有一段时间了,但我在搜索列表框时发现了这个,并认为我会将它添加到讨论中。

      如果您有一个列表框并且想要禁用所有复选框以便无法单击它们,但不禁用控件以便用户仍然可以滚动等。您可以这样做:

      listbox.SelectionMode = SelectionMode.None
      

      【讨论】:

        【解决方案6】:

        CheckedListBox 不会以这种方式工作。 CheckedListBox.Items 是字符串的集合,因此它们不能被“禁用”。

        以下是一些关于可能对您有所帮助的解决方案的讨论:herehere

        【讨论】:

          【解决方案7】:

          解决方法是使用事件ItemChecking:

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

          这将取消对每个项目的所有检查,但您始终可以做更精细的解决方案,但测试当前的.SelectedItem

          【讨论】:

            【解决方案8】:

            这对我有用:

            checkedListBox1.SelectionMode = SelectionMode.None;
            

            这意味着无法选择任何项目

            无:无法选择任何项目。

            更多信息,您可以在这里查看:SelectionMode Enumeration

            【讨论】:

              【解决方案9】:

              这是我在我编写的帮助台应用程序中的做法:

              首先,当我在表单加载期间将其添加到列表中时,复选框是灰色的:

                  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 中存在的组列表。

              这是否是一个好主意,这取决于情况。我有另一个应用程序,其中要禁用的项目取决于另一个设置。在这个应用程序中,我只想让帮助台看到这个组是必需的,这样他们就不会从其中删除它们。

              【讨论】:

                【解决方案10】:

                试试下面的代码:

                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
                

                【讨论】:

                  【解决方案11】:

                  我认为另一种解决方案是使用Telerik 组件。

                  RadListControl 可以为您提供该选项:

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2014-07-11
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-01-19
                    • 2020-11-14
                    • 1970-01-01
                    相关资源
                    最近更新 更多