一个ListBox项目的背景颜色(Windows窗体)

55

如何设置 System.Windows.Forms.ListBox 中某个项目的背景颜色?

如果可以的话,我想设置多个项目的背景颜色。

4个回答

65

感谢Grad van Horck提供的答案,它指导我朝着正确的方向前进。

为了支持文字(而不仅仅是背景颜色),这是我完整可用的代码:

//global brushes with ordinary/selected colors
private SolidBrush reportsForegroundBrushSelected = new SolidBrush(Color.White);
private SolidBrush reportsForegroundBrush = new SolidBrush(Color.Black);
private SolidBrush reportsBackgroundBrushSelected = new SolidBrush(Color.FromKnownColor(KnownColor.Highlight));
private SolidBrush reportsBackgroundBrush1 = new SolidBrush(Color.White);
private SolidBrush reportsBackgroundBrush2 = new SolidBrush(Color.Gray);

//custom method to draw the items, don't forget to set DrawMode of the ListBox to OwnerDrawFixed
private void lbReports_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    bool selected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected);

    int index = e.Index;
    if (index >= 0 && index < lbReports.Items.Count)
    {
        string text = lbReports.Items[index].ToString();
        Graphics g = e.Graphics;

        //background:
        SolidBrush backgroundBrush;
        if (selected)
            backgroundBrush = reportsBackgroundBrushSelected;
        else if ((index % 2) == 0)
            backgroundBrush = reportsBackgroundBrush1;
        else
            backgroundBrush = reportsBackgroundBrush2;
        g.FillRectangle(backgroundBrush, e.Bounds);

        //text:
        SolidBrush foregroundBrush = (selected) ? reportsForegroundBrushSelected : reportsForegroundBrush;
        g.DrawString(text, e.Font, foregroundBrush, lbReports.GetItemRectangle(index).Location);
    }

    e.DrawFocusRectangle();
}

以上代码将添加到给定的代码中,并将显示正确的文本并突出显示所选项目。

1
很棒,所选的位非常有用。 - Almo
1
@PrakashVishwakarma 完成了,看到我的编辑了吗。感谢您的提醒,我还提高了整体效率,我每次调用该方法都会创建新的 Brush 实例,这是错误的。 - Shadow The Spring Wizard
1
@ShadowWizardIsVaccinatedV3 希望对当前和未来的用户做出说明。 目前我将使用ListView,只是因为我还没有看到像这样的listbox解决方案而感到好奇。也许将来我会有兴趣去尝试一下 - 如果我这样做了,我会发布结果的 - 但现在快速得到一个可用的东西比“另一个有趣的项目”更重要。特别是对于OwnerDraw,我之前没有任何经验,并且预见不需要它。;-) - J. Chris Compton
1
@J.ChrisCompton,不知怎么错过了你的最后一条评论,谢谢你提供的链接,以及你所付出的时间! - undefined
1
@ulatekh 有道理,但我更喜欢在修改代码之前先进行测试,希望能尽快找到我的测试代码并进行测试。谢谢! - undefined
显示剩余6条评论

56

可能唯一实现此目的的方法是自行绘制项目。

DrawMode设置为OwnerDrawFixed,并在DrawItem事件上编写类似以下内容的代码:

private void listBox_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    Graphics g = e.Graphics;

    g.FillRectangle(new SolidBrush(Color.Silver), e.Bounds);

    // Print text

    e.DrawFocusRectangle();
}

第二个选项是使用ListView,虽然它们有另一种实现方式(不是真正的数据绑定方式,但在列的灵活性方面更加灵活)。

2
// Set the background to a predefined colour
MyListBox.BackColor = Color.Red;
// OR: Set parts of a color.
MyListBox.BackColor.R = 255;
MyListBox.BackColor.G = 0;
MyListBox.BackColor.B = 0;

如果你想设置多个背景颜色,使每个项目的背景颜色不同,那么在ListBox中是不可能实现的,但是在ListView中可以通过以下方式实现:

// Set the background of the first item in the list
MyListView.Items[0].BackColor = Color.Red;

2
可以使用ListBox实现。请参见https://dev59.com/MnVD5IYBdhLWcg3wGHiu - jfs
替换/可能/为容易/. 哦,天啊。C#1,菜鸟0。我之前没有怎么使用过重载绘画方法。 - Matthew Scharley
BackColor不是ListBox.ObjectCollection项的属性。 - ghiboz

-1
public MainForm()
{
    InitializeComponent();
    this.listbox1.DrawItem += new DrawItemEventHandler(this.listbox1_DrawItem);
}

private void listbox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
    e.DrawBackground();
    Brush myBrush = Brushes.Black;
    var item = listbox1.Items[e.Index];
    if(e.Index % 2 == 0)
    {
        e.Graphics.FillRectangle(new SolidBrush(Color.Gold), e.Bounds);
    }
        e.Graphics.DrawString(((ListBox)sender).Items[e.Index].ToString(), 
            e.Font, myBrush,e.Bounds, StringFormat.GenericDefault);
        e.DrawFocusRectangle();
    }
}

需要进行解释。例如,什么是主要的想法/要点?请通过[编辑(更改)您的答案](https://stackoverflow.com/posts/41631585/edit)来响应,而不是在评论中(***不要***带上“编辑:”,“更新:”或类似的字眼 - 答案应该看起来像今天写的)。 - Peter Mortensen
同意@PeterMortensen的观点。我完全无法理解这个逻辑——似乎与问题相去甚远。懒惰的表现。 - stigzler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接