带有 AllowColumnReorder 的 ListView OwnerDraw 不能正常工作

ListView OwnerDraw with AllowColumnReorder don't work correct

我正在绘制自定义 ListView,OwnerDraw 属性 设置为 'true'。 listview 也有 AllowColumnReorder 'true' 属性.

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    e.Graphics.DrawString(e.SubItem.Text, Font, Brushes.Black, e.Bounds);
}

这工作正常:

但是如果我移动第一列就会出现绘图问题 - 前两列的数据被绘制在第一列中,而被移动的列中的数据根本没有被绘制:

发生这种情况是因为 e.Bounds 两个不同列的值相等。我该怎么做才能获得正确的 e.Bounds 值。

是的,这是 ListView class 中的错误。它的私有 GetItemRectOrEmpty() method 很无聊。作为错误解决方法编写,内部错误编号 VSWhidbey #163674。一个错误修复导致另一个错误是一个非常传统的编程事故,大男孩也会犯错误 :) 当它询问 Windows 项目矩形时,通过 e.Bounds 属性 传递给你,它会出错并要求 ItemBoundsPortion.Entire。这是完整的 ListViewItem 矩形,包括子项。

幸运的是,解决方法很简单,您可以自己使用 ItemBoundsPortion.ItemOnly:

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e) {
    var bounds = e.Bounds;
    if (e.ColumnIndex == 0) {
        bounds = listView1.GetItemRect(e.ItemIndex, ItemBoundsPortion.ItemOnly);
    }
    e.Graphics.DrawString(e.SubItem.Text, Font, Brushes.Black, bounds);
}

感谢 Hans Passant 提供的信息。我使用下一个代码修复了这个错误:

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
    {
        Rectangle bounds = e.Bounds;
        if (e.ColumnIndex == 0 && listView1.Columns[0].DisplayIndex != 0)
        {
            bounds = GetFirstColumnCorrectRectangle(e.Item);
        }
        e.Graphics.DrawString(e.SubItem.Text, Font, Brushes.Black, bounds);
    }

    private Rectangle GetFirstColumnCorrectRectangle(ListViewItem item)
    {
        int i;
        for (i = 0; i < listView1.Columns.Count; i++)
            if (listView1.Columns[i].DisplayIndex == listView1.Columns[0].DisplayIndex - 1)
                break;
        return new Rectangle(item.SubItems[i].Bounds.Right, item.SubItems[i].Bounds.Y, listView1.Columns[0].Width, item.SubItems[i].Bounds.Height);
    }