Change the background color of Winform ListView headers
Asked Answered
E

4

18

How can you change the background color of the Headers of a ListView?

Eachelle answered 29/11, 2009 at 4:56 Comment(2)
you will need to implement custom drawing by overriding the Paint event.Economist
overriding the Paint method does nothing on a ListView. You need to use the OwnerDraw mechanism that @David suggested. Just remember that doing so removes all styling from your header control -- no hot item, no sort indicators, no gradient backgrounds.Pich
J
23

You can do this by setting the OwnerDraw property for the list view to true.

This then allows you to provide event handlers for the listview's draw events.

There is a detailed example on MSDN

Below is some example code to set the header colour to red:

    private void listView1_DrawColumnHeader(object sender,
                                            DrawListViewColumnHeaderEventArgs e)
    {
        e.Graphics.FillRectangle(Brushes.Red, e.Bounds);
        e.DrawText();
    }

I think (but am happy to be proved wrong) that with OwnerDraw set to true, you will need to also provide handlers for the other draw events that have default implementations as shown below:

    private void listView1_DrawItem(object sender,
                                    DrawListViewItemEventArgs e)
    {
        e.DrawDefault = true;
    }

I certainly haven't managed to make the listview draw the items without that.

Jonathonjonati answered 29/11, 2009 at 5:28 Comment(1)
As a word of warning, because it took me over an hour to figure it out, don't put a MSGBOX command inside of the drawcolumnheader! It hangs vb.net up - this worked fine otherwiseScalar
C
21

I know this is a little late to the party but I still saw this post and this would have helped me. Here is a little abstracted application of the code david supplied

using System.Windows.Forms;
using System.Drawing;

//List view header formatters
public static void colorListViewHeader(ref ListView list, Color backColor, Color foreColor)
{
    list.OwnerDraw = true;
    list.DrawColumnHeader += 
        new DrawListViewColumnHeaderEventHandler
        (
            (sender, e) => headerDraw(sender, e, backColor, foreColor)
        );
    list.DrawItem += new DrawListViewItemEventHandler(bodyDraw);
}

private static void headerDraw(object sender, DrawListViewColumnHeaderEventArgs e, Color backColor, Color foreColor)
{
    using (SolidBrush backBrush = new SolidBrush(backColor))
    {
        e.Graphics.FillRectangle(backBrush, e.Bounds);
    }

    using (SolidBrush foreBrush = new SolidBrush(foreColor))
    {
        e.Graphics.DrawString(e.Header.Text, e.Font, foreBrush, e.Bounds);
    }
}

private static void bodyDraw(object sender, DrawListViewItemEventArgs e)
{
    e.DrawDefault = true;
}

Then call this in your form constructor

public Form()
{
    InitializeComponent();
    *CLASS NAME*.colorListViewHeader(ref myListView, *SOME COLOR*, *SOME COLOR*);
}

Just replace the *CLASS NAME* with whatever class you put the first bit of code in and the *SOME COLOR*'s with some sort of color.

//Some examples:
Color.white
SystemColors.ActiveCaption
Color.FromArgb(0, 102, 255, 102);
Carlyn answered 23/8, 2015 at 5:51 Comment(1)
Thanks, this is nice. However, that is not all there is to it. I have not solved the following, but what I noticed is: * Horizontal alignment property not evaluated * Vertical alignment not set (centered by default?) * Mouse over effects missing * Font is rendered very blocky (e.Graphics.TextRenderingHintClearTypeGridFit did not help). As simple as this should be, it is rather disappointing how much has to be done manually.Marthmartha
U
3

This being 2023, I don't know if David's answer worked correctly in 2009, but is really ugly on screen today. It doesn't draw all the text, looks like possibly the first letter only.

Nick Pray had the better answer that works today, but there are some things to think about. First the Text shows up in the top right corner, so you need to format it as part of the draw. Also, no lines show up between each column, so this too needs to be set.

Working off of Nick's example, I made some modifications, hope this helps.

    private void ListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
    {
        //Fills one solid background for each cell.
        using (SolidBrush backBrush = new SolidBrush(Color.FromArgb(6, 128, 128)))
        {
            e.Graphics.FillRectangle(backBrush, e.Bounds);
        }
        //Draw the borders for the header around each cell.
        using (Pen backBrush = new Pen(Color.Wheat))
        {
            e.Graphics.DrawRectangle(backBrush, e.Bounds);
        }
        using (SolidBrush foreBrush = new SolidBrush(Color.White))
        {
            //Since e.Header.TextAlign returns 'HorizontalAlignment' with values of (Right, Center, Left).  
            //DrawString uses 'StringAlignment' with values of (Near, Center, Far). 
            //We must translate these and setup a vertical alignment that doesn't exist in DrawListViewColumnHeaderEventArgs.
            StringFormat stringFormat = GetStringFormat(e.Header.TextAlign);

            //Do some padding, since these draws right up next to the border for Left/Near.  Will need to change this if you use Right/Far
            Rectangle rect = e.Bounds; rect.X += 2;
            e.Graphics.DrawString(e.Header.Text, e.Font, foreBrush, rect, stringFormat);
        }
    }

    private StringFormat GetStringFormat(HorizontalAlignment ha)
    {
        StringAlignment align;

        switch (ha)
        {
            case HorizontalAlignment.Right:
                align = StringAlignment.Far;
                break;
            case HorizontalAlignment.Center:
                align = StringAlignment.Center;
                break;
            default:
                align = StringAlignment.Near;
                break;
        }

        return new StringFormat()
        {
            Alignment = align,
            LineAlignment = StringAlignment.Center
        };
    }
Unlay answered 12/3, 2023 at 20:7 Comment(0)
F
0

To change color of the header with keeping the text vertically centered you can do this:

You can hook the DrawColumnHeader of listView like this:

listView1.DrawColumnHeader += new DrawListViewColumnHeaderEventHandler(listView1_DrawColumnHeader);

then the event will look like:

    private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
    {
        e.Graphics.FillRectangle(Brushes.LightBlue, e.Bounds); //Fill header with color

        //Adjust the position of the text to be vertically centered
        int yOffset = (e.Bounds.Height - e.Graphics.MeasureString(e.Header.Text, e.Font).ToSize().Height) / 2;
        Rectangle newBounds = new Rectangle(e.Bounds.X, e.Bounds.Y + yOffset, e.Bounds.Width, e.Bounds.Height - yOffset);

        e.Graphics.DrawString(e.Header.Text, e.Font, Brushes.Black, newBounds);
    }

Let me know if it works well for you!

Fie answered 4/3, 2023 at 18:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.