WinForms:在ListView中更改所选项目的ForeColor

时间:2018-03-22 15:44:59

标签: c# winforms listview

我将ListView中所有项目的ForeColor设置为不同的颜色,但是当选择该项目时,这将被覆盖(再次更改为黑色;取消选择时更改为自定义颜色)。

我希望我的商品能够保留我的自定义颜色,即使在选择中也是如此。

我基本上问了7年前问过here的同一个问题,似乎没有任何令人满意的答案。

我尝试在SO和其他地方搜索,但没有运气。到目前为止提供的唯一解决方案是绘制整个事物(DrawItem方法),我试了一下,但是对于这样一个小小的要求却非常复杂......

这是唯一的方法吗?说不是的。

1 个答案:

答案 0 :(得分:1)

Enable your ListView OwnerDraw mode, then subscribe its DrawItem and DrawColumnHeader events.
If your design requires it, also subcribe the DrawSubitem event.

At this point, you can draw anything in the related areas of your ListView.

In the example, I've painted a little symbol in the Header area.
The Header text needs to be painted too.

If the Background color doesn't change (same as in design mode), you just need to use the DrawListViewItemEventArgs e parameter function e.DrawBackground();

If not, use e.Graphics.FillRectangle() to color the Item area, defined by e.Bounds.

The Item Text is drawn using e.Graphics.DrawString().
The item Text is e.Item.Text, the text area is defined by e.Bounds again.
If you don't need any specific details/settings for the item's text, you can simply use e.DrawText();, which uses the default properties (defined at design-time).

Here, the item color complex logic is that the color is specified inside the item text. Could be anything else. The item tag, its Index position, a List<Parameters>, you name it.

This is how it might look like:
(I added e.Graphics.TextRenderingHint = [] to show how you can control the quality of the rendered text. e.Graphics.TextContrast can be also used to enhance the contrast).

ListView Colored Items

Note: this code sample only draws a generic image, if the ListView has an ImageList. You should also verify whether the SmallIcon/LargeIcon ImageLists are defined and draw the related Image in the specified size. It's the same procedure, though.

protected void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    e.Item.UseItemStyleForSubItems = true;
    int imageOffset = 0;
    Rectangle rect = e.Item.Bounds;
    bool drawImage = !(e.Item.ImageList is null);
    Color itemColor = Color.FromName(e.Item.Text.Substring(e.Item.Text.LastIndexOf(" ") + 1));
    using (StringFormat format = new StringFormat(StringFormatFlags.FitBlackBox)) {
        format.LineAlignment = StringAlignment.Center;

        if (drawImage) {
            imageOffset = e.Item.ImageList.ImageSize.Width + 1;
            rect.Location = new Point(e.Bounds.X + imageOffset, e.Item.Bounds.Y);
            rect.Size = new Size(e.Bounds.Width - imageOffset, e.Item.Bounds.Height);
            e.Graphics.DrawImage(e.Item.ImageList.Images[e.Item.ImageIndex], e.Bounds.Location);
        }

        if (e.Item.Selected) {
            using (SolidBrush bkgrBrush = new SolidBrush(itemColor))
            using (SolidBrush foreBrush = new SolidBrush(e.Item.BackColor)) {
                e.Graphics.FillRectangle(bkgrBrush, rect);
                e.Graphics.DrawString(e.Item.Text, e.Item.Font, foreBrush, rect, format);
            }
            e.DrawFocusRectangle();
        }
        else {
            //e.DrawDefault = true;
            using (SolidBrush foreBrush = new SolidBrush(itemColor)) {
                e.Graphics.DrawString(e.Item.Text, e.Item.Font, foreBrush, rect, format);
            }
        }
    }
}

// Draws small symbol in the Header beside the normal Text
protected void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
    e.DrawBackground();
    string extra = (e.ColumnIndex == 1) ? (char)32 + "\u2660" + (char)32 : (char)32 + "\u2663" + (char)32;
    e.Graphics.DrawString(extra + e.Header.Text, e.Font, new SolidBrush(e.ForeColor), e.Bounds, StringFormat.GenericTypographic);
}