【问题标题】:How to dynamically change / set checkedListBox item fore colour如何动态更改/设置checkedListBox项目前景色
【发布时间】:2013-07-11 08:15:15
【问题描述】:

我有下面的代码。如何根据是否选中项目来设置checkedListBox项目的前景色?

private void FindSelectedUserRoles()
{
        lblSelectedUser.Text = Code.CommonUtilities.getDgvStringColValue(dataGridViewUserList, "UserName").Trim();

        //iterate all roles selected user is member of
        for (int i = 0; i < checkedListRoles.Items.Count; i++)
        {
            string roleName = checkedListRoles.Items[i].ToString();
            string selectedUserRoles = Code.MemberShipManager.GetSpecificUsersRoles(lblSelectedUser.Text.Trim());

            if (selectedUserRoles.Contains(roleName))
            {
                checkedListRoles.SetItemChecked(i, true);
                //here i want to set item fore colour to green

            }
            else if (selectedUserRoles.Contains(roleName) == false)
            {
                checkedListRoles.SetItemChecked(i, false);
                //and here, i want item fore colour to remain black
            }
        }
}

【问题讨论】:

    标签: c# winforms checkedlistbox


    【解决方案1】:

    我认为你必须像这样画自己的CheckedListBox item

    public class CustomCheckedListBox : CheckedListBox
    {
        public CustomCheckedListBox()
        {
            DoubleBuffered = true;
        }
        protected override void OnDrawItem(DrawItemEventArgs e)
        {            
            Size checkSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, System.Windows.Forms.VisualStyles.CheckBoxState.MixedNormal);
            int dx = (e.Bounds.Height - checkSize.Width)/2;
            e.DrawBackground();
            bool isChecked = GetItemChecked(e.Index);//For some reason e.State doesn't work so we have to do this instead.
            CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(dx, e.Bounds.Top + dx), isChecked ? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal : System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
            using (StringFormat sf = new StringFormat { LineAlignment = StringAlignment.Center })
            {
                using (Brush brush = new SolidBrush(isChecked ? CheckedItemColor : ForeColor))
                {
                    e.Graphics.DrawString(Items[e.Index].ToString(), Font, brush, new Rectangle(e.Bounds.Height, e.Bounds.Top, e.Bounds.Width - e.Bounds.Height, e.Bounds.Height), sf);
                }
            }            
        }
        Color checkedItemColor = Color.Green;
        public Color CheckedItemColor
        {
            get { return checkedItemColor; }
            set
            {
                checkedItemColor = value;
                Invalidate();
            }
        }
    }
    

    如果您想为每个项目设置不同的CheckedColor,您必须存储每个项目的CheckedColor 设置(例如在集合中)并使用Index 引用CheckedColor。但是,我认为这需要做很多工作。因此,如果您有这样的要求,则改用ListView 会更好。

    【讨论】:

    • 行“bool isChecked = GetItemChecked(e.Index);”如果您将该项目拖放到设计器中,则会对我抛出错误。要解决这个问题,您必须添加 Entreis,然后不再抛出错误(否则我认为索引为 -1);
    • @Nerdintraining 感谢您的回复,我不太确定。据我了解,e.Index 在事件处理程序中应该是有效的(因为在处理绘图之前该项目确实存在)。这里的代码当然没有经过很好的测试。我也不确定如何在设计器上拖放列表项(据我所知,标准的窗体设计器无法做到这一点)。您的评论对于其他人改进代码仍然很有价值。最后,我已经多年没有使用 winform 编程了,现在对它并不感兴趣。谢谢。
    • 哇,这是快速反应^^ 3 年后只有 25 分钟的反应时间^-^ 无论如何,我给你一个编辑 :) 你知道如何创建一个看起来像这样的 ControllBox (或者如果存在)link
    • @Nerdintraining 如果您指的是来自该链接的图像中的复选框,那么我会说这并不容易。 tick 看起来像手绘的。也许您需要准备一个 transparent 勾号并尝试将其渲染(或简单地放置)在复选框的顶部,复选框的正方形也应该在里面绘制并留出边距周围(用于渲染刻度线)。当刻度线可以显示在其他控件的顶部时,这变得不容易,这意味着您可以通过刻度线的边界看到后面的所有控件。可以搜索透明背景相关的自定义控件。
    • 正如我所说,我已经多年没有使用 Winforms 编程了,所以我无法为您提供更多帮助。您应该遵循的下一个 UI 技术是 WPF :) 如果您想构建丰富的 UI,它真的很酷,而且它显着改变了您编写 Windows 应用程序的方式。
    【解决方案2】:

    我认为你应该试试ListView 而不是checkedListBox。它具有必要的属性,可以根据需要进行定制。只需将Checkboxes 属性设置为true,然后在您的代码中添加这样的前景色:

    listView1.Items[i].ForeColor = Color.Red;
    

    【讨论】:

      【解决方案3】:

      由于自己绘制东西相当复杂,您实际上可以让原始控件自己绘制 - 只需调整颜色即可。这是我的建议:

      public class CustomCheckedListBox : CheckedListBox
      {
          protected override void OnDrawItem(DrawItemEventArgs e)
          {
              Color foreColor;
              if (e.Index >= 0)
              {
                  foreColor = GetItemChecked(e.Index) ? Color.Green : Color.Red;
              }
              else
              {
                  foreColor = e.ForeColor;
              }
      
              // Copy the original event args, just tweaking the fore color.
              var tweakedEventArgs = new DrawItemEventArgs(
                  e.Graphics,
                  e.Font,
                  e.Bounds,
                  e.Index,
                  e.State,
                  foreColor,
                  e.BackColor);
      
              // Call the original OnDrawItem, but supply the tweaked color.
              base.OnDrawItem(tweakedEventArgs);
          }
      }
      

      【讨论】:

      • 这似乎是一个更简单的方法 - 不错!
      【解决方案4】:

      扩展@Mattias 的答案,我制作了这个自定义控件以满足我的需求。我需要它的颜色取决于 Checked 值以外的其他因素。

      public class CheckedListBoxColorable : CheckedListBox
      {
          /// <summary>
          /// Controls the forecolors of the objects in the Items collection.
          /// If the item is not represented, it will have the default forecolor.
          /// </summary>
          public Dictionary<object, Color> Colors { get; set; }
      
          public CheckedListBoxColorable()
          {
              this.DoubleBuffered = true; //prevent flicker, not sure if this is necessary.
          }
      
          protected override void OnDrawItem(DrawItemEventArgs e)
          {
              //Default forecolor
              Color foreColor = e.ForeColor;
      
              //Item to be drawn
              object item = null;
      
              if (e.Index >= 0) //If index is -1, no customization is necessary
              {
                  //Find the item to be drawn
                  if (this.Items.Count > e.Index) item = this.Items[e.Index];
      
                  //If the item was found and we have a color for it, get the custom forecolor
                  if (item != null && this.Colors != null && this.Colors.ContainsKey(item))
                  {
                      foreColor = this.Colors[item];
                  }
              }
      
              // Copy the original event args, just tweaking the forecolor.
              var tweakedEventArgs = new DrawItemEventArgs(
                  e.Graphics,
                  e.Font,
                  e.Bounds,
                  e.Index,
                  e.State,
                  foreColor,
                  e.BackColor);
      
              // Call the original OnDrawItem, but supply the tweaked color.
              base.OnDrawItem(tweakedEventArgs);
          }
      }
      

      用法:

      //Set the colors I want for my objects
      foreach (var obj in objects)
      {
          //Add your own logic here to set the color depending on whatever criteria you have
          if (obj.SomeProperty) lstBoxes.Colors.Add(obj, Color.Green);
          else lstBoxes.Colors.Add(obj, Color.Red);
      }
      //Add the items to the checkedlistbox
      lstBoxes.Items.AddRange(objects.ToArray());
      

      【讨论】:

        【解决方案5】:

        接受的答案对我有用,但如果你想禁用 CustomCheckedListBox,它需要修改。

        我修改代码如下:-

        我将“CheckBoxRenderer.DrawCheckBox...”行更改为

        if(Enabled)
        {
            CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(dx, e.Bounds.Top + dx), isChecked ? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal : System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
        }
        else
        {
            CheckBoxRenderer.DrawCheckBox(e.Graphics, new Point(dx, e.Bounds.Top + dx), isChecked ? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedDisabled : System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedDisabled);
        }
        

        然后我将 'using (Brush Brush = new SolidBrush...' 行改为

        using (Brush brush = new SolidBrush(isChecked ? CheckedItemColor : (Enabled ? ForeColor : SystemColors.GrayText)))
        

        这导致启用/禁用对我有用。

        【讨论】:

          猜你喜欢
          • 2012-11-15
          • 1970-01-01
          • 2013-09-03
          • 1970-01-01
          • 2018-04-06
          • 2010-12-07
          • 1970-01-01
          • 1970-01-01
          • 2016-07-26
          相关资源
          最近更新 更多