C# WinForm下DataGridView单元按钮列
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# WinForm下DataGridView单元按钮列相关的知识,希望对你有一定的参考价值。
参考技术A在C# WinForm下做过项目的朋友都知道 其中的DataGridView控件默认只支持DataGridViewButtonColumn DataGridViewCheckBoxColumn DataGridViewComboBoxColumn DataGridViewImageColumn DataGridViewLinkColumn和DataGridViewTextBoxColumn六种列类型 如果你想要在DataGridView的列中添加其它的子控件 则需要自己实现DataGridViewColumn和DataGridViewCell 这就意味着你需要从现有的列中继承并改写一些方法 如实现一个支持单选按钮的列 或支持三种选择状态的多选按钮的列
上面两个截图分别为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)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) / ; center Y += (cellBounds Height size Height) / ;
// 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) / ; center Y += (cellBounds Height size Height) / ;
// 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 dataGridView _CellContentClick(object sender DataGridViewCellEventArgs e) if (e RowIndex >= ) DataGridViewColumn column = dataGridView Columns[e ColumnIndex];
if (column is DataGridViewCheckBoxColumn) DataGridViewDisableCheckBoxCell cell = dataGridView 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 dataGridView _CellContentClick(object sender DataGridViewCellEventArgs e) if (e RowIndex >= ) DataGridViewColumn column = dataGridView Columns[e ColumnIndex];
if (column is DataGridViewCheckBoxColumn) DataGridViewDisableCheckBoxCell cell = dataGridView 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 = ; i < dataGridView Rows Count; i++) DataGridViewDisableCheckBoxCell cel = dataGridView Rows[i] Cells[ checkbox ] as DataGridViewDisableCheckBoxCell; if (!cel Equals(cell)) cel Value = status; 函数SetRadionButtonValue负责修改宿主DataGridView当前列中其它的RadionButton的状态
在完成这些工作后 一个相对完整的支持RadionButton或三种状态的CheckBox列的DataGridView界面就完成了 你可以根据需要在接下来的代码中来判断DataGridView中哪些行被选中了 或者哪些行处于未确定的选择状态(CheckBox的第三种状态) 进而做出判断来完成后面的工作
lishixinzhi/Article/program/net/201311/11638
以上是关于C# WinForm下DataGridView单元按钮列的主要内容,如果未能解决你的问题,请参考以下文章
C# datagridview 单元格内值改变时触发了哪些事件?(winform)
c# winform datagridview第一行单元格不能调整高度~~
C# winform控件DataGridView中动态改变其中某列的值后,发现那列单元格文字会闪烁,不知是啥原因?