NHibernate3.2+Asp.net MVC3+Extjs 4.0.2项目实践(六):Extjs Grid,Window,Form实现增删改操作

    上一节讲到利用树形菜单的打击事件来动态加载Tab(继承自Ext.Panel)页,那Tab页如何来装载Grid,并实现数据浏览及增删改操作呢?原理是这样的:Tab页中autoLoad属性的url定义为Controller的Action方法,来render一个MVC view到Tab Panel,而view装载的是GridPanel的Extjs组件,这个组件并不是自定义组件(非define),而是直接用Ext.create来创建的,可能因为涉及到Grid的操作比较多;这里有一个宽度自适应问题,就是当浏览器resize的时候,GridPanel的宽度如何来自适应,方法是定义Tab Panel的resize事件来控制GridPanel的宽度,可以参考上一节贴出的代码。

    接下来看一下Controller:

CountryController.cs
隐藏行号 复制代码
  1. public partial class AppCenterController : Controller
    
  2.    {
    
  3.        //
    
  4.        // GET: /Country/
    
  5. 
    
  6.        public ActionResult CountryPage()
    
  7.        {
    
  8.            return PartialView("~/Views/AppCenter/_Country.cshtml");
    
  9.        }
    
  10. 
    
  11.        [AcceptVerbs(HttpVerbs.Get)]
    
  12.        public JsonResult CountryList()
    
  13.        {
    
  14.            var result = _iLocation_CountryService.GetLocation_Countries();
    
  15.            var ts = from t in result
    
  16.                     select new { t.CountryId, t.CountryName, t.CountryCode1, t.CountryCode2, t.CountryDialCode, t.ModifiedDate, t.ModifiedBy };
    
  17. 
    
  18.            int total = result.Count;
    
  19. 
    
  20.            //var tss = result.AsQueryable().ToList();
    
  21. 
    
  22.            return Json(new { Countries = ts, totalCount = total }, JsonRequestBehavior.AllowGet);
    
  23.        }
    
  24. 
    
  25.        [HttpPost]
    
  26.        public JsonResult CreateCountry(Location_Country country)
    
  27.        {
    
  28.            try
    
  29.            {
    
  30.                country.ModifiedBy = ADHelper.ToADAccountName(User.Identity.Name);
    
  31.                country.ModifiedDate = DateTime.Now;
    
  32. 
    
  33.                if (_iLocation_CountryService.CreateLocation_Country(country))
    
  34.                {
    
  35.                    return Json(new { success = true, Msg = "Add country successfully." });
    
  36.                }
    
  37.                else
    
  38.                {
    
  39.                    return Json(new { success = false, Msg = "Failed to add country." });
    
  40.                }
    
  41.            }
    
  42.            catch
    
  43.            {
    
  44.                return Json(new {success=false, Msg ="Unkown error occurred while adding country." });
    
  45.                //return Json(new { success = false, Msg = "Unkown error:</br>" + "Source:" + ex.TargetSite.Name + "</br> Error:" + ex.Message });
    
  46.            }
    
  47.        }
    
  48. 
    
  49.        [HttpPost]
    
  50.        public JsonResult UpdateCountry(Location_Country country)
    
  51.        {
    
  52.            try
    
  53.            {
    
  54.                Location_Country lc = _iLocation_CountryService.FindLocation_Country(Data.DataAccess.Country_Query_Index.CountryId, country.CountryId);
    
  55. 
    
  56.                country.ModifiedDate = lc.ModifiedDate;
    
  57.                country.ModifiedBy = lc.ModifiedBy;
    
  58. 
    
  59.                if (_iLocation_CountryService.UpdateLocation_Country(country))
    
  60.                {
    
  61.                    return Json(new { success = true, Msg = "Update country successfully." });
    
  62.                }
    
  63.                else
    
  64.                {
    
  65.                    return Json(new { success = false, Msg = "Failed to update country." });
    
  66.                }
    
  67.            }
    
  68.            catch
    
  69.            {
    
  70.                return Json(new { success = false, Msg = "Unkown error occurred while updating country." });
    
  71.            }
    
  72.        }
    
  73. 
    
  74.        [HttpPost]
    
  75.        public JsonResult DeleteCountries(Array countries)
    
  76.        {
    
  77.            var message="";
    
  78.            int iUpdates=0;
    
  79. 
    
  80.            try
    
  81.            {
    
  82.                foreach (object o in countries)
    
  83.                {
    
  84.                    Location_Country lc = _iLocation_CountryService.FindLocation_Country(Data.DataAccess.Country_Query_Index.CountryId, Convert.ToInt32(o));
    
  85. 
    
  86.                    if (_iLocation_CountryService.DeleteLocation_Country(lc))
    
  87.                        iUpdates += 1;
    
  88.                }
    
  89. 
    
  90.                message = iUpdates.ToString() + " countries deleted successfully.";
    
  91. 
    
  92.                return Json(new { success = true, Msg = message });
    
  93.            }
    
  94.            catch
    
  95.            {
    
  96.                message = "Error occurred while deleting countries and "+iUpdates.ToString()+" countries deleted.";
    
  97.                return Json(new { success = false, Msg = message });
    
  98.            }
    
  99.        }
    
  100.    }
    

    CountryController.cs中定义了partialView,CountryList,Create,Update和Delete的Action。

隐藏行号 复制代码
  1. <script src="@Url.Content("~/Components/Tesz.App/Pages/Country.js")" type="text/javascript"></script>
    
  2. <div id="divCountry"></div>
    
  3. 
    

  以上是View文件_Country.cshtml。

Country.js
隐藏行号 复制代码
  1. Ext.require('Tesz.App.Models.CountryModel');
    
  2. Ext.require('Tesz.App.Stores.CountryStore');
    
  3. 
    
  4. var store;
    
  5. 
    
  6. Ext.onReady(function () {
    
  7. 
    
  8.     store = Ext.create('Tesz.App.Stores.CountryStore');
    
  9. 
    
  10.     LoadGridData();
    
  11. 
    
  12.     var refreshAction = Ext.create('Ext.Action', {
    
  13.         iconCls: 'x-tbar-loading',
    
  14.         text: 'Refresh',
    
  15.         handler: LoadGridData
    
  16.     });
    
  17. 
    
  18.     var addAction = Ext.create('Ext.Action', {
    
  19.         iconCls: 'x-toolbarbtn-add',
    
  20.         text: 'Add new item',
    
  21.         handler: function () {
    
  22.             openCTRYWindow('Add');
    
  23.         }
    
  24.     });
    
  25. 
    
  26.     var deleteAction = Ext.create('Ext.Action', {
    
  27.         iconCls: 'x-toolbarbtn-delete',
    
  28.         text: 'Delete item',
    
  29.         disabled: true,
    
  30.         handler: function () {
    
  31.             Ext.MessageBox.confirm('Message', 'Sure to delete selected items?', function (e) {
    
  32.                 if (e == 'no') {
    
  33.                     return;
    
  34.                 }
    
  35.                 else {
    
  36.                     DeleteCounties();
    
  37.                 }
    
  38.             });
    
  39.         }
    
  40.     });
    
  41. 
    
  42.     var gridCountry = Ext.create('Ext.grid.Panel', {
    
  43.         renderTo: 'divCountry',
    
  44.         requires:['Tesz.App.SearchField'],
    
  45.         id: 'COUNTRYGRID',
    
  46.         height: 350,
    
  47.         store: store,
    
  48.         frame: true,
    
  49.         selModel: Ext.create('Ext.selection.CheckboxModel'),
    
  50.         columns: [{
    
  51.             text: "Id",
    
  52.             dataIndex: 'CountryId',
    
  53.             width: 50,
    
  54.             sortable: true
    
  55.         }, {
    
  56.             text: "Name",
    
  57.             dataIndex: 'CountryName',
    
  58.             width: 150
    
  59.         }, {
    
  60.             text: "Code1",
    
  61.             dataIndex: 'CountryCode1',
    
  62.             width: 100
    
  63.         }, {
    
  64.             text: "Code2",
    
  65.             dataIndex: 'CountryCode2',
    
  66.             width: 100
    
  67.         }, {
    
  68.             text: "Dial Code",
    
  69.             dataIndex: 'CountryDialCode',
    
  70.             width: 100
    
  71.         }, {
    
  72.             text: "Modified Date",
    
  73.             dataIndex: 'ModifiedDate',
    
  74.             renderer: renderTime,
    
  75.             width: 150
    
  76.         }, {
    
  77.             text: "Modified By",
    
  78.             dataIndex: 'ModifiedBy',
    
  79.             flex: 1
    
  80.         }],
    
  81.         dockedItems: [{
    
  82.             xtype: 'toolbar',
    
  83.             //store: store,   // same store GridPanel is using 
    
  84.             dock: 'bottom',
    
  85.             height: 26,
    
  86.             items: [refreshAction, '-', {
    
  87.                 text: 'Total 0 records.',
    
  88.                 id: 'tbarCount'
    
  89.             }]
    
  90.         }, {
    
  91.             xtype: 'toolbar',
    
  92.             dock: 'top',
    
  93.             items: [addAction, '-', deleteAction, '-', exportAction]
    
  94.         }],
    
  95.         listeners: {
    
  96.             itemdblclick: function (grid, rec, item, index, e) {
    
  97.                 openCTRYWindow('Edit');
    
  98. 
    
  99.                 var form = Ext.getCmp('COUNTRYFORM');
    
  100.                 form.loadRecord(rec);
    
  101.                 //alert(form.id);
    
  102.             }
    
  103.         }
    
  104.     });
    
  105. 
    
  106.     gridCountry.getSelectionModel().on({
    
  107.         selectionchange: function (sm, selections) {
    
  108.             if (selections.length) {
    
  109.                 deleteAction.enable();
    
  110.             } else {
    
  111.                 deleteAction.disable();
    
  112.             }
    
  113.         }
    
  114.     });
    
  115. });
    
  116. 
    
  117. function openCTRYWindow(action) {
    
  118.     var window = Ext.getCmp('COUNTRYWINDOW');
    
  119.     if  (!window)
    
  120.         window = Ext.create('Tesz.App.Forms.CountryForm');
    
  121. 
    
  122.     window.setTitle(action);
    
  123. 
    
  124.     if (action == 'Add') {
    
  125.         var form = Ext.getCmp('COUNTRYFORM');
    
  126.         form.form.reset();
    
  127.     }
    
  128. 
    
  129.     window.show();
    
  130. 
    
  131. }
    
  132. 
    
  133. function LoadGridData() {
    
  134.     store.load({
    
  135.         callback: function (records, options, success) {
    
  136.             //var total = store.getCount();
    
  137.             //totalRecordCount = records.length;
    
  138.             //alert(records.length);
    
  139.             var tbar = Ext.getCmp('tbarCount');
    
  140.             tbar.setText('Total ' + records.length + ' records.');
    
  141.         }
    
  142.     });
    
  143. }
    
  144. 
    
  145. function DeleteCounties() {   
    
  146.     var grid = Ext.getCmp('COUNTRYGRID');
    
  147.     var records = grid.getSelectionModel().getSelection();
    
  148.     var array=new Array(records.length);
    
  149. 
    
  150.     for (var i = 0; i < records.length; i++) {
    
  151.         array[i] = records[i].get('CountryId');
    
  152.     }
    
  153. 
    
  154.     Ext.Ajax.request({
    
  155.         url: 'DeleteCountries', //请?求ó的?Action
    
  156.         method: "POST",
    
  157.         params: { countries: array }, //发¢送í的?参?数y
    
  158.         success: function (r, p) {
    
  159.             var o = Ext.decode(r.responseText);
    
  160.             try {
    
  161.                 Ext.MessageBox.alert("Message", o.Msg, LoadGridData);
    
  162.             }
    
  163.             catch (e) {
    
  164.                 Ext.MessageBox.alert("Unkown error", e);
    
  165.             }
    
  166.         },
    
  167.         failure: function (r, p) {
    
  168.             try {
    
  169.                 Ext.MessageBox.alert("Error", o.Msg);
    
  170.             }
    
  171.             catch (e) {
    
  172.                 Ext.MessageBox.alert("Unkown error", e);
    
  173.             }
    
  174.         }
    
  175.     });
    
  176. }
    
  177. 
    

     Country.js是View文件装载的GridPanel的js组件,定义了GridPanel的toolbar、toolbar buttons及事件;GridPanel的itemdblclick及selectionchange事件;还有LoadGridData,DeleteCounties方法。toolbar buttons包括Add,Delete和Refresh,继承自Ext.Action;通过点击Add按钮,打开一个内嵌FormPanel的Window来执行数据记录的添加,或由GridPanel的itemdblclick事件打开,两个事件以标识所打开Window的Title为”Add”,”Edit”来区分是添加还是修改操作。GridPanel的selectionchange事件响应Delete按钮的Enable和Disable;LoadGridData实现GridPanel数据的刷新。DeleteCounties方法通过GridPanel的selectionchange事件响应的grid.getSelectionModel().getSelection()获取选中的记录Id的Array作为参数Post给Controller的Delete action;

     Add,Modify,Delete事件结果通过Ext.MessageBox来通知,并加入了错误处理及提示。

  Country.js所引用的Store,Model如下:

CountryStore.js
隐藏行号 复制代码
  1. Ext.define('Tesz.App.Stores.CountryStore', {
    
  2.     extend: 'Ext.data.Store',
    
  3.     requires: ['Tesz.App.Models.CountryModel'],
    
  4.     alias: 'widget.countrystore',
    
  5.     //model: 'stateprovincemodel',
    
  6.     model: 'Tesz.App.Models.CountryModel',
    
  7.     //pageSize: 20,
    
  8.     proxy: {
    
  9.         type: 'ajax',
    
  10.         url: 'CountryList',
    
  11.         reader: {
    
  12.             type: 'json',
    
  13.             root: 'Countries',
    
  14.             totalProperty: 'totalCount',
    
  15.             id: 'CountryId'
    
  16.         }
    
  17.     }
    
  18. });
    
CountryModel.js
隐藏行号 复制代码
  1. Ext.define('Tesz.App.Models.CountryModel', {
    
  2.     extend: 'Ext.data.Model',
    
  3.     alias: 'widget.countrymodel',
    
  4.     idProperty: 'CountryId',
    
  5.     fields: ['CountryId', 'CountryName', 'CountryCode1', 'CountryCode2', 'CountryDialCode', 'ModifiedDate', 'ModifiedBy']
    
  6. });
    

    最后就是记录的添加和修改操作了,通过FormPanel的form.submit()实现;Open Window时如果为”Add”操作,用form.reset()来清空Fields,为”Edit”时用form.loadRecord(rec)方法装载Fields。submit时以Window的Title为依据来定义submit的url指向controller的action,submit前先对Fields进行合法性验证。代码如下:

CountryForm.js
隐藏行号 复制代码
  1. var countryform = Ext.create('Ext.form.Panel', {
    
  2.     frame: true,
    
  3.     id: 'COUNTRYFORM',
    
  4.     monitorValid: true,
    
  5.     bodyStyle: 'padding:5px 5px 0',
    
  6.     fieldDefaults: {
    
  7.         labelAlign: 'top',
    
  8.         msgTarget: 'side'
    
  9.     },    
    
  10.     items: [{
    
  11.         xtype: 'container',
    
  12.         anchor: '100%',
    
  13.         layout: 'column',
    
  14.         items: [{
    
  15.             xtype: 'container',
    
  16.             columnWidth: .5,
    
  17.             layout: 'anchor',
    
  18.             items: [{
    
  19.                 xtype: 'textfield',
    
  20.                 name: 'CountryId',
    
  21.                 value: 0,
    
  22.                 hidden: true
    
  23.             },{
    
  24.                 xtype: 'textfield',
    
  25.                 fieldLabel: 'Country Name',
    
  26.                 name: 'CountryName',
    
  27.                 allowBlank: false,
    
  28.                 maxLength: 50,
    
  29.                 anchor: '96%'
    
  30.             }, {
    
  31.                 xtype: 'textfield',
    
  32.                 fieldLabel: 'Country Code1',
    
  33.                 name: 'CountryCode1',
    
  34.                 maxLength: 10,
    
  35.                 anchor: '96%'
    
  36.             }]
    
  37.         }, {
    
  38.             xtype: 'container',
    
  39.             columnWidth: .5,
    
  40.             layout: 'anchor',
    
  41.             items: [{
    
  42.                 xtype: 'textfield',
    
  43.                 fieldLabel: 'Country Code2',
    
  44.                 name: 'CountryCode2',
    
  45.                 maxLength: 10,
    
  46.                 anchor: '100%'
    
  47.             }, {
    
  48.                 xtype: 'textfield',
    
  49.                 fieldLabel: 'Dial Code',
    
  50.                 name: 'CountryDialCode',
    
  51.                 maxLength: 10,
    
  52.                 anchor: '100%'
    
  53.             }]
    
  54.         }]
    
  55.     }],
    
  56.     buttons: [{
    
  57.         text: 'Save',
    
  58.         formBind: true,
    
  59.         handler: SubmitForm
    
  60.     }, {
    
  61.         text: 'Cancel',
    
  62.         handler: CloseWindow
    
  63.     }]
    
  64. });
    
  65. Ext.define('Tesz.App.Forms.CountryForm', {
    
  66.     extend: 'Ext.Window',
    
  67.     id:'COUNTRYWINDOW',
    
  68.     title: 'Country Edit',
    
  69.     width: 600,
    
  70.     height: 400,
    
  71.     iconCls: 'x-window-icon',
    
  72.     plain: true,
    
  73.     constrain: true,
    
  74.     closeAction: 'hide',
    
  75.     layout:'fit',
    
  76.     modal: true,
    
  77.     items: countryform
    
  78. });
    
  79. function SubmitForm() {
    
  80.     if (!countryform.form.isValid()) {
    
  81.         return;
    
  82.     }
    
  83.     var win = Ext.getCmp('COUNTRYWINDOW');
    
  84.     var actionUrl;
    
  85.     if (win.title == 'Add') {
    
  86.         actionUrl = 'CreateCountry';
    
  87.     }
    
  88.     else {
    
  89.         actionUrl = 'UpdateCountry';
    
  90.     }
    
  91.     countryform.form.submit({
    
  92.         waitMsg: "Submitting data to server...",
    
  93.         url: actionUrl,
    
  94.         success: function (f, a) {
    
  95.             try {
    
  96.                 Ext.MessageBox.alert("Message", a.result.Msg, RefreshCountryGrid);
    
  97.             }
    
  98.             catch (e) {
    
  99.                 Ext.MessageBox.alert("Unkown error", e);
    
  100.             }
    
  101.         },
    
  102.         failure: function (f, a) {
    
  103.             try {
    
  104.                 Ext.MessageBox.alert("Error", a.result.Msg);
    
  105.             }
    
  106.             catch (e) {
    
  107.                 Ext.MessageBox.alert("Unkown error", e);
    
  108.             }
    
  109.         }
    
  110.     });
    
  111. }
    
  112. function CloseWindow() {
    
  113.     var win = Ext.getCmp('COUNTRYWINDOW');
    
  114.     win.hide();
    
  115. }
    
  116. function RefreshCountryGrid() {
    
  117.     var grid = Ext.getCmp('COUNTRYGRID');
    
  118.     grid.getStore().load({
    
  119.         callback: function (records, options, success) {
    
  120.             //var total = store.getCount();
    
  121.             //totalRecordCount = records.length;
    
  122.             //alert(records.length);
    
  123.             var tbar = Ext.getCmp('tbarCount');
    
  124.             tbar.setText('Total ' + records.length + ' records.');
    
  125.         }
    
  126.     });
    
  127.     CloseWindow();
    
  128. }
    
posted @ 2011-11-03 13:43  Leo Wuang  阅读(3800)  评论(15编辑  收藏  举报