2009-05-15 53 views
10

Estoy desarrollando una aplicación de ventana en C# VS2005. Tengo un dataGridView en el que la primera columna tiene casillas de verificación. Ahora quiero que el encabezado de columna también sea un CheckBox, que si selecciono todo el Checkboxex en la columna debería ser seleccionado. ¿Cómo puedo hacer esto? que se refiere el Code Project linkCómo tener Checkbox como ColumnHeader de dataGridView

Pero si uso que, si hago clic en el firstcell (no el encabezado) todas las celdas debajo están siendo seleccionados. Pero quiero un CheckBox en el encabezado Columna. Cómo puedo hacer esto.?

+0

Indique el código completo, ya que el código que ha proporcionado está incompleto y tiene errores. Necesito este código. Saludos Zuhaib –

Respuesta

12

También necesitaba tener un CheckBox en el encabezado de columna de una columna DataGridView. Así es como lo hice:

  • crear una clase que hereda de DataGridViewColumnHeaderCell
  • uso interno un System.Windows.Forms.CheckBox para almacenar el estado de activación y proporcionar el sistema operativo de estilo CheckBox representación visual.
  • Utilice un Bitmap como un amortiguador y dibujar la regularidad CheckBox en él (usando CheckBox.DrawToBitmap)
  • Anulación DataGridViewColumnHeaderCell.Paint y, si es necesario, actualizar la memoria intermedia antes de sacar la memoria intermedia a la Graphics suministrada por Paint
  • Proporcionar una propiedad Checked en el derivado DataGridViewColumnHeaderCell, y también un Sustituto evento CheckedChanged
  • el derivado DataGridViewColumnHeaderCell en la columna de HeaderCell cuando se está poblada la DataGridView.
  • activar y desactivar la CheckBox cuando se hace clic en el encabezado de la columna, sólo si el clic del ratón está dentro de los límites de la CheckBox
  • Implementar el registro de entrada, todos/Deseleccionar todo fuera de la clase derivada escuchando la CheckedChanged caso, la actualización del objeto de datos subyacente y luego llamar ResetBindings para actualizar el DataGridView

Ésta es la clase que escribí que se deriva de DataGridViewColumnHeaderCell:

class DataGridViewCheckBoxColumnHeaderCell : DataGridViewColumnHeaderCell 
{ 
    private Bitmap buffer; 
    private CheckBox checkBox; 
    private Rectangle checkBoxBounds; 

    public DataGridViewCheckBoxColumnHeaderCell() 
    { 
     this.checkBox = new CheckBox(); 
    } 

    public event EventHandler CheckedChanged; 

    public bool Checked 
    { 
     get 
     { 
      return this.checkBox.Checked; 
     } 

     set 
     { 
      if (!this.Checked == value) 
      { 
       this.checkBox.Checked = value; 
       if (this.buffer != null) 
       { 
        this.buffer.Dispose(); 
        this.buffer = null; 
       } 

       this.OnCheckedChanged(EventArgs.Empty); 

       if (this.DataGridView != null) 
       { 
        this.DataGridView.Refresh(); 
       } 
      } 
     } 
    } 

    protected override void Paint(
     Graphics graphics, 
     Rectangle clipBounds, 
     Rectangle cellBounds, 
     int rowIndex, 
     DataGridViewElementStates dataGridViewElementState, 
     object value, 
     object formattedValue, 
     string errorText, 
     DataGridViewCellStyle cellStyle, 
     DataGridViewAdvancedBorderStyle advancedBorderStyle, 
     DataGridViewPaintParts paintParts) 
    { 
     // Passing String.Empty in place of 
     // value and formattedValue prevents 
     // this header cell from having text. 

     base.Paint(
      graphics, 
      clipBounds, 
      cellBounds, 
      rowIndex, 
      dataGridViewElementState, 
      String.Empty, 
      String.Empty, 
      errorText, 
      cellStyle, 
      advancedBorderStyle, 
      paintParts); 

     if (this.buffer == null 
      || cellBounds.Width != this.buffer.Width 
      || cellBounds.Height != this.buffer.Height) 
     { 
      this.UpdateBuffer(cellBounds.Size); 
     } 

     graphics.DrawImage(this.buffer, cellBounds.Location); 
    } 

    protected override Size GetPreferredSize(
     Graphics graphics, 
     DataGridViewCellStyle cellStyle, 
     int rowIndex, 
     Size constraintSize) 
    { 
     return this.checkBox.GetPreferredSize(constraintSize); 
    } 

    protected override void OnMouseClick(DataGridViewCellMouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Left 
      && this.checkBoxBounds.Contains(e.Location)) 
     { 
      this.Checked = !this.Checked; 
     } 

     base.OnMouseClick(e); 
    } 

    private void UpdateBuffer(Size size) 
    { 
     Bitmap updatedBuffer = new Bitmap(size.Width, size.Height); 

     this.checkBox.Size = size; 

     if (this.checkBox.Size.Width > 0 && this.checkBox.Size.Height > 0) 
     { 
      Bitmap renderedCheckbox = new Bitmap(
       this.checkBox.Width, 
       this.checkBox.Height); 

      this.checkBox.DrawToBitmap(
       renderedCheckbox, 
       new Rectangle(new Point(), this.checkBox.Size)); 

      MakeTransparent(renderedCheckbox, this.checkBox.BackColor); 
      Bitmap croppedRenderedCheckbox = AutoCrop(
       renderedCheckbox, 
       Color.Transparent); 

      // TODO implement alignment, right now it is always 
      // MiddleCenter regardless of this.Style.Alignment 

      this.checkBox.Location = new Point(
       (updatedBuffer.Width - croppedRenderedCheckbox.Width)/2, 
       (updatedBuffer.Height - croppedRenderedCheckbox.Height)/2); 

      Graphics updatedBufferGraphics = Graphics.FromImage(updatedBuffer); 
      updatedBufferGraphics.DrawImage(
       croppedRenderedCheckbox, 
       this.checkBox.Location); 

      this.checkBoxBounds = new Rectangle(
       this.checkBox.Location, 
       croppedRenderedCheckbox.Size); 

      renderedCheckbox.Dispose(); 
      croppedRenderedCheckbox.Dispose(); 
     } 

     if (this.buffer != null) 
     { 
      this.buffer.Dispose(); 
     } 

     this.buffer = updatedBuffer; 
    } 

    protected virtual void OnCheckedChanged(EventArgs e) 
    { 
     EventHandler handler = this.CheckedChanged; 
     if (handler != null) 
     { 
      handler(this, e); 
     } 
    } 

    // The methods below are helper methods for manipulating Bitmaps 

    private static void MakeTransparent(Bitmap bitmap, Color transparencyMask) 
    { 
     int transparencyMaskArgb = transparencyMask.ToArgb(); 
     int transparentArgb = Color.Transparent.ToArgb(); 

     List deadColumns = new List(); 

     for (int x = 0; x = 0; x--) 
     { 
      if (deadColumns.Count == bitmap.Height) 
      { 
       break; 
      } 

      for (int y = bitmap.Height - 1; y >= 0; y--) 
      { 
       if (deadColumns.Contains(y)) 
       { 
        continue; 
       } 

       int pixel = bitmap.GetPixel(x, y).ToArgb(); 

       if (pixel == transparencyMaskArgb) 
       { 
        bitmap.SetPixel(x, y, Color.Transparent); 
       } 
       else if (pixel != transparentArgb) 
       { 
        deadColumns.Add(y); 
        break; 
       } 
      } 
     } 
    } 

    public static Bitmap AutoCrop(Bitmap bitmap, Color backgroundColor) 
    { 
     Size croppedSize = bitmap.Size; 
     Point cropOrigin = new Point(); 
     int backgroundColorToArgb = backgroundColor.ToArgb(); 

     for (int x = bitmap.Width - 1; x >= 0; x--) 
     { 
      bool allPixelsAreBackgroundColor = true; 
      for (int y = bitmap.Height - 1; y >= 0; y--) 
      { 
       if (bitmap.GetPixel(x, y).ToArgb() != backgroundColorToArgb) 
       { 
        allPixelsAreBackgroundColor = false; 
        break; 
       } 
      } 

      if (allPixelsAreBackgroundColor) 
      { 
       croppedSize.Width--; 
      } 
      else 
      { 
       break; 
      } 
     } 

     for (int y = bitmap.Height - 1; y >= 0; y--) 
     { 
      bool allPixelsAreBackgroundColor = true; 
      for (int x = bitmap.Width - 1; x >= 0; x--) 
      { 
       if (bitmap.GetPixel(x, y).ToArgb() != backgroundColorToArgb) 
       { 
        allPixelsAreBackgroundColor = false; 
        break; 
       } 
      } 

      if (allPixelsAreBackgroundColor) 
      { 
       croppedSize.Height--; 
      } 
      else 
      { 
       break; 
      } 
     } 

     for (int x = 0; x = 0 && xWhole = 0) 
       { 
        bitmapSection.SetPixel(x, y, bitmap.GetPixel(xWhole, yWhole)); 
       } 
       else 
       { 
        bitmapSection.SetPixel(x, y, Color.Transparent); 
       } 
      } 
     } 

     return bitmapSection; 
    } 
} 
+0

Sé que esto es un poco antiguo, pero ¿podría darnos un ejemplo completo de esto? Cuando trato de usar tu código obtengo errores. – Misiu

+0

última parte del código está lleno de error FOR seguido de un ELSE. puede corregirlo – Riju

10

La solución anterior es buena, ¡pero también hay una manera más fácil! ¡Simplemente agregue estos dos métodos y luego tendrá lo que desea!

primero Añadir un método show_chkBox a su código y lo llaman en la función onload de su formulario o después de la creación de su DataGridView:

private void show_chkBox() 
{ 
    Rectangle rect = dataGridView1.GetCellDisplayRectangle(0, -1, true); 
    // set checkbox header to center of header cell. +1 pixel to position 
    rect.Y = 3; 
    rect.X = rect.Location.X + (rect.Width/4); 
    CheckBox checkboxHeader = new CheckBox(); 
    checkboxHeader.Name = "checkboxHeader"; 
    //datagridview[0, 0].ToolTipText = "sdfsdf"; 
    checkboxHeader.Size = new Size(18, 18); 
    checkboxHeader.Location = rect.Location; 
    checkboxHeader.CheckedChanged += new EventHandler(checkboxHeader_CheckedChanged); 
    dataGridView1.Controls.Add(checkboxHeader); 
} 

y entonces tendría la casilla de verificación en la cabecera.

Para el problema de la selección, sólo tiene que añadir este código:

private void checkboxHeader_CheckedChanged(object sender, EventArgs e) 
{    
    CheckBox headerBox = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]); 
    int index = 0; 
    for (int i = 0; i < dataGridView1.RowCount; i++) 
    { 
     dataGridView1.Rows[i].Cells[0].Value = headerBox.Checked; 
    } 
} 
+0

Esto es bueno, pero marque una casilla de verificación de manera independiente y todo se desincroniza. –

+0

No lo creo, he estado usando este código durante mucho tiempo y no he visto este problema. ¿Me puede decir exactamente lo que está haciendo? – Ehsan

+1

Probé muchos ejemplos, pero mi casilla de verificación está siempre en la esquina superior izquierda de la vista de la cuadrícula. ¿Alguna razón para eso? –

2

Si elige solución @Ehsan debe saber que si se selecciona la casilla de verificación de células no actualizará la interfaz de usuario casilla. Necesita llamar a RefreshEdit() luego.

Solo ocurre cuando el control es control de niños de la vista de cuadrícula de datos. Por alguna razón, cuando se trata de un control de niños, las casillas de verificación de las celdas seleccionadas no pueden actualizar la interfaz de usuario por su cuenta.

+0

Gracias por esto, es una pieza importante para incluir. –

0

Gracias a Ehsan por la manera fácil, funciona bien para mí. Para el problema, solo un CheckBox está siempre en la esquina superior izquierda, agrego un sufijo de nombre a cada uno y lo resuelvo. Además, me gustaría modificar ligeramente el método de gestión de eventos lanzando directamente el remitente del objeto, ya que era muy específico en la creación (a menos que este método también se utilice para manejar otro tipo de evento de controles).

private string[] _colLst = columNameArray; 
private void AddCheckBoxGridViewHeader() 
{ 
    for (int ndx = 0; ndx < _colLst.Length; ndx++) 
    { 
     var rect = dtgv1.GetCellDisplayRectangle(ndx, -1, true); 
     var x = rect.X + (rect.Width * 4/5); 
     var y = 3; 
     Rectangle nrect = new Rectangle(x, y, rect.Width, rect.Height); 
     CheckBox checkboxHeader = new CheckBox(); 
     checkboxHeader.BackColor = Color.Transparent; 
     checkboxHeader.Name = "checkboxHeader" + ndx; 
     checkboxHeader.Size = new Size(18, 18); 
     checkboxHeader.Location = nrect.Location; 
     checkboxHeader.CheckedChanged += new EventHandler(checkboxHeader_CheckedChanged); 
     dtgv1.Controls.Add(checkboxHeader); 
    } 
} 

private void checkboxHeader_CheckedChanged(object sender, EventArgs e) 
{ 
    //CheckBox headerBox = ((CheckBox)dtgv1.Controls.Find("checkboxHeader", true)[0]); 

    var headerBox = (CheckBox)sender; 
    var b = headerBox.Checked; 
    var c = int.Parse(headerBox.Name.Replace("checkboxHeader", "")); 
    for (int i = 0; i < dtgv1.RowCount; i++) 
    { 
     dtgv1.Rows[i].Cells[c].Style = new DataGridViewCellStyle(); 
     dtgv1.Rows[i].Cells[c].Style.BackColor = (b)? Color.Salmon : Color.White; 
    } 
} 
+0

Si tiene una nueva pregunta, por favor, haga clic en el botón [Ask Question] (http://stackoverflow.com/questions/ask). Incluye un enlace a esta pregunta si ayuda a proporcionar contexto. –