Winforms DataGridView с DataGridViewButtonColumn(кнопка) и режим множественного выбора позволил потерять информацию при нажатии на строку сетки Кнопка

У меня есть DataGridView с режимом множественного выбора и строкой сетки, имеющей DataGridViewButtonColumn(Button). Я могу выбирать строки с несколькими ключами, используя ключи CRTL и SHIFT, такие же, как функциональность папки / файла Windows, но когда я нажимаю на кнопку строки (DataGridViewButtonColumn) в любой строке после выполнения при многократном выборе эта информация о нескольких выбранных строках теряется, и текущая строка выделяется. Мне необходимо сохранить эту информацию о нескольких выбранных строках. Если я нажимаю клавишу CTRL при нажатии на кнопку строки, текущий отменяется / выбирается.

Я использую VS 2012, C# и Winforms. Каков наилучший способ хранения информации о нескольких выбранных строках в сетке данных, имеющей кнопки и флажки в каждой строке сетки? Спасибо за любую помощь заранее и любые предложения / фрагменты кода приветствуются.

Набор свойств DatagridView:

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

1 ответ

Решение

Вы должны настроить свой собственный DataGridView, Это позволяет добавить пользовательский код в WndProc тогда вы можете поймать сообщение WM_LBUTTONDOWN, проверьте, нажата ли мышь на DataGridViewButtonCell отказаться от этого сообщения. Каким-то образом CellContentClick все еще поднят (это делается путем внутренней реализации DataGridView). Однако после отбрасывания WM_LBUTTONDOWN, Button теряет вид и ощущение нажатого состояния. Это немного раздражает. Поэтому, чтобы имитировать это состояние, мы должны сами нарисовать кнопку. Рисование кнопки заставляет нас имитировать больше состояний, чем просто нажатое состояние (например, горячее состояние, нормальное состояние). Вот код для вас, работает отлично:

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);
    }  
}

Этот снимок экрана показывает, что нажата одна кнопка, пока все выбранные ячейки все еще выбираются.

введите описание изображения здесь

Другие вопросы по тегам