1

我有具有多选模式的 DataGridView 和具有 DataGridViewButtonColumn(Button) 的网格行。我可以使用与 windows 文件夹/文件功能相同的 CRTL 和 SHIFT 键选择多行但是当我在任何行上单击行按钮(DataGridViewButtonColumn) 之后多选这个多选的行信息正在丢失并且当前行被突出显示。我需要保留这个多选的行信息。如果我在单击行按钮时使用 CTRL 键,则当前被取消选择/选择。

我正在使用 VS 2012、c# 和 winforms。在每个网格行上有按钮和复选框的datagridview上保存多选行信息的最佳方法是什么?感谢您提前提供任何帮助,并感谢任何建议/代码片段。

DatagridView 属性设置:

        dataGridView1.AutoGenerateColumns = false;
        dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        dataGridView1.MultiSelect = true;
        dataGridView1.ReadOnly = false;
4

1 回答 1

0

您必须自定义自己的DataGridView. 这允许您将自定义代码添加到WndProc然后您可以捕获消息WM_LBUTTONDOWN,检查鼠标是否在 a 上DataGridViewButtonCell以丢弃该消息。不知何故,CellContentClick仍然提出了(这是由 的内部实现完成的DataGridView)。然而丢弃后WM_LBUTTONDOWN,就失去了压制状态Button的观感。这有点烦人。因此,为了模仿这种状态,我们必须自己绘制按钮。绘制按钮让我们模仿更多的状态,而不仅仅是按下状态(例如hot statenormal state)。这是适合您的代码,可以完美运行:

public class CustomGrid : DataGridView
{
    DataGridViewCell downButton;
    DataGridViewCell lastHoveredCell;
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x201)//WM_LBUTTONDOWN = 0x201
        {
            HitTestInfo ht = TryHitTest(m);
            if (ht.Type == DataGridViewHitTestType.Cell)
            {
                downButton = this[ht.ColumnIndex, ht.RowIndex];
                if (SelectedCells.Count > 1&&downButton is DataGridViewButtonCell){                                    
                   InvalidateCell(ht.ColumnIndex, ht.RowIndex);
                   return;
                }
            }
         } else if (m.Msg == 0x202) downButton = null; //WM_LBUTTONUP = 0x202
         else if (m.Msg == 0x200) { //WM_MOUSEMOVE = 0x200
            HitTestInfo ht = TryHitTest(m);
            if (ht.Type == DataGridViewHitTestType.Cell)
            {
                if (lastHoveredCell != this[ht.ColumnIndex, ht.RowIndex]){
                    if(lastHoveredCell != null &&
                       lastHoveredCell.DataGridView!=null)        
                       InvalidateCell(lastHoveredCell);                        
                    lastHoveredCell = this[ht.ColumnIndex, ht.RowIndex];
                    InvalidateCell(lastHoveredCell);                        
                }
            }
         }            
         base.WndProc(ref m);            
    }
    private HitTestInfo TryHitTest(Message m)
    {
        int x = m.LParam.ToInt32() & 0xffff;
        int y = m.LParam.ToInt32() >> 16;
        return HitTest(x, y);
    }
    protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
    {
        if (e.ColumnIndex > -1 && e.RowIndex > -1 && this[e.ColumnIndex, e.RowIndex] is DataGridViewButtonCell)
        {
            e.Handled = true;
            e.PaintBackground(e.ClipBounds, false);
            Rectangle buttonBounds = e.CellBounds;
            string text = ((DataGridViewButtonColumn)Columns[e.ColumnIndex]).Text;
            var buttonState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
            if(buttonBounds.Contains(PointToClient(MousePosition))){
                buttonState = MouseButtons == MouseButtons.Left && downButton == this[e.ColumnIndex, e.RowIndex] ?
                              System.Windows.Forms.VisualStyles.PushButtonState.Pressed :
                              System.Windows.Forms.VisualStyles.PushButtonState.Hot;
            }                                
            ButtonRenderer.DrawButton(e.Graphics, buttonBounds, text, e.CellStyle.Font, false, buttonState);                
        }
        else base.OnCellPainting(e);            
    }
    protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e) {
        base.OnColumnWidthChanged(e);            
        InvalidateColumn(e.Column.Index);
    }  
}

此屏幕截图显示,当所有选定的单元格仍处于选中状态时,正在按下一个按钮。

在此处输入图像描述

于 2013-11-10T11:10:41.933 回答