Henry手记 - Datagrid键盘事件响应(一)
2024-07-21 02:16:34
供稿:网友
1. datagrid上的键盘响应
当datagrid与数据源绑定后,会呈现出如图1所示的形式。当datagrid被聚焦后,焦点会首先落在第一行第一列的单元格上(注意:不是单元格内),如图1-(3)所示。在该单元格上单击一下鼠标,会出现如图1-(4)所示的情况,焦点落入了单元格中。
图1 datagrid聚焦图
我们在本节中讨论的是图1-(1)及1-(2)所示的情况,即焦点是落在datagrid的框格上。一般的键盘事件响应是用keypress、keydown或keyup事件处理程序中的(键盘响应的顺序是keydown->keypress->keyup),我们也来如法炮制一下:
private sub datagrid1_keypress(byval sender as object, byval e as _
system.windows.forms.keypresseventargs) handles datagrid1.keypress
msgbox("你输入的是:" + e.keychar.tostring)
end sub
现在运行一下程序,当您点击键盘上的“0-1”“a-z”、“enter键”、“backspace键”等时,会弹出“你输入的是…”对话框,但是当你点击“ctrl键”“alt键”“shift键”时会毫无反应,点击方向键、tab键时,焦点会相应发生变动,而对话框却不会相应弹出。也就是说,keypress不能截得虚键,这是因为keychar表示的是ascii码表中有的键码。要截得虚键,我们用keydown来试试:
private sub datagrid1_keydown(byval sender as object, byval e as _
system.windows.forms.keyeventargs) handles datagrid1.keydown
msgbox("你输入的是:" + e.keycode.tostring)
end sub
搞定了,我们可以截得“ctrl键”“alt键”“shift键”了(组合键问题也就迎刃而解了,对吧?),等等,方向键、tab键、pgup、pgdown为什么还不理我们?看来是datagrid控件把它们藏起来了,怎么处理?后面再来说吧。
现在请关注这样一个需求,我们不是已经可以截得“enter键”了吗?我想在用户键入enter时,响应tab键的事件处理程序。来吧,用keydown试试(keypress也行):
private sub datagrid1_keydown(byval sender as object, byval e as _
system.windows.forms.keyeventargs) handles datagrid1.keydown
if e.keycode = keys.enter then
sendkeys.send("{tab}") ‘通知系统调用tab键的事件处理程序
end if
end sub
运行一下程序,我们将焦点落在图1-(1)的位置,敲下enter键,怎么样?果然程序把enter键当成了tab键来执行了,焦点落入到第一行的第二列那个单元格上了!
那我再敲enter键,咦,焦点怎么不跳动了?呵呵,当然不会动了,因为现在焦点已经被单元格获取了。
2. datagrid单元格上的键盘响应
单元格上的键盘响应主要是针对能显示的字符输入(这也是单元格的主要作用嘛!),当然还有backspace/delete/home/end这样的功能键。那么怎样来截得键盘信息呢?事件的对象现在是单元格了,可是我们在vs.net的代码编辑器的“类名”下拉框中却看不到可以用的类,是什么东东的keydown/keypress/keyup事件呢?
如果您看过我写的datagrid结构剖析系列文章,您应该会很清楚,单元格的直接领导就是“列”了。所以我们应该在列上动动脑筋。让列来承接这项任务。我们来完成的需求是:实现单元格的数值框功能,就是只能在单元格中输入数字0-9,以及小数点“.”与回退键(backspace键),form_load中的代码的参数声明见datagrid结构剖析(一):
dim ts as new datagridtablestyle()
dim acolumntextcolumn as datagridtextboxcolumn
datagrid1.datasource = dt
ts.mappingname = dt.tablename
dim numcols as integer
numcols = dt.columns.count
dim i as integer = 0
do while (i < numcols) '重绘所有的列
acolumntextcolumn = new datagridtextboxcolumn()
addhandler acolumntextcolumn.textbox.keypress, new keypresseventhandler(addressof column_keypress)
'让列中的单元格来响应keypress事件
acolumntextcolumn.headertext = dt.columns(i).columnname
acolumntextcolumn.mappingname = dt.columns(i).columnname
ts.gridcolumnstyles.add(acolumntextcolumn) '增加一种自定义的column风格
i = (i + 1)
loop
datagrid1.tablestyles.add(ts) '增加一种自定义的表风格
……
‘事件处理程序,同样适用于其它textbox用于数值框处理的情况。
private sub column_keypress(byval sender as object, _
byval e as system.windows.forms.keypresseventargs)
msgbox("you have pressed the " & e.keychar)
if not (isnumeric(e.keychar) or e.keychar = chrw(8) or e.keychar = chrw(46)) then
e.handled = true
end if
运行一下程序,您还能在单元格中输入“a-z”这样的字符吗?
当然还可以利用赋值方法来实现:
在类中先声明(原因请参见拙作《windows 窗体引介(二) 》):
friend withevents column1 as textbox
friend withevents column2 as textbox
然后在form_load中编写代码如下(同样见datagrid结构剖析(一)的参数声明):
dim mygridtablestyle as datagridtablestyle = new datagridtablestyle()
mygridtablestyle.mappingname = dt.tablename
datagrid1.tablestyles.add(mygridtablestyle)
dim tempcolumn as datagridtextboxcolumn
tempcolumn = datagrid1.tablestyles(0).gridcolumnstyles(0)
column1 = tempcolumn.textbox
tempcolumn = datagrid1.tablestyles(0).gridcolumnstyles(1)
事件处理程序:
private sub column1_keypress(byval sender as object, _
byval e as system.windows.forms.keypresseventargs) _
handles column1.keypress
if not (isnumeric(e.keychar) or e.keychar = chrw(8) or e.keychar = chrw(46)) then
e.handled = true
end if
end sub
private sub column2_keydown(byval sender as object, _
byval e as system.windows.forms.keyeventargs) _
handles column2.keydown
msgbox("you have pressed the " & e.keycode)
end sub
运行一下程序,你会发现第一列已经实现了数值框功能,第二列会在接受键盘请求后报告用户按下的是什么键。这么一处理,我们可以轻松地针对各列的单元格进行我们想要的处理了(不管是keypress,keydown,还是其它textbox能响应的事件,我们都可以来处理了!怎一个爽字了得!)
继续第一节提出的问题,我们在单元格获得响应时来按下“enter键”发现会有两种情况:(1)当单元格的内容没有任何变化时,按下此键没有任何响应;(2)当单元格的内容发生变动后,按下此键,焦点会落入下一行同一列的那个单元格里去了。
我们在上述的事件处理程序中来截取“enter键”,完了,却截不到了,不论是keypress还是keydown!那些第一节中就束手无策的虚键:方向键、tab键、pgup/pgdn,当然仍然截不到。怎么办?它们藏到哪去了?下次再讨论吧,敬请继续关注!