版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的
20.3.11 实现文本单元格中显示下拉框并设置值
在实际工作中,为了防止用户乱填写数据,开发者往往需要给出固定的几个值,用户只能在那几个值里面选择,在DataGridView中可以通过设置DataGridViewComboBoxCell来实现,但是一列的下拉框单元格,没有文本单元格视觉效果那么好,造成用户体验并不是很好。在本节将实现当点击文本单元格开始编辑时,就出现下拉框,编辑完成后又恢复为文本单元格。
第一种方法,直接在点击DataGridViewTextBoxCell的单元格时,将其替换为DataGridViewComboBoxCell,选定值后再换回来。
【例 20.20】【项目:code20-020】文本单元格显示下拉框并设置值。
private void Form1_Load(object sender, EventArgs e)
{
//增加对单元格的值发生改变时的处理
dgv.CellValueChanged += dgv_CellValueChanged;
}
//当单元格被点击时
private void dgv_CellClick(object sender, DataGridViewCellEventArgs e)
{
//获得点击单元格的列索引和行索引
int cellrowindex, cellcolindex;
cellcolindex = e.ColumnIndex;
cellrowindex = e.RowIndex;
//当点击第2列(索引1)的单元格时显示ComboBox
if (cellcolindex != 1)
return;
//获得当前单元格的值
string cellvalue = (string)dgv[cellcolindex, cellrowindex].Value;
DataGridViewComboBoxCell dcb = new DataGridViewComboBoxCell();
//向DataGridViewComboBoxCell下拉列表中填入数据
dcb.Items.Add("第1中学");
dcb.Items.Add("第2中学");
dcb.Items.Add("第3中学");
//设置值为原单元格的值
dcb.Value = cellvalue;
//将单元格设置为DataGridViewComboBoxCell
dgv[cellcolindex, cellrowindex] = dcb;
}
//当单元格的值发生改变时
private void dgv_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
//获得单元格的列索引和行索引
int cellrowindex, cellcolindex;
cellcolindex = e.ColumnIndex;
cellrowindex = e.RowIndex;
//获得当前单元格的值
string cellvalue = (string)dgv[cellcolindex, cellrowindex].Value;
DataGridViewTextBoxCell dt = new DataGridViewTextBoxCell();
dt.Value = cellvalue;
//将单元格设置为DataGridViewTextBoxCell
dgv[cellcolindex, cellrowindex] = dt;
}
运行结果如下图所示:
图20-25 下拉框单元格与文本单元格交换
如图20-25,这一种方法在单元格焦点未失去时,将一直显示为下拉框单元格。因为DataGridViewComboBoxCell没有提供类似ComboBox.SelectedIndexChanged事件,无法捕获到下拉框索引改变这个事件。
第二种方法,首先明确几个概念:
1、DataGridView控件可以包含子控件,通过DataGridView.Controls 属性访问即可,这样就可以将ComboBox控件包含进去,当然其它控件也可以。
2、当ComboBox加入后,需要确定它的大小和位置,需要调用DataGridView的GetCellDisplayRectangle方法,具体语法:
public Rectangle GetCellDisplayRectangle( int columnIndex, int rowIndex, bool cutOverflow )
参数说明:
- columnIndex:单元格的列索引。
- rowIndex:单元格的行索引。
- cutOverflow:如果只返回该单元格的显示部分,则为true;如果返回整个单元格界限,则为false。
返回值:
- 表示单元格显示区域的矩形,也就获得了该区域的位置和尺寸。这是一个Rectangle对象。
当获得Rectangle对象后,设置ComboBox的大小和位置与它相同就可以了。
3、当点击指定的单元格(CellClick)时或者单元格获得焦点(CellEnter)时,设置显示ComboBox。
4、当从ComboBox选择了值,将值写回单元格。就可以使ComboBox隐藏起来。
以上操作中可能遇到的几个问题:
1、单元格获得了值,但不会像正常情况下选择了值或者输入了值,DataGridView的最下面就会出来新的一行,而要在其他列输入数据后才会出来新行。这也是很多代码没有解决的问题。这个问题可以使用DataGridView的NotifyCurrentCellDirty方法来通知做了修改。在笔者实际测试时发现有时候一次通知不行,最好是调用此方法两次。
2、当点击某个单元格ComboBox显示出来后,点击其它不应显示ComboBox的单元格时,ComboBox仍然还在原单元格。这个问题只需要点击单元格时先将ComboBox隐藏即可。
3、当点击某个单元格ComboBox显示出来后,也可以输入数据,而不是期望的从ComboBox中的数据。这个问题只需要设置该单元格只读(ReadOnly=true)即可。
【例 20.21】【项目:code20-021】文本单元格显示下拉框并设置值。
//声明一个窗体级的ComboBox变量cb
ComboBox cb;
//声明两个Integer保存点击的行列的索引
int cellrowindex, cellcolindex;
//当窗体载入后, 将固定的值增加到cb中,
private void Form1_Load(object sender, EventArgs e)
{
//实例化ComboBox,填入数据
cb = new ComboBox();
cb.Items.Add("第1中学");
cb.Items.Add("第2中学");
cb.Items.Add("第3中学");
//限制用户输入,使用DropDownList
cb.DropDownStyle = ComboBoxStyle.DropDownList;
//不显示
cb.Visible = false;
//增加到DataGridView所属控件中
dgv.Controls.Add(cb);
//同时增加ComboBox的索引改变事件(SelectedIndexChanged)
cb.SelectedIndexChanged += cbChanged;
}
//添加ComboBox的SelectedIndexChanged事件具体代码
private void cbChanged(object sender, EventArgs e)
{
//将选好值后将值传给对应的单元格
dgv[cellcolindex, cellrowindex].Value = cb.Text;
//隐藏ComboBox
cb.Visible = false;
//当单元格写入数据后通知DataGridView做了修改
dgv.NotifyCurrentCellDirty(true);
//实测需要两次通知, 一次有时候不行
dgv.NotifyCurrentCellDirty(false);
}
private void dgv_CellClick(object sender, DataGridViewCellEventArgs e)
{
//获得点击单元格的列索引和行索引
cellcolindex = e.ColumnIndex;
cellrowindex = e.RowIndex;
//先使ComboBox隐藏
cb.Visible = false;
//当点击第2列(索引1)的单元格时显示ComboBox
if (cellcolindex != 1)
return;
//设置单元格只读,不允许用户绕过ComboBox手动输入修改
dgv[cellcolindex, cellrowindex].ReadOnly = true;
//获得当前单元格的值
string cellvalue = (string)dgv[cellcolindex, cellrowindex].Value;
//获得单元格的大小和位置。
Rectangle rect;
rect = dgv.GetCellDisplayRectangle(cellcolindex, cellrowindex, true);
//设置ComboBox的大小位置与单元格相同
cb.Top = rect.Top;
cb.Left = rect.Left;
cb.Width = rect.Width;
cb.Height = rect.Height;
//为了限制用户输入,设置ComboBox的文本为第一个值
cb.Text = cellvalue;
//显示ComboBox
cb.Visible = true;
}
运行结果如下图所示:
图20-26 从ComboBox中选择值填入单元格
学习更多vb.net知识,请参看vb.net 教程 目录
学习更多C#知识,请参看C#教程 目录