C# WinForm下DataGridView单选按钮列和支持三种选择状态的复选框列的实现

简介:
 在C# WinForm下做过项目的朋友都知道,其中的DataGridView控件默认只支持DataGridViewButtonColumn、DataGridViewCheckBoxColumn、DataGridViewComboBoxColumn、DataGridViewImageColumn、DataGridViewLinkColumn和DataGridViewTextBoxColumn六种列类型,如果你想要在DataGridView的列中添加其它的子控件,则需要自己实现DataGridViewColumn和DataGridViewCell,这就意味着你需要从现有的列中继承并改写一些方法,如实现一个支持单选按钮的列,或支持三种选择状态的多选按钮的列。

6-22-2009 3-32-18 PM

6-22-2009 3-31-44 PM

      上面两个截图分别为RadioButton列和支持三种状态的CheckBox列在DataGridView中的实现效果,我是在Windows 2003中实现的,因此显示的效果跟在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) base .Clone();
        cell.Enabled 
=   this .Enabled;
        
return  cell;
    }

    
//  By default, enable the CheckBox cell.
     public  DataGridViewDisableCheckBoxCell()
    {
        
this .Enabled  =   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  ( ! this .Enabled)
        {
            
//  Draw the cell background, if specified.
             if  ((paintParts  &  DataGridViewPaintParts.Background)  ==  DataGridViewPaintParts.Background)
            {
                SolidBrush cellBackground 
=   new  SolidBrush(cellStyle.BackColor);
                graphics.FillRectangle(cellBackground, cellBounds);
                cellBackground.Dispose();
            }

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

            
//  Calculate the area in which to draw the checkBox.
            CheckBoxState state  =  CheckBoxState.MixedDisabled;
            Size size 
=  CheckBoxRenderer.GetGlyphSize(graphics, state);
            Point center 
=   new  Point(cellBounds.X, cellBounds.Y);
            center.X 
+=  (cellBounds.Width  -  size.Width)  /   2 ;
            center.Y 
+=  (cellBounds.Height  -  size.Height)  /   2 ;

            
//  Draw the disabled checkBox.
            CheckBoxRenderer.DrawCheckBox(graphics, center, state);
        }
        
else
        {
            
//  The checkBox cell is enabled, so let the base class, handle the painting.
             base .Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        }
    }
}
复制代码


复制代码
public   class  DataGridViewDisableCheckBoxColumn : DataGridViewCheckBoxColumn
{
    
public  DataGridViewDisableCheckBoxColumn()
    {
        
this .CellTemplate  =   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  &  DataGridViewPaintParts.Background)  ==  DataGridViewPaintParts.Background)
        {
            SolidBrush cellBackground 
=   new  SolidBrush(cellStyle.BackColor);
            graphics.FillRectangle(cellBackground, cellBounds);
            cellBackground.Dispose();
        }

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

        
//  Calculate the area in which to draw the checkBox.
        RadioButtonState state  =  value  !=   null   &&  (SelectedStatus)value  ==  SelectedStatus.Selected  ?  RadioButtonState.CheckedNormal : RadioButtonState.UncheckedNormal;
        Size size 
=  RadioButtonRenderer.GetGlyphSize(graphics, state);
        Point center 
=   new  Point(cellBounds.X, cellBounds.Y);
        center.X 
+=  (cellBounds.Width  -  size.Width)  /   2 ;
        center.Y 
+=  (cellBounds.Height  -  size.Height)  /   2 ;

        
//  Draw the disabled checkBox.
        RadioButtonRenderer.DrawRadioButton(graphics, center, state);
    }
复制代码

      使用RadioButtonState代替CheckBoxState。

      当然,上面的代码只是实现了列和单元格的显示效果,在使用过程中当用户点击单选或多选按钮时如何改变状态则需要自己手动编写代码来实现,如在点击单选按钮时将DataGridView中其它行的单选按钮设置为未选择状态,点击多选按钮时在三种状态之间转换等。

      首先我们需要手动修改Form的Designer.cs文件中的代码,将CheckBox所在的列的类型由DataGridViewCheckBoxColumn改成DataGridViewDisableCheckBoxColumn,并设置ThreeState的值为true,这个代码是需要手动去修改的,因为默认情况下VS不支持对自定义DataGridView列类型进行可视化编辑。要支持CheckBox的三种状态,我们还需要定义一个枚举来给CheckBox的TrueValue、FalseValue和IndeterminateValue赋值。这个枚举很简单,有三个成员就够了。

复制代码
public   enum  SelectedStatus

    Selected, 
    NoSelected, 
    Indeterminate
}
复制代码

      然后设置CheckBox的TrueValue=SelectedStatus.Selected,FalseValue=SelectedStatus.NoSelected,IndeterminateValue=SelectedStatus.Indeterminate。

      好了!这个时候运行程序,可以看到经过我们改造的列已经可以正常显示了,但是有一个问题,那就是当我们点击其中的单选或多选按钮时它的状态并不能发生变化,这是因为我们没有在click事件中改变按钮的选择状态。要实现这个功能,你需要给宿主DataGridView定义CellContentClick事件,并且判断当用户点击的是否为你所指定的控件,然后进行相应的处理。代码如下:

复制代码
private   void  dataGridView1_CellContentClick( object  sender, DataGridViewCellEventArgs e)
{
    
if  (e.RowIndex  >=   0 )
    {
        DataGridViewColumn column 
=  dataGridView1.Columns[e.ColumnIndex];

        
if  (column  is  DataGridViewCheckBoxColumn)
        {
            DataGridViewDisableCheckBoxCell cell 
=  dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]  as  DataGridViewDisableCheckBoxCell;
            
if  ( ! cell.Enabled)
            {
                
return ;
            }
            
if  ((SelectedStatus)cell.Value  ==  SelectedStatus.NoSelected)
            {
                cell.Value 
=  SelectedStatus.Selected;
            }
            
else   if  ((SelectedStatus)cell.Value  ==  SelectedStatus.Selected)
            {
                cell.Value 
=  SelectedStatus.Indeterminate;
            }
            
else
            {
                cell.Value 
=  SelectedStatus.NoSelected;
            }
        }
    }
}
复制代码
       这个是CheckBox的,如果是RadioButton的话你还需要控制其它RadionButton的状态,这个时候就没有三种状态而是两种状态了,代码可以修改成这样:
复制代码
private   void  dataGridView1_CellContentClick( object  sender, DataGridViewCellEventArgs e)
{
    
if  (e.RowIndex  >=   0 )
    {
        DataGridViewColumn column 
=  dataGridView1.Columns[e.ColumnIndex];

        
if  (column  is  DataGridViewCheckBoxColumn)
        {
            DataGridViewDisableCheckBoxCell cell 
=  dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]  as  DataGridViewDisableCheckBoxCell;
            
if  ( ! cell.Enabled)
            {
                
return ;
            }
            
if  ((SelectedStatus)cell.Value  ==  SelectedStatus.NoSelected)
            {
                cell.Value 
=  SelectedStatus.Selected;
                SetRadioButtonValue(cell);
            }
            
else
            {
                cell.Value 
=  SelectedStatus.NoSelected;
            }
        }
    }
}

private   void  SetRadioButtonValue(DataGridViewDisableCheckBoxCell cell)
{
    SelectedStatus status 
=  (SelectedStatus)cell.Value;
    
if  (status  ==  SelectedStatus.Selected)
    {
        status 
=  SelectedStatus.NoSelected;
    }
    
else
    {
        status 
=  SelectedStatus.Selected;
    }
    
for  ( int  i  =   0 ; i  <  dataGridView1.Rows.Count; i ++ )
    {
        DataGridViewDisableCheckBoxCell cel 
=  dataGridView1.Rows[i].Cells[ " checkbox " as  DataGridViewDisableCheckBoxCell;
        
if  ( ! cel.Equals(cell))
        {
            cel.Value 
=  status;
        }
    }
}
复制代码

      函数SetRadionButtonValue负责修改宿主DataGridView当前列中其它的RadionButton的状态。

      在完成这些工作后,一个相对完整的支持RadionButton或三种状态的CheckBox列的DataGridView界面就完成了,你可以根据需要在接下来的代码中来判断DataGridView中哪些行被选中了,或者哪些行处于未确定的选择状态(CheckBox的第三种状态),进而做出判断来完成后面的工作。

      最后我会提供整个工程供大家下载,其中也给出了DataGridViewLinkColumn列中的一些效果,如当鼠标指向超链接时显示一个ToolTip,当用户点击超链接时打开一个网页等。

ThreeStatusCheckBoxDataGridColumn.rar


本文转自Jaxu博客园博客,原文链接:http://www.cnblogs.com/jaxu/archive/2009/06/22/1508380.html,如需转载请自行联系原作者


相关文章
|
2月前
|
SQL 数据库连接 应用服务中间件
C#WinForm基础编程(三)
C#WinForm基础编程
76 0
|
2月前
C#WinForm基础编程(二)
C#WinForm基础编程
57 0
|
2月前
|
C# 数据安全/隐私保护
C#WinForm基础编程(一)
C#WinForm基础编程
60 0
|
4月前
|
小程序 C#
C#WinForm实现Loading等待界面
上篇博客中解决了程序加载时屏幕闪烁的问题。 但是,加载的过程变得很缓慢。 这个给用户的体验也不是很好,我这里想加一个Loading的进度条。 项目启动的时候,加载进度条,界面UI加载完毕,进度条消失。
124 0
|
6月前
|
关系型数据库 MySQL C#
C# winform 一个窗体需要调用自定义用户控件的控件名称
给用户控件ucQRCode增加属性: //二维码图片 private PictureBox _pictureBoxFSHLQrCode; public PictureBox PictureBoxFSHLQrCode {   get { return _pictureBoxFSHLQrCode; }   set { this.pictureBoxFSHLQrCode = value; } } 在Form1窗体直接调用即可: ucQRCode uQRCode=new ucQRCode(); ucQRCode.PictureBoxFSHLQrCode.属性= 要复制或传给用户控件上的控件的值
36 0
|
1月前
|
存储 缓存 C#
46.c#:datagridview控件
46.c#:datagridview控件
20 1
|
1月前
|
C# 开发者
35.c#:winform窗口
35.c#:winform窗口
12 1
|
2月前
|
C#
C# Winform 选择文件夹和选择文件
C# Winform 选择文件夹和选择文件
44 0
|
4月前
|
SQL 数据库连接 数据库
C# | 将DataGridView中的数据保存到Accesss数据库
要将WinForm的DataGridView中的数据保存到Access数据库,可以按照本文的步骤进行。 在Visual Studio中,打开项目,右键单击“引用”文件夹,选择“添加引用”,在“COM”选项卡中找到并选中“Microsoft Office 14.0 Access Database Engine Object Library”,然后单击“确定”按钮。
89 0
C# | 将DataGridView中的数据保存到Accesss数据库
|
4月前
|
XML 存储 JSON
C# | DataGridView数据转存为Json、XML格式
DataGridView是常用的数据展示组件,而将其转存为Json或XML格式,则可以方便地进行数据的传输和存储。 Json格式具有轻量、易读、易解析等优点,广泛应用于Web开发、API接口传输等场景。 XML格式则具有良好的结构化特性,支持命名空间、数据类型等复杂数据表示方式,被广泛应用于数据交换、配置文件等领域。 因此,将DataGridView数据转存为Json、XML格式,不仅能够方便地进行数据的传输和存储,还能够满足不同场景下的数据需求。 本篇文章将介绍如何将DataGridView数据转存为Json、XML格式,并提供相应的代码示例。
98 0
C# | DataGridView数据转存为Json、XML格式