如何更改ListView的默认选择颜色?

时间:2019-04-03 12:18:08

标签: c# winforms listview colors selection

我正在尝试更改ListView中选择栏的默认(蓝色)颜色。
我拒绝使用ObjectListView,因为我必须更改所有代码。

我已经搜索了这个主题,并在这里找到了一些答案:
Change background selection color of ListView?
但这指向ObjectListView。

以前我使用ListBox时,这可以根据自己的喜好设置选择栏的颜色:

  1. 在“属性”下将DrawMode设置为OwnerDrawFixed
  2. 在“事件”下将DrawItem设置为ListBox1_DrawItem

private void ListBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    if (e.Index < 0) return;
    //if the item state is selected them change the back color 
    if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
        e = new DrawItemEventArgs(e.Graphics,
                                  e.Font,
                                  e.Bounds,
                                  e.Index,
                                  e.State ^ DrawItemState.Selected,
                                  e.ForeColor,
                                  Color.FromArgb(43, 144, 188));//Choose the color

    // Draw the background of the ListBox control for each item.
    e.DrawBackground();
    // Draw the current item text
    e.Graphics.DrawString(lb_result.Items[e.Index].ToString(), e.Font, Brushes.Black, e.Bounds, StringFormat.GenericDefault);
    // If the ListBox has focus, draw a focus rectangle around the selected item.
    e.DrawFocusRectangle();
}

但是我现在正在使用ListView。

  1. 我将OwnerDraw设置为True
  2. 我将DrawItem设置为ListView1_DrawItem

...并使用上面的代码。

我希望它能为我显示如上所述的另一种选择颜色,但是却出现了一些错误:

errors

我将如何正确地将此代码用于ListView?

1 个答案:

答案 0 :(得分:0)

所有者绘制LitView控件比ListBox控件复杂:要处理的更多细节。 这是一个考虑ListView的四个View设置的示例:
View.DetailsView.ListView.TileView.SmallIcon

此处仅绘制文本(这就是为什么不包括View.LargeIcon),以将代码包含在适当范围内的原因。 绘制链接到ListView的ImageList中包含的位图的示例为here

设置ListView
启用ListView OwnerDraw 模式,然后订阅其DrawItemDrawSubItemDrawColumnHeader事件,如示例代码所示(强制性,如果您希望ListView显示任何内容)。

使用默认渲染(设置 e.DrawDefault = true )绘制标题。

常用操作说明
使用TextRenderer.DrawText绘制项目文本:这是ListView用来绘制其项目的原始方法。它允许精确匹配默认渲染,因此我们不会注意到文本的某些未对齐情况。

DrawItem事件用于在所有 View 模式下绘制自定义背景,并将在除 View.Details < / strong>,其中DrawSubItems事件起作用:如果DrawItem事件执行相同任务,我们将绘制第一个项目的文本两次。

DrawSubItems设置为ViewTile 时,不会调用List事件

此处提供的代码的详细信息
辅助方法 GetTextAlignment 负责设置项目的对齐方式,因为每个列可以具有特定的文本对齐方式。

Color listViewSelectionColor 字段用于设置/更改所选项目的颜色。要修改选择颜色,请将此字段设置为任何值,并 Invalidate() ListView:新颜色将立即应用。

结果样本

ListView OwnerDraw

Color listViewSelectionColor = Color.Orange;

protected void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    ListView lView = sender as ListView;
    if (lView.View == View.Details) return;
    TextFormatFlags flags = GetTextAlignment(lView, 0);
    Color itemColor = e.Item.ForeColor;
    if (e.Item.Selected) {
        using (SolidBrush bkgrBrush = new SolidBrush(listViewSelectionColor)) {
            e.Graphics.FillRectangle(bkgrBrush, e.Bounds);
        }
        itemColor = e.Item.BackColor;
    }
    else {
        e.DrawBackground();
    }
    TextRenderer.DrawText(e.Graphics, e.Item.Text, e.Item.Font, e.Bounds, itemColor, flags);

    if (lView.View == View.Tile && e.Item.SubItems.Count > 1)
    {
        var subItem = e.Item.SubItems[1];
        flags = GetTextAlignment(lView, 1);
        TextRenderer.DrawText(e.Graphics, subItem.Text, subItem.Font, e.Bounds, SystemColors.GrayText, flags);
    }
}

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    ListView lView = sender as ListView;
    TextFormatFlags flags = GetTextAlignment(lView, e.ColumnIndex);
    Color itemColor = e.Item.ForeColor;
    if (e.Item.Selected) {
        if (e.ColumnIndex == 0 || lView.FullRowSelect) {
            using (SolidBrush bkgrBrush = new SolidBrush(listViewSelectionColor)) {
                e.Graphics.FillRectangle(bkgrBrush, e.Bounds);
            }
            itemColor = e.Item.BackColor;
        }
    }
    else  {
        e.DrawBackground();
    }
    TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, e.Bounds, itemColor, flags);
}

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

private TextFormatFlags GetTextAlignment(ListView lstView, int colIndex)
{
    TextFormatFlags flags = (lstView.View == View.Tile)
        ? (colIndex == 0) ? TextFormatFlags.Default : TextFormatFlags.Bottom
        : TextFormatFlags.VerticalCenter;

    flags |= TextFormatFlags.LeftAndRightPadding | TextFormatFlags.NoPrefix;
    switch (lstView.Columns[colIndex].TextAlign)
    {
        case HorizontalAlignment.Left:
            flags |= TextFormatFlags.Left;
            break;
        case HorizontalAlignment.Right:
            flags |= TextFormatFlags.Right;
            break;
        case HorizontalAlignment.Center:
            flags |= TextFormatFlags.HorizontalCenter;
            break;
    }
    return flags;
}