WinForms: Changing ForeColor of Selected item in ListView

后端 未结 1 570
有刺的猬
有刺的猬 2021-01-17 04:37

I am setting the ForeColor of all items in my ListView to a different color, but this get\'s overrided when the item is selected (changes to Black again; changes back to cus

相关标签:
1条回答
  • 2021-01-17 05:06

    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).

    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);
    }
    
    0 讨论(0)
提交回复
热议问题