熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C# WinForm下DataGridView單元按鈕列

2013-11-13 09:48:34  來源: .NET編程 

  在C# WinForm下做過項目的朋友都知道其中的DataGridView控件默認只支持DataGridViewButtonColumnDataGridViewCheckBoxColumnDataGridViewComboBoxColumnDataGridViewImageColumnDataGridViewLinkColumn和DataGridViewTextBoxColumn六種列類型如果你想要在DataGridView的列中添加其它的子控件則需要自己實現DataGridViewColumn和DataGridViewCell這就意味著你需要從現有的列中繼承並改寫一些方法如實現一個支持單選按鈕的列或支持三種選擇狀態的多選按鈕的列

  6-22-2009 3-32-18 PM

  6-22-2009 3-31-44 PM     上面兩個截圖分別為RadioButton列和支持三種狀態的CheckBox列在DataGridView中的實現效果我是在Windows 中實現的因此顯示的效果跟在XP和Vista下有些區別Vista下CheckBox的第三種狀態(不確定狀態)顯示出來的效果是一個實心的藍色方塊

  下面我看具體來看看如何實現這兩種效果

  要實現自定義的DataGridView列你需要繼承並改寫兩個類一個是基於DataGridViewColumn的一個是基於DataGridViewCell的因為RadionButton和CheckBox的實現原理類似因此我們可以將這兩種列采用同一種方法實現創建DataGridViewDisableCheckBoxCell和DataGridViewDisableCheckBoxColumn兩個類分別繼承自DataGridViewCheckBoxCell和DataGridViewCheckBoxColumn代碼如下

  public class DataGridViewDisableCheckBoxCell: DataGridViewCheckBoxCell
{
    public bool Enabled { get; set; }

  // Override the Clone method so that the Enabled property is copied
    public override object Clone()
    {
        DataGridViewDisableCheckBoxCell cell = (DataGridViewDisableCheckBoxCell)baseClone();
        cellEnabled = thisEnabled;
        return cell;
    }

  // By default enable the CheckBox cell
    public DataGridViewDisableCheckBoxCell()
    {
        thisEnabled = true;
    }

  // Three state checkbox column cell
    protected override void Paint(Graphics graphics Rectangle clipBounds Rectangle cellBounds int rowIndex
        DataGridViewElementStates elementState object value object formattedValue string errorText
        DataGridViewCellStyle cellStyle DataGridViewAdvancedBorderStyle advancedBorderStyle DataGridViewPaintParts paintParts)
    {
        // The checkBox cell is disabled so paint the border background and disabled checkBox for the cell
        if (!thisEnabled)
        {
            // Draw the cell background if specified
            if ((paintParts & DataGridViewPaintPartsBackground) == DataGridViewPaintPartsBackground)
            {
                SolidBrush cellBackground = new SolidBrush(cellStyleBackColor);
                graphicsFillRectangle(cellBackground cellBounds);
                cellBackgroundDispose();
            }

  // Draw the cell borders if specified
            if ((paintParts & DataGridViewPaintPartsBorder) == DataGridViewPaintPartsBorder)
            {
                PaintBorder(graphics clipBounds cellBounds cellStyle advancedBorderStyle);
            }

  // Calculate the area in which to draw the checkBox
            CheckBoxState state = CheckBoxStateMixedDisabled;
            Size size = CheckBoxRendererGetGlyphSize(graphics state);
            Point center = new Point(cellBoundsX cellBoundsY);
            centerX += (cellBoundsWidth sizeWidth) / ;
            centerY += (cellBoundsHeight sizeHeight) / ;

  // Draw the disabled checkBox
            CheckBoxRendererDrawCheckBox(graphics center state);
        }
        else
        {
            // The checkBox cell is enabled so let the base class handle the painting
            basePaint(graphics clipBounds cellBounds rowIndex elementState value formattedValue errorText cellStyle advancedBorderStyle paintParts);
        }
    }
}

  public class DataGridViewDisableCheckBoxColumn : DataGridViewCheckBoxColumn
{
    public DataGridViewDisableCheckBoxColumn()
    {
        thisCellTemplate = new DataGridViewDisableCheckBoxCell();
    }
}
       主要是要實現DataGridViewDisableCheckBoxCell的呈現方式其中設置了CheckBoxState的狀態為MixedDisabled表示支持三種狀態這個是實現效果的核心如果要實現RadioButton列的效果只需要將Paint方法改成下面這樣即可

  protected override void Paint(Graphics graphics Rectangle clipBounds Rectangle cellBounds int rowIndex
DataGridViewElementStates elementState object value object formattedValue string errorText
DataGridViewCellStyle cellStyle DataGridViewAdvancedBorderStyle advancedBorderStyle DataGridViewPaintParts paintParts)
    {
        // Draw the cell background if specified
        if ((paintParts & DataGridViewPaintPartsBackground) == DataGridViewPaintPartsBackground)
        {
            SolidBrush cellBackground = new SolidBrush(cellStyleBackColor);
            graphicsFillRectangle(cellBackground cellBounds);
            cellBackgroundDispose();
        }

  // Draw the cell borders if specified
        if ((paintParts & DataGridViewPaintPartsBorder) == DataGridViewPaintPartsBorder)
        {
            PaintBorder(graphics clipBounds cellBounds cellStyle advancedBorderStyle);
        }

  // Calculate the area in which to draw the checkBox
        RadioButtonState state = value != null && (SelectedStatus)value == SelectedStatusSelected ? RadioButtonStateCheckedNormal : RadioButtonStateUncheckedNormal;
        Size size = RadioButtonRendererGetGlyphSize(graphics state);
        Point center = new Point(cellBoundsX cellBoundsY);
        centerX += (cellBoundsWidth sizeWidth) / ;
        centerY += (cellBoundsHeight sizeHeight) / ;

  // Draw the disabled checkBox
        RadioButtonRendererDrawRadioButton(graphics center state);
    }
      使用RadioButtonState代替CheckBoxState

  當然上面的代碼只是實現了列和單元格的顯示效果在使用過程中當用戶點擊單選或多選按鈕時如何改變狀態則需要自己手動編寫代碼來實現如在點擊單選按鈕時將DataGridView中其它行的單選按鈕設置為未選擇狀態點擊多選按鈕時在三種狀態之間轉換等

  首先我們需要手動修改Form的Designercs文件中的代碼將CheckBox所在的列的類型由DataGridViewCheckBoxColumn改成DataGridViewDisableCheckBoxColumn並設置ThreeState的值為true這個代碼是需要手動去修改的因為默認情況下VS不支持對自定義DataGridView列類型進行可視化編輯要支持CheckBox的三種狀態我們還需要定義一個枚舉來給CheckBox的TrueValueFalseValue和IndeterminateValue賦值這個枚舉很簡單有三個成員就夠了

  public enum SelectedStatus
{
    Selected
    NoSelected
    Indeterminate
}
      然後設置CheckBox的TrueValue=SelectedStatusSelectedFalseValue=SelectedStatusNoSelectedIndeterminateValue=SelectedStatusIndeterminate

  好了!這個時候運行程序可以看到經過我們改造的列已經可以正常顯示了但是有一個問題

  那就是當我們點擊其中的單選或多選按鈕時它的狀態並不能發生變化這是因為我們沒有在click事件中改變按鈕的選擇狀態要實現這個功能你需要給宿主DataGridView定義CellContentClick事件並且判斷當用戶點擊的是否為你所指定的控件然後進行相應的處理代碼如下

  private void dataGridView_CellContentClick(object sender DataGridViewCellEventArgs e)
{
    if (eRowIndex >= )
    {
        DataGridViewColumn column = dataGridViewColumns[eColumnIndex];

  if (column is DataGridViewCheckBoxColumn)
        {
            DataGridViewDisableCheckBoxCell cell = dataGridViewRows[eRowIndex]Cells[eColumnIndex] as DataGridViewDisableCheckBoxCell;
            if (!cellEnabled)
            {
                return;
            }
            if ((SelectedStatus)cellValue == SelectedStatusNoSelected)
            {
                cellValue = SelectedStatusSelected;
            }
            else if ((SelectedStatus)cellValue == SelectedStatusSelected)
            {
                cellValue = SelectedStatusIndeterminate;
            }
            else
            {
                cellValue = SelectedStatusNoSelected;
            }
        }
    }
}
       這個是CheckBox的如果是RadioButton的話你還需要控制其它RadionButton的狀態這個時候就沒有三種狀態而是兩種狀態了代碼可以修改成這樣

  private void dataGridView_CellContentClick(object sender DataGridViewCellEventArgs e)
{
    if (eRowIndex >= )
    {
        DataGridViewColumn column = dataGridViewColumns[eColumnIndex];

  if (column is DataGridViewCheckBoxColumn)
        {
            DataGridViewDisableCheckBoxCell cell = dataGridViewRows[eRowIndex]Cells[eColumnIndex] as DataGridViewDisableCheckBoxCell;
            if (!cellEnabled)
            {
                return;
            }
            if ((SelectedStatus)cellValue == SelectedStatusNoSelected)
            {
                cellValue = SelectedStatusSelected;
                SetRadioButtonValue(cell);
            }
            else
            {
                cellValue = SelectedStatusNoSelected;
            }
        }
    }
}

  private void SetRadioButtonValue(DataGridViewDisableCheckBoxCell cell)
{
    SelectedStatus status = (SelectedStatus)cellValue;
    if (status == SelectedStatusSelected)
    {
        status = SelectedStatusNoSelected;
    }
    else
    {
        status = SelectedStatusSelected;
    }
    for (int i = ; i < dataGridViewRowsCount; i++)
    {
        DataGridViewDisableCheckBoxCell cel = dataGridViewRows[i]Cells[checkbox] as DataGridViewDisableCheckBoxCell;
        if (!celEquals(cell))
        {
            celValue = status;
        }
    }
}
      函數SetRadionButtonValue負責修改宿主DataGridView當前列中其它的RadionButton的狀態

  在完成這些工作後一個相對完整的支持RadionButton或三種狀態的CheckBox列的DataGridView界面就完成了你可以根據需要在接下來的代碼中來判斷DataGridView中哪些行被選中了或者哪些行處於未確定的選擇狀態(CheckBox的第三種狀態)進而做出判斷來完成後面的工作

  最後我會提供整個工程供大家下載其中也給出了DataGridViewLinkColumn列中的一些效果如當鼠標指向超鏈接時顯示一個ToolTip當用戶點擊超鏈接時打開一個網頁等


From:http://tw.wingwit.com/Article/program/net/201311/11638.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.