当鼠标悬停在一行上时,突出显示DataGridView中的行

时间:2017-02-27 11:21:41

标签: c# winforms datagridview mouseover

我有一个DataGridView,目前看起来如下图所示:

enter image description here

我想要实现的是当我将鼠标悬停在任何一行的任何列上时,整个行应突出显示,背景颜色应变为不同的颜色,如下图所示。

enter image description here

你能帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:4)

您可以在RowPostPaint事件中突出显示鼠标指针下的行,也可以在派生的DataGridView中覆盖OnRowPostPaint事件。在这种方法中,您可以自己绘制整行,或者只绘制其中的一部分或在行上绘制一些东西:

enter image description here

示例

using System;
using System.Drawing;
using System.Windows.Forms;
public class MyDataGridView : DataGridView
{
    public MyDataGridView() { DoubleBuffered = true; }
    protected override void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
    {
        base.OnRowPostPaint(e);
        if (this.RectangleToScreen(e.RowBounds).Contains(MousePosition))
        {
            using (var b = new SolidBrush(Color.FromArgb(50, Color.Blue)))
            using (var p = new Pen(Color.Blue))
            {
                var r = e.RowBounds; r.Width -= 1; r.Height -= 1;
                e.Graphics.FillRectangle(b, r);
                e.Graphics.DrawRectangle(p, r);
            }
        }
    }
    protected override void OnMouseMove(MouseEventArgs e){
        base.OnMouseMove(e); this.Invalidate();
    }
    protected override void OnMouseEnter(EventArgs e){
        base.OnMouseEnter(e); this.Invalidate();
    }
    protected override void OnMouseLeave(EventArgs e){
        base.OnMouseLeave(e); this.Invalidate();
    }
    protected override void OnScroll(ScrollEventArgs e){
        base.OnScroll(e); this.Invalidate();
    }
}

答案 1 :(得分:2)

您在第二个屏幕截图中看到的内容不是DataGridView,而是ListView模式中的Details

listView1.View = View.Details;
listView1.FulRowSelect = true;

使用Columns填充列,Items填充行。连续的第二列和更多列可以通过每个项目的SubItems属性填充。

默认情况下,该行不会自动悬停,选择外观是一条丑陋的深蓝色静态线。要显示这个漂亮的淡蓝色悬停,可以通过一个小技巧在列表视图中启用“资源管理器”主题:

internal sealed class AdvancedListView : ListView
{
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);

        if (!DesignMode && Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6)
        {
            SetWindowTheme(Handle, "explorer", null);
        }
    }

    [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
    private extern static int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList);
}

现在,您将获得与第二个屏幕截图完全相同的外观和感觉......

好吧,除了订购。要启用那个也是隐藏功能的小箭头,请使用下面的类(请注意,它在此实现中按字符串值排序):

internal class ListViewSorter : IComparer
{
    private const int HDI_FORMAT = 0x0004;
    private const int HDF_SORTUP = 0x0400;
    private const int HDF_SORTDOWN = 0x0200;
    private const int LVM_GETHEADER = 0x1000 + 31; // LVM_FIRST + 31
    private const int HDM_GETITEM = 0x1200 + 11; // HDM_FIRST + 11
    private const int HDM_SETITEM = 0x1200 + 12; // HDM_FIRST + 12

    private readonly int column;
    private readonly SortOrder sortOrder;


    public ListViewSorter(SortOrder sortOrder, int col, ListView listView)
    {
        IntPtr hColHeader = SendMessage(listView.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
        HDITEM hdItem = new HDITEM();
        IntPtr colHeader = new IntPtr(col);

        hdItem.mask = HDI_FORMAT;
        SendMessageItem(hColHeader, HDM_GETITEM, colHeader, ref hdItem);

        if (sortOrder == SortOrder.Ascending)
        {
            hdItem.fmt &= ~HDF_SORTDOWN;
            hdItem.fmt |= HDF_SORTUP;
        }
        else if (sortOrder == SortOrder.Descending)
        {
            hdItem.fmt &= ~HDF_SORTUP;
            hdItem.fmt |= HDF_SORTDOWN;
        }
        else if (sortOrder == SortOrder.None)
        {
            hdItem.fmt &= ~HDF_SORTDOWN & ~HDF_SORTUP;
        }

        SendMessageItem(hColHeader, HDM_SETITEM, colHeader, ref hdItem);
        this.sortOrder = sortOrder;
        this.column = col;
    }

    protected virtual int DoCompare(ListViewItem item1, ListViewItem item2)
    {
        return sortOrder == SortOrder.Ascending ? String.Compare(item1.SubItems[column].Text, item2.SubItems[column].Text, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)
            : String.Compare(item2.SubItems[column].Text, item1.SubItems[column].Text, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase);
    }

    public int Compare(object x, object y)
    {
        ListViewItem item1 = (ListViewItem)x;
        ListViewItem item2 = (ListViewItem)y;
        return DoCompare(item1, item2);
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct HDITEM
    {
        public int mask;
        public int cxy;
        [MarshalAs(UnmanagedType.LPTStr)] public string pszText;
        public IntPtr hbm;
        public int cchTextMax;
        public int fmt;
        public int lParam;
        public int iImage;
        public int iOrder;
    };

    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", EntryPoint = "SendMessage")]
    private static extern IntPtr SendMessageItem(IntPtr handle, int msg, IntPtr wParam, ref HDITEM lParam);
}

要对点击的列应用排序,请使用ColumnClick事件:

private void advancedListView1_ColumnClick(object sender, ColumnClickEventArgs e)
{
    advancedListView1.Sorting = advancedListView1.Sorting == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
    advancedListView1.ListViewItemSorter = new ListViewSorter(advancedListView1.Sorting, e.Column, advancedListView1);
}

在Windows 7中,它将如截图所示。在我的Windows 10中它看起来像这样:

Advanced ListView in Windows 10

答案 2 :(得分:0)

你可以这样做:

private void dataGridView1_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
{ DataGridView1.ClearSelection();
    If (e.RowIndex > -1) {  DataGridView1.Rows(e.RowIndex).Selected = True;  }          }

我认为使用行的背景颜色是不可能的,但我不确定...