4

I'd like my ListView's selected item to remain clearly visible when focus is lost (it is a dim grey on Windows 7 ). I did set the HideSelection property to False.

I'd like to do for the List View what someone has done here for the TreeView control, namely, override the Drawnode event:

C# WinForms highlight treenode when treeview doesnt have focus

I presume I need to set the OwnerDraw property to True override the DrawItem event, but I am not sure what I need to do in this event.... :-)

Community
  • 1
  • 1
Chad
  • 23,658
  • 51
  • 191
  • 321

1 Answers1

13

You need something like that:

private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
    e.DrawDefault = true;
}

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    const int TEXT_OFFSET = 1;    // I don't know why the text is located at 1px to the right. Maybe it's only for me.

    ListView listView = (ListView)sender;

    // Check if e.Item is selected and the ListView has a focus.
    if (!listView.Focused && e.Item.Selected)
    {
        Rectangle rowBounds = e.SubItem.Bounds;
        Rectangle labelBounds = e.Item.GetBounds(ItemBoundsPortion.Label);
        int leftMargin = labelBounds.Left - TEXT_OFFSET;
        Rectangle bounds = new Rectangle(rowBounds.Left + leftMargin, rowBounds.Top, e.ColumnIndex == 0 ? labelBounds.Width : (rowBounds.Width - leftMargin - TEXT_OFFSET), rowBounds.Height);
        TextFormatFlags align;
        switch (listView.Columns[e.ColumnIndex].TextAlign)
        {
            case HorizontalAlignment.Right:
                align = TextFormatFlags.Right;
                break;
            case HorizontalAlignment.Center:
                align = TextFormatFlags.HorizontalCenter;
                break;
            default:
                align = TextFormatFlags.Left;
                break;
        }
        TextRenderer.DrawText(e.Graphics, e.SubItem.Text, listView.Font, bounds, SystemColors.HighlightText,
            align | TextFormatFlags.SingleLine | TextFormatFlags.GlyphOverhangPadding | TextFormatFlags.VerticalCenter | TextFormatFlags.WordEllipsis);
    }
    else
        e.DrawDefault = true;
}

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    ListView listView = (ListView)sender;

    // Check if e.Item is selected and the ListView has a focus.
    if (!listView.Focused && e.Item.Selected)
    {
        Rectangle rowBounds = e.Bounds;
        int leftMargin = e.Item.GetBounds(ItemBoundsPortion.Label).Left;
        Rectangle bounds = new Rectangle(leftMargin, rowBounds.Top, rowBounds.Width - leftMargin, rowBounds.Height);
        e.Graphics.FillRectangle(SystemBrushes.Highlight, bounds);
    }
    else
        e.DrawDefault = true;
}

EDIT: Improved for View = View.Details and FullRowSelect = true.
EDIT2: Different alignment types of column are taken into account, and also auto-ellipsis flag was added.

Dmitry
  • 13,797
  • 6
  • 32
  • 48
  • Unfortunately, my list has multiple columns and the text disappears for all but the first column when a row is selected. Can I impose on you to also help to implement the draw sub item method? I'm using a full row select. – Chad Nov 16 '13 at 04:15
  • I've updated the code for your needs. Now all 3 events are handled: `DrawItem`, `DrawSubItem`, `DrawColumnHeader`. – Dmitry Nov 16 '13 at 10:15
  • Aside from a minor issue when the colimn is not large enough to display the full text and ellipsis are added, it worked very well. The fulkl column text was spilling over into the next column. – Chad Nov 16 '13 at 14:54
  • Fixed. Also different alignment types of column are taken into account. – Dmitry Nov 16 '13 at 15:40
  • I have the same problem with disappeared text in all but the first columns only when I have multiple ListViews on a form and after form is shown and mouse hovers the second ListView. This situation fixes when I click this second ListView and after that everything draws normally. – Andark Nov 17 '16 at 05:27
  • 1
    I have figured out the problem, it was a bug in the underlying Win32 control. The DrawItem event occurs without accompanying DrawSubItem events once per row in the details view when the mouse pointer moves over the row. If anyone faces the same problem the solution is here: [link](https://msdn.microsoft.com/en-us/library/system.windows.forms.listview.drawitem.aspx) – Andark Nov 17 '16 at 07:17