2009-05-15 118 views
10

Tôi đang phát triển một ứng dụng cửa sổ trong C# VS2005. Tôi có một dataGridView trong đó cột đầu tiên có Hộp kiểm. Bây giờ tôi muốn tiêu đề cột cũng là một CheckBox mà nếu tôi chọn tất cả các Checkboxex trong cột nên được chọn. Làm cách nào để tôi thực hiện việc này? Tôi gọi các Code Project linkLàm thế nào để có Checkbox là ColumnHeader của dataGridView

Nhưng nếu tôi sử dụng đó, nếu tôi nhấp vào FirstCell (không Header) tất cả các ô dưới đây đang nhận được lựa chọn. Nhưng tôi muốn một CheckBox trong tiêu đề cột. Tôi có thể làm cái này như thế nào.?

+0

Vui lòng cung cấp cho chúng tôi mã hoàn chỉnh vì mã bạn đã cung cấp chưa hoàn chỉnh và bị lỗi. Tôi cần mã này. Trân trọng Zuhaib –

Trả lời

12

Tôi cũng cần có một CheckBox trong tiêu đề cột của cột DataGridView. Đây là cách tôi đã làm nó:

  • Tạo một lớp mà được thừa hưởng từ DataGridViewColumnHeaderCell
  • Bên sử dụng một System.Windows.Forms.CheckBox để lưu trữ trạng thái kiểm tra và cung cấp hệ điều hành theo kiểu thị giác CheckBox đại diện.
  • Sử dụng một Bitmap như một bộ đệm và vẽ thường xuyên CheckBox vào nó (sử dụng CheckBox.DrawToBitmap)
  • Override DataGridViewColumnHeaderCell.Paint và, nếu cần thiết, cập nhật bộ đệm trước khi rút ra bộ đệm cho Graphics cung cấp bởi Paint
  • Cung cấp một tài sản Checked trên số xuất phát DataGridViewColumnHeaderCell và cũng là sự kiện được đánh dấuChọn thay đổi
  • Thay thế số xuất phát DataGridViewColumnHeaderCell trong cột HeaderCell khi số DataGridView đang được điền.
  • Kiểm tra và bỏ chọn CheckBox khi nó được tiêu đề cột được nhấp, chỉ khi click chuột nằm trong phạm vi giới hạn của CheckBox
  • Thực hiện việc kiểm tra-tất cả/bỏ chọn-tất cả các bên ngoài của lớp được thừa kế bằng cách lắng nghe những CheckedChanged sự kiện, cập nhật các đối tượng dữ liệu cơ bản và sau đó gọi ResetBindings để cập nhật các DataGridView

đây là lớp tôi đã viết trong đó có nguồn gốc từ 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

Tôi biết điều này hơi cũ nhưng bạn có thể vui lòng cung cấp ví dụ đầy đủ về điều này không? Khi tôi cố gắng sử dụng mã của bạn, tôi nhận được lỗi. – Misiu

+0

phần cuối cùng của mã có đầy đủ lỗi FOR tiếp theo là ELSE. bạn có thể vui lòng sửa nó – Riju

10

Các giải pháp trên là loại tốt, nhưng cũng có một cách dễ dàng hơn! Chỉ cần thêm hai phương pháp này và sau đó bạn sẽ có những gì bạn muốn!

Đầu tiên thêm một phương pháp show_chkBox để mã của bạn và gọi nó trong onload chức năng của biểu mẫu hoặc sau khi tạo DataGridView của bạn:

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

và sau đó bạn sẽ có hộp kiểm trong tiêu đề.

Đối với vấn đề lựa chọn, chỉ cần thêm đoạn mã này:

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

Điều này là tốt, nhưng hãy chọn một hộp kiểm độc lập và toàn bộ nội dung sẽ không đồng bộ. –

+0

Tôi không nghĩ như vậy, tôi đã sử dụng mã này trong một thời gian dài, và chưa thấy vấn đề này. Bạn có thể cho tôi biết chính xác những gì bạn đang làm không? – Ehsan

+1

Tôi đã thử nhiều ví dụ nhưng hộp kiểm của tôi luôn ở góc trên cùng bên trái của chế độ xem lưới. Có lý do gì không? –

2

Nếu bạn chọn @Ehsan giải pháp bạn phải biết rằng nếu ô checkbox được chọn nó sẽ không cập nhật giao diện người dùng hộp kiểm. Bạn cần gọi lại hàm RefreshEdit() sau đó.

Điều này chỉ xảy ra khi điều khiển là kiểm soát trẻ em của chế độ xem dữ liệu. Đối với một số lý do khi đó là kiểm soát trẻ em, các hộp kiểm ô được chọn không thể tự làm mới giao diện người dùng.

+0

Cảm ơn vì điều này, đó là một phần quan trọng cần đưa vào. –

0

Cảm ơn Ehsan một cách dễ dàng, hoạt động tốt cho tôi. Đối với vấn đề chỉ có một CheckBox luôn ở góc trên bên trái, tôi thêm một hậu tố tên cho mỗi một và giải quyết. Ngoài ra, tôi muốn sửa đổi một chút phương thức xử lý sự kiện bằng cách trực tiếp truyền người gửi đối tượng vì nó rất cụ thể trong quá trình tạo (trừ khi phương thức này được sử dụng để xử lý sự kiện loại điều khiển khác).

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

Nếu bạn có câu hỏi mới, vui lòng hỏi câu hỏi bằng cách nhấp vào nút [Hỏi câu hỏi] (http://stackoverflow.com/questions/ask). Bao gồm một liên kết đến câu hỏi này nếu nó giúp cung cấp ngữ cảnh. –

Các vấn đề liên quan