首先要声明,下面的代码在传说中的弦哥(http://www.cnblogs.com/legendxian/)的Asp.Net大型项目实践系列的代码基础上修改而成。弦哥同学的这个系列是个非常好的实例,对ExtJS,MVC和NHb感兴趣的可以去看看,可以学到不少东西。由于作为示例非常合适,所以以此引申开来。代码中,其中的界面js有一点小遗憾,就是没有完全用Ext的方式来写,譬如:

 

部门管理代码
function Infra_Department() {
    
    
// 表格Store
    var gridStore = new Ext.data.Store({
                url : 
"/InfraDepartment/GetPlist",
                remoteSort : 
true,
                reader : 
new Ext.data.JsonReader({
                            root : 
'data',
                            totalProperty : 
'total',
                            id : 
'Id'
                        }, [{
                                    name : 
'Id',
                                    type : 
'string'
                                }, {
                                    name : 
'CreateTime',
                                    type : 
'date'
                                }, {
                                    name : 
'Name',
                                    type : 
'string'
                                }, {
                                    name : 
'Code',
                                    type : 
'string'
                                }, {
                                    name : 
'InputCode1',
                                    type : 
'string'
                                }, {
                                    name : 
'InputCode2',
                                    type : 
'string'
                                }, {
                                    name : 
'InputCode3',
                                    type : 
'string'
                                }, {
                                    name : 
'Description',
                                    type : 
'string'
                                }]),
                listeners : {
                    
'update' : function(thiz, record, operation) {
                        
var model = record.data;
                        
if (operation == Ext.data.Record.EDIT
                                
&& !record.getChanges().Id) {
                            Ext.Ajax.request({
                                        url : 
'/InfraDepartment/SaveOrUpdate',
                                        params : model,
                                        success : 
function(response, opts) {
                                            
var result = Ext.util.JSON
                                                    .decode(response.responseText);
                                            
if (result.success) {
                                                
if (!record.get('Id'))
                                                    record.set(
'Id', result.id);
                                                thiz.commitChanges();
                                            } 
else {
                                                JsHelper.ShowError(result.msg);
                                                thiz.rejectChanges();
                                            }
                                        }
                                    });
                        }
                    }
                }
            });
    gridStore.setDefaultSort(
'CreateTime''DESC');

    
// 定义Editor
    var gridEditor = new Ext.ux.grid.RowEditor();
    
// 定义filters
    var filters = new Ext.ux.grid.GridFilters({
                encode : 
true,
                filters : [{
                            type : 
'string',
                            dataIndex : 
'Name'
                        }, {
                            type : 
'string',
                            dataIndex : 
'Code'
                        }]
            });
    
// 定义表格列
    var sm = new Ext.grid.CheckboxSelectionModel();
    
var cm = new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(), sm, {
                header : 
"科室名称",
                dataIndex : 
'Name',
                sortable : 
true,
                updateEdit : 
false,
                editor : {
                    xtype : 
'textfield',
                    allowBlank : 
false,
                    name : 
'Name',
                    plugins : [Ext.ux.plugins.RemoteValidator],
                    rvOptions : {
                        url : 
'/InfraDepartment/IsFieldExist',
                        params : {
                            
'FieldName' : 'Name',
                            
'Id' : "-1"
                        }
                    }
                }
            }, {
                header : 
"代码",
                dataIndex : 
'Code',
                sortable : 
true,
                updateEdit : 
false,
                width : 
60,
                editor : {
                    xtype : 
'textfield',
                    allowBlank : 
false,
                    name : 
'Code',
                    plugins : [Ext.ux.plugins.RemoteValidator],
                    rvOptions : {
                        url : 
'/InfraDepartment/IsFieldExist',
                        params : {
                            
'FieldName' : 'Code',
                            
'Id' : "-1"
                        }
                    }
                }
            }, {
                header : 
"描述",
                dataIndex : 
'Description',
                sortable : 
true,
                editor : {
                    xtype : 
'textfield'
                }
            }, {
                header : 
"助记码1",
                dataIndex : 
'InputCode1',
                sortable : 
true,
                width : 
70,
                editor : {
                    xtype : 
'textfield'
                }
            }, {
                header : 
"助记码2",
                dataIndex : 
'InputCode2',
                sortable : 
true,
                width : 
70,
                editor : {
                    xtype : 
'textfield'
                }
            }, {
                header : 
"助记码3",
                dataIndex : 
'InputCode3',
                sortable : 
true,
                width : 
70,
                editor : {
                    xtype : 
'textfield'
                }
            }, {
                xtype : 
'datecolumn',
                format : 
'Y年m月d日 H:i:s',
                header : 
"创建时间",
                width : 
150,
                dataIndex : 
'CreateTime',
                sortable : 
true
            }]);
    
// 定义表格工具栏
    var tbar = new Ext.Toolbar({
        items : [{
                    xtype : 
"tbbutton",
                    minWidth : 
80,
                    ref : 
'../addBtn',
                    text : 
"添加项",
                    cls : 
"x-btn-text-icon",
                    icon : 
"/Content/icons/add.png",
                    handler : 
function(btn, e) {
                        gridEditor.stopEditing();
                        gridStore.insert(
0new gridStore.recordType);
                        grid.getView().refresh();
                        grid.getSelectionModel().selectRow(
0);
                        gridEditor.startEditing(
0);
                    }
                }, 
"-", {
                    xtype : 
"tbbutton",
                    ref : 
'../delBtn',
                    minWidth : 
80,
                    disabled : 
true,
                    text : 
"删除项",
                    cls : 
"x-btn-text-icon",
                    icon : 
"/Content/icons/delete.png",
                    handler : 
function(btn, e) {
                        JsHelper.DelConfirm(
function(btn) {
                            
if (btn == 'yes') {
                                
var records = grid.getSelectionModel()
                                        .getSelections();
                                
for (var i = 0; i < records.length; i++) {
                                    Ext.Ajax.request({
                                        url : 
'/InfraDepartment/Delete',
                                        params : {
                                            
'Id' : records[i].get("Id")
                                        },
                                        success : 
function(response, opts) {
                                            
var result = Ext.util.JSON
                                                    .decode(response.responseText);
                                            
if (result.success == false) {
                                                JsHelper.ShowError(result.msg);
                                            } 
else {
                                                
var paramsId = opts.params.Id;
                                                
var r = gridStore
                                                        .getAt(gridStore.find(
                                                                
"Id", paramsId));
                                                
if (Ext.isDefined(r)) {
                                                    gridStore.remove(r);
                                                }
                                            }
                                        }
                                    });

                                }
                            }
                        });
                    }
                }, 
"-", {
                    xtype : 
"tbbutton",
                    minWidth : 
80,
                    text : 
"双击修改项",
                    cls : 
"x-btn-text-icon",
                    icon : 
"/Content/icons/pencil.png",
                    disabled : 
true
                }]
    });
    
// 分页工具栏
    var bbar = new Ext.PagingToolbar({
                displayInfo : 
true,
                emptyMsg : 
"没有数据显示",
                displayMsg : 
"显示从{0}条数据到{1}条数据,共{2}条数据",
                store : gridStore,
                pageSize : ALL_PAGESIZE_SETTING,
                plugins : [filters]
            })
    
// 定义表格
    var grid = new Ext.grid.GridPanel({
                sm : sm,
                cm : cm,
                enableColumnMove : 
false,
                plugins : [gridEditor, filters],
                stripeRows : 
true,
                frame : 
true,
                border : 
true,
                layout : 
"fit",
                store : gridStore,
                loadMask : 
true,
                tbar : tbar,
                bbar : bbar
            });
    grid.getSelectionModel().on(
'selectionchange'function(sm) {
                grid.delBtn.setDisabled(sm.getCount() 
< 1);
            });
    JsHelper.ExtTabDoLayout(grid);
    
// 注意 在ExtTabDoLayout之后Load
    gridStore.load({
                params : {
                    start : 
0,
                    limit : ALL_PAGESIZE_SETTING
                }
            });
}

Infra_Department();

 

 

由于不是OO的方式,看起来比较乱,这个尚在其次,最大的问题是当需要重用时,譬如有一个页面,左边是一个人员的Panel,右边是人员所属部门的grid的Panel,右边的内容根据左边的人员选择切换----如果发生了这样的需求,那代码要在这个新的页面中重写。所以也许比较好的方式是写一个继承自GridPanel的类。可以这样(这里是一个我当前项目的例子代码,本质上是一样的):

代码
Ext.ns('YC''YC.TeacherRankDef');

YC.TeacherRankDef.Grid 
= Ext.extend(Ext.grid.GridPanel, {
    enableColumnMove : 
true,
    stripeRows : 
true,
    frame : 
true,
    border: 
true,
    layout : 
"fit",
    loadMask : 
true,

    initComponent: 
function() {
        
this.viewConfig = {
            
//            forceFit : true
        };

        
this.store = this.buildStores()[0];

        
this.tbar = this.buildTopToolbar();
        
this.bbar = this.buildBottomToolbar();
        
this.sm = new Ext.grid.CheckboxSelectionModel();
        
this.cm = this.buildCm();
        
this.on("rowdblclick"this.onrowdblclick, this);
        
this.getSelectionModel().on('selectionchange'this.onSelectionChange, this);
        YC.TeacherRankDef.Grid.superclass.initComponent.call(
this);
    },

    buildTopToolbar : 
function() {
        
return [
            {
                xtype : 
"tbbutton",
                minWidth : 
80,
                ref : 
'../addBtn',
                text : 
"添加项",
                cls : 
"x-btn-text-icon",
                icon : 
"/Content/icons/add.png",
                handler : 
this.onAdd,
                scope: 
this
            },
            
"-",
            {
                xtype : 
"tbbutton",
                ref : 
'../delBtn',
                minWidth : 
80,
                disabled : 
true,
                text : 
"删除项",
                cls : 
"x-btn-text-icon",
                icon : 
"/Content/icons/delete.png",
                handler : 
this.onDelete,
                scope : 
this
            },
            
"-",
            {
                xtype : 
"tbbutton",
                minWidth : 
80,
                text : 
"双击修改项",
                cls : 
"x-btn-text-icon",
                icon : 
"/Content/icons/pencil.png",
                disabled : 
true
            }
        ];
    },
    onAdd : 
function(btn, e) {
        
this.showEditFormWinFn(this.store.reader, "添加教师级别");
    },
    onDelete : 
function(btn, e) {
        JsHelper.DelConfirm(
function(btn) {
            
if (btn == 'yes') {
                
var s = this
                        .getSelectionModel()
                        .getSelections();
                
for (var i = 0, r; r = s[i]; i++) {
                    
this.store.remove(r);
                }
            }
        });
    },
    onSelectionChange : 
function(sm) {
        
this.delBtn.setDisabled(sm.getCount() < 1);
    },

    buildBottomToolbar : 
function() {
        
return new Ext.PagingToolbar({
            displayInfo : 
true,
            emptyMsg : 
"没有数据显示",
            displayMsg : 
"显示从{0}条数据到{1}条数据,共{2}条数据",
            store : 
this.store,
            pageSize : ALL_PAGESIZE_SETTING,
            plugins : [
this.filters]
        });
    },
    filters : 
new Ext.ux.grid.GridFilters({
        encode : 
true,
        filters : [
            {type: 
'int',dataIndex: 'Value'},
            {type: 
'string',dataIndex: 'Text'},
            {type: 
'float',dataIndex: 'BasePrice'},
            {type: 
'date',dataIndex: 'CreateTime'},
            {type: 
'boolean',dataIndex: 'IsDelete'},
            {type: 
'string',dataIndex: 'Id'}
        ]
    }),

    
//TODO: Merge listeners of store into grid listeners by relaying
    buildStores : function() {
        
var store = new Ext.data.Store({
            url : 
"/TeacherRankDef/GetPlist",
            remoteSort : 
true,
            reader : 
new Ext.data.JsonReader({
                root : 
'data',
                totalProperty : 
'total',
                id : 
'Id'
            }, [
                {name: 
'Value',type: 'int'}
                ,
                {name: 
'Text',type: 'string'}
                ,
                {name: 
'BasePrice',type: 'float'}
                ,
                {name: 
'CreateTime',type: 'date'}
                ,
                {name: 
'IsDelete',type: 'boolean'}
                ,
                {name: 
'Id',type: 'string'}

            ])
        });
        store.on(
'remove'this.onStoreRemove, this);
        store.setDefaultSort(
'Value''ASC');
        
return [store];
    },
    onStoreRemove : 
function(thiz, record, index) {
        Ext.Ajax.request({
            url : 
'/TeacherRankDef/Delete',
            params : {
                
'Id' : record.data.Id
            },
            success : 
function(response, opts) {
                
var result = Ext.util.JSON
                        .decode(response.responseText);
                
if (result.success == false) {
                    JsHelper.ShowError(result.msg);
                    
this.store.insert(0, record);
                }
            }
        });
    },
    buildWin : 
function() {
        
var form = new Ext.FormPanel({
            id : 
'mainForm',
            border : 
false,
            waitMsgTarget : 
true,
            labelWidth : 
90,
            frame : 
true,
            bodyStyle : 
'padding:5px 5px 0',
            labelAlign : 
'right',
            layout : 
'tableform',
            layoutConfig : {
                columns : 
2
            },
            defaultType: 
'textfield',
            defaults: {
                allowBlank: 
false,
                width: 
150
            },
            items : [
                {name: 
'Value',xtype: 'textfield', fieldLabel : ''}
                ,
                {name: 
'Text',xtype: 'textfield', fieldLabel : '文本'}
                ,
                {name: 
'BasePrice',xtype: 'textfield', fieldLabel : '基本收费'}
            ],
            buttonAlign : 
'center',
            buttons : 
this.buildFormButtons()
        });
        
var win = new Ext.Window({
            iconCls : 
'application_form',
            width : 
700,
            resizable : 
false,
            constrain : 
true,
            autoHeight : 
true,
            modal : 
true,
            closeAction : 
'close',
            plain : 
true,
            items : [form]
        });
        
return win;
    },
    buildFormButtons : 
function() {
        
var btnSubmit = new Ext.ux.SubmitBtn({
            handler : 
function() {
                
var form = this.win.items.items[0];
                
if (form.getForm().isValid()) {
                    form.getForm().submit({
                        url : 
'/TeacherRankDef/SaveOrUpdate',
                        params : {
                            
'Id' : (form.updateEdit) ? form.entityId : ""
                        },
                        success : 
function(form, action) {
                            
this.store.setDefaultSort(
                                    
'Value''ASC');
                            
this.store.load({
                                params : {
                                    start : 
0,
                                    limit : ALL_PAGESIZE_SETTING
                                }
                            });
                            
this.win.destroy();
                        },
                        failure : 
function(form, action) {
                            JsHelper
                                    .ShowError(action.result.msg);
                        }
                    });
                }
            },
            scope: 
this
        });
        
var btnCancel = new Ext.ux.CancelBtn({
            handler : 
function() {
                
this.win.destroy();
            },
            scope : 
this
        });
        
return [btnSubmit, btnCancel];
    },
    buildCm : 
function() {
        
return new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(), this.sm,
            {header: 
'',dataIndex: 'Value',sortable: true},
            {header: 
'文本',dataIndex: 'Text',sortable: true},
            {header: 
'基本收费',dataIndex: 'BasePrice',sortable: true}
        ]);
    },
    showEditFormWinFn : 
function(formReader, title, id) {
        
this.win = this.buildWin();
        
var updateEdit = Ext.isDefined(id);
        
var formLoadArgs = (updateEdit) ? {
            url : 
'/TeacherRankDef/Get',
            params : {
                
'Id' : id
            },
            waitMsg : 
'数据加载中...'
        } : 
null;

        
var form = this.win.items.items[0];
        form.reader 
= formReader;
        form.updateEdit 
= updateEdit;
        form.entityId 
= id;
        
this.win.title = title;
        
this.win.show();
        
if (formLoadArgs) {
            form.load(formLoadArgs);
        }
    },
    onrowdblclick : 
function(g, rowIndex, e) {
        
var store = g.getStore();
        
var id = store.getAt(rowIndex).get("Id");
        
this.showEditFormWinFn(this.store.reader, "修改教师级别", id);
    }
});

 

 

这样的话,对于上面所描述的需求,只需要把这个类add到右边的Panel中即可。而且,由于已经把可能需要根据具体情况调整的属性和方法暴露了出来(而不再是闭包的变量),可以按需更改。从维护角度来说,代码也比较清晰,循着initComponent方法中的几行代码为主线浏览即可。

posted on 2010-05-15 01:00  追萝驴  阅读(1843)  评论(0编辑  收藏  举报