但是事后我看了看 CellSelectionModel 和 RowSelectionModel的源代码,发现单元格多选并不难,于是先没和项目经理说我的想法,而是抽时间没事研究了一下,终于搞了几天之后,初版的模型就出来,嘿嘿现在尝试着说服项目经理应用在系统中。OK,先上代码和理论知识吧:
先说说Ext GridPanel UI组件的结构,它由五个部分组成,GridView、ColumnModel、SelectionModel、Store、GridPanel,不得不佩服Ext团队的设计理念,这是一个典型的MVC结构组件。GridView负责管理表格的内容展示,ColumnModel负责列的定义,SelectionModel是选择模组,Store是数据层,最后它们全部组合在一起由GridPanel进行渲染,展现在我们的面前。因为只关注单元格多选,对我们有用的组件只有Gridview 和 SelecitonModel。
Grid选择模型的实现原理是这样的:Ext组件关系非常复杂,这里用图表进行说明吧

左侧是加载初始化时的操作,右侧是触发事件时的操作。
现在我们自定义的SelectionModel 主要关注于handleMouseDown方法就行。我们的多选规则和Excel一样,按住shift这是区域全选,按住ctrl则是添加被选中的单元格
Ext.hl.MultiCellSelectionModel = Ext.extend(Ext.grid.CellSelectionModel, {
last : false , // 上一次选中的单元格
selections : [], // 选择区缓存
constructor : function () {
Ext.hl.MultiCellSelectionModel.superclass.constructor.call( this );
},
initEvents : function () {
Ext.hl.MultiCellSelectionModel.superclass.initEvents.call( this );
},
// 根据行列以及是否按住Ctrl键或者shift键,执行多选操作的逻辑
handleMouseDown : function (grid, row, col, event) {
var isSelected;
if (event.button !== 0 || this .isLocked())
return ;
if (event.shiftKey && this .last !== false ) { //是否按下shift
this .selectMatrix(row, col);
grid.getView().focusCell(row, col);
return ;
} else if (event.ctrlKey){ //是否按下ctrl
isSelected = this .isSelected(row,col);
if (col === 0 && this .last[ 1 ] === 0 ){
isSelected this .deselectRow(row) : this .selectRow(row, true );
}
if (isSelected){ // 是否已被选中,是则反选,否则选中
this .deselectCell(row, col);
} else {
this .selectCell(row,col, true );
this .last = [row, col];
}
} else if (col === 0 ){ // 第一列是NumberColumn 点击则选择列
this .selectRow(row);
this .last = [row, col];
} else { // 选择单个单元格
this .selectCell(row,col);
this .last = [row, col];
}
if ( this .matrix)
delete this .matrix;
},
// 清楚选择区内所以单元格被选中的样式
clearCellSelections : function (){
var l