问题
I have code below. How can i set checkedListBox item fore colour depending on if item is checked or not checked?
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
}
}
}
回答1:
I think you have to draw your own CheckedListBox item
like this:
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();
}
}
}
If you want to set CheckedColor
differently for each item, you have to store the CheckedColor
setting for each item (such as in a Collection) and reference the CheckedColor
using Index
. However I think it's a little much work to do. So if you have such a requirement, going for ListView
instead would be better.
回答2:
I think you should try ListView
instead of checkedListBox. It has necessary properties and could be customized as you wish. Just set Checkboxes
property to true
, and then in your code add forecolor like that:
listView1.Items[i].ForeColor = Color.Red;
回答3:
Since it's rather complicated to draw the thing yourself, you could actually let the original control draw itself -- just tweaking the color. This is my suggestion:
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:
Expanding on @Mattias' answer, I made this custom control to fit my needs. I needed it to have colors depending on other factors than the Checked value.
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);
}
}
Usage:
//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:
The accepted answer worked for me but it needs modifying if you want to disable the CustomCheckedListBox.
I modified the code as follows: -
I changed the 'CheckBoxRenderer.DrawCheckBox...' line to
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);
}
and then I changed the 'using (Brush brush = new SolidBrush...' line to
using (Brush brush = new SolidBrush(isChecked ? CheckedItemColor : (Enabled ? ForeColor : SystemColors.GrayText)))
This caused enabling/disabling to work for me.
来源:https://stackoverflow.com/questions/17588322/how-to-dynamically-change-set-checkedlistbox-item-fore-colour