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、マウスが上にあるかどうかを確認して、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);
    }  
}

このスクリーンショットは、選択されたすべてのセルがまだ選択されている間に、1 つのボタンが押されていることを示しています。

ここに画像の説明を入力

于 2013-11-10T11:10:41.933 に答える