2009-05-15 8 views
10

私はC#VS2005でウィンドウアプリケーションを開発しています。最初の列にチェックボックスがあるdataGridViewがあります。今私は、列のチェックボックスが選択される必要がありますすべてのチェックボックスを選択する場合は、列ヘッダーもCheckBoxにします。 どうすればいいですか? 私はCode Project linkDataGridViewのColumnHeaderとしてCheckboxを持つ方法

を参照さが、私はFirstCell(ないヘッダ)をクリックすると全ての下のセルを選択得ている、ことを使用している場合。しかし、私は列ヘッダーのCheckBoxをしたい。これどうやってするの。?

+0

あなたが指定したコードが不完全でバグがありますので、完全なコードを入力してください。私はこのコードが必要です。よろしくご連絡ください ズハイブ –

答えて

12

DataGridView列の列ヘッダーにCheckBoxが必要でした。ここで私はそれをやった方法は次のとおりです。

  • チェック状態を保存し、OSスタイルのビジュアルCheckBox表現を提供するためにSystem.Windows.Forms.CheckBoxを使用して内部DataGridViewColumnHeaderCell
  • から継承するクラスを作成します。
  • Checkedプロパティを提供するバッファとしてBitmapを使用し、その上に通常のCheckBoxを描く(CheckBox.DrawToBitmapを使用して)
  • オーバーライドDataGridViewColumnHeaderCell.Paintと、必要に応じて、Paint
  • によって供給Graphicsにバッファを描画する前にバッファを更新DataGridViewColumnHeaderCellおよびCheckedChangedイベントの場合
  • DataGridViewが入力されたときに、派生したDataGridViewColumnHeaderCellを列のHeaderCellに置き換えます。
  • チェックし、それが列ヘッダーをクリックしたときに、マウスクリックがCheckBox
  • の境界内にある場合にのみチェックをすべて実装/オフ、すべての派生クラスの外をを聞くことによってCheckBoxのチェックを外しますCheckedChangedイベント、基礎となるデータオブジェクトを更新して、ここでDataGridView

更新するResetBindingsを呼び出し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

私はこれが少し古くは知っていますが、あなたはこれの完全な例を提供することができますか?あなたのコードを使用しようとするとエラーが発生します。 – Misiu

+0

コードの最後の部分にエラーFORが続き、ELSEが続きます。 – Riju

10

上記の解決策は一種ですが、より簡単な方法もあります。 これらの2つの方法を単に追加するだけで、必要なものを手に入れることができます。

まず、あなたのコードにshow_chkBoxメソッドを追加し、フォームのonload機能やあなたの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); 
} 

、その後、あなたはヘッダにあるチェックボックスを持っているでしょう。選択問題については

、ちょうどこのコードを追加します。

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

これは良いことですが、1つのチェックボックスを個別にチェックすると、すべてが同期しなくなります。 –

+0

私はそうは思わない、私はこのコードを長い間使用してきたが、この問題は見ていない。あなたは何をやっているのか正確に教えてくれますか? – Ehsan

+1

多くの例を試しましたが、私のチェックボックスは常にグリッドビューの左上隅にあります。その理由は何ですか? –

2

あなたがチェックボックスセルが選択されている場合、それは、チェックボックスのUIを更新しないことを知っている必要があり@Ehsanソリューションを選択した場合。後でRefreshEdit()を呼び出す必要があります。

コントロールがDataGridViewの子コントロールである場合にのみ発生します。何らかの理由で、子コントロールである場合、選択されたセルのチェックボックスは、独自のUIをリフレッシュすることができません。

+0

これはありがとうございます。これは重要な部分です。 –

0

簡単な方法でエッサンさんに感謝します。問題のために、ただ1つのチェックボックスが常に左上隅にあります、私はそれぞれに名前接尾辞を追加し、解決します。さらに、オブジェクトの送信者を直接キャストすることで、イベントの処理方法を少し変更したいのですが(このメソッドが他の種類のコントロールのイベントの処理にも使用されていない限り)

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

新しい質問がある場合は、[Ask Question](http://stackoverflow.com/questions/ask)ボタンをクリックして質問してください。コンテキストを提供する場合は、この質問へのリンクを含めてください。 –

関連する問題