版權聲明:本文爲博主原創文章,未經博主允許不得轉載。
有時候閒的無聊,看到extjs那麼肥大,真想把自己的項目改了,最近看到一款輕型的UI感覺不錯,但是在網上找了好多教程,但是沒有一個是完全是C#asp.net寫的
無耐下,自己寫了下,感覺效果不錯,故拿出來和大學分享一下,希望可以拋磚引玉作用.
由於好多人都只是拷貝代碼,故在此全用圖片作說明.
圖片效果圖1
這個界面是上左右下結構
左邊是一棵樹
右邊是一個表格
上部是標題
最下部只是一個空的保留一部分空間
下面開始說下整體結構HTML代碼如下
至於HTML代碼不想在做多餘的解說
下面開始左邊的樹,在easyUI裏面是有樹的,但這裏沒有用,在這裏還得感謝Ferry's blogs提供的dTree樹,在網上叫無級樹,因爲它擴展性還是比較好的,在此就用它吧.
在用它之前還是先看下dtree 說明文檔,在下載這樹JS裏面有詳細的說明
在上面<head>裏面樹這樣寫,不懂可以看下文檔這裏就不作多解釋了.
- //<--Tree Begin-->
- d = new dTree('d');
- d.add(0, -1, '個人面板');
- function getData(id) {
- $.ajax({
- url: 'TreeSource/GetTreeData.ashx?parentID=' + id,
- type: 'post',
- datatype: 'json',
- success: function (JsonValureturne) {
- if (JsonValureturne) {
- //格式化爲JSON數據格式
- var json = eval("(" + JsonValureturne + ")");
- //alert(json.Menu.length);
- //document.write(returnJsonValue.Menu[0].MenuName);
- //遍歷集合,添加樹節點
- $.each(json.Menu, function (key, value) {
- if (id == 0) {
- d.add(value.ID, value.ParentMenuID, value.MenuName, '', value.MenuName, '', 'img/folder.gif', 'img/folderopen.gif');
- }
- else {
- d.add(value.ID, value.ParentMenuID, value.MenuName, "javascript:addTab('" + value.MenuName + "','" + value.MenuClickURL + "')", value.MenuName, '');
- }
- //根據模塊的ParentID遞歸綁定數據
- getData(value.ID);
- })
- }
- else {
- $("#divTree").html(d.toString());
- //數據請求完畢,隱藏圖片
- }
- }
- })
- }
- $(getData(0));
- //<--Tree End-->
這裏我們引用一個後臺文件'TreeSource/GetTreeData.ashx?parentID=' + id
意思就是傳給後臺一個父ID,返回一組json數據
數據庫結構這裏也貼出來吧,以防有人不理解.
像這樣 設計如果還是不懂,請參考dtree文檔
下面重點來講解後臺如何來處理及返回數據據的.
- <%@ WebHandler Language="C#" Class="GetTreeData" %>
- using System;
- using System.Web;
- using System.Data;
- using System.Collections;
- using System.Collections.Generic;
- using System.Web.Script.Serialization;
- public class GetTreeData : IHttpHandler
- {
- public bool IsReusable
- {
- get { return false; }
- }
- public void ProcessRequest(HttpContext context)
- {
- //不讓瀏覽器緩存
- // context.Response.Buffer = true;
- // context.Response.ExpiresAbsolute = DateTime.Now.AddDays(-1);
- // context.Response.AddHeader("pragma", "no-cache");
- // context.Response.AddHeader("cache-control", "");
- // context.Response.CacheControl = "no-cache";
- context.Response.ContentType = "text/plain";
- if (!String.IsNullOrEmpty(GetParentID(context)))
- {
- string ParentID = GetParentID(context);
- DataTable dt = SqlHelper.FillDataTable(String.Format(
- "SELECT * FROM SunZonTMSMenu WHERE ParentMenuID={0}", ParentID
- ));
- IList<Menu> menu = new List<Menu>();
- if (dt != null && dt.Rows.Count > 0)
- {
- foreach (DataRow dr in dt.Rows)
- {
- menu.Add(new Menu()
- {
- ID = Int32.Parse(dr["ID"].ToString()),
- ParentMenuID = Int32.Parse(dr["ParentMenuID"].ToString()),
- MenuName = dr["MenuName"].ToString(),
- MenuCode = dr["MenuCode"].ToString(),
- MenuClickURL = dr["MenuClickURL"].ToString()
- });
- }
- }
- if (menu.Count > 0)
- {
- context.Response.Write(FormatToJson.ListToJson<Menu>(menu));
- }
- }
- }
- public string GetParentID(HttpContext context)
- {
- return context.Request["parentID"];
- }
- }
這裏使用一個類庫SqlHelper.FillDataTable()及IList<Menu> menu = new List<Menu>() meun類
還有一個FormatToJson.ListToJson<T>(T))泛型方法,別嚇着了,其它很簡單.
先分析一下這裏的總體思路.
1)獲取前臺的父ID
2)通過此ID在數據裏查找相應的數據
3)再把返回的數據據填充到自定義的類裏面,可能問爲什麼這樣做,因爲這樣做可以利用反射的方法很好的外理數據,下面會詳細的說明
4)把形成的類集合IList<Menu>格式化成json數據並返回給前臺
看下怎麼查找數據SqlHelper.FillDataTable()方法
就這麼簡單
下面再看下類Meun
注意了這個類是在VS2010上面寫的,每個成員類型必須和數據庫一致,
下面關健的一部就是把這個類集合格式化JSON數據,來看下代碼
好了,這些基本上完成了轉化的方法,
我們來看看前臺返回的婁據是什麼樣的,相信很多人都明白了
如果出現這些數據說明就成功了
這裏做下說明吧,Meun就是我們的類名稱,數據庫裏面是什麼型的數據這裏必須返回什麼樣的類型,很多json示例都是引號的,這裏看到了吧,並不是json數據都用引號,希望這點大家要理解,這也是標準的Json數據形式,爲什麼我們要把ID作爲整形呢,因爲我們傳給後臺的時候用整形或者數據庫設計一般都用整形這樣可以設主健等等好處,
前臺接收數據的時候需要注意的var json = eval("(" + JsonValureturne + ")");
因爲我們返回的時候是以字符串形式返回的,必須用eval轉化下或者paserjson方法都行的,eval用了雙的括號(),這樣是把裏面的數據才真正意思上的轉化爲對象
詳細請看eval用法,這裏就不多說了.
這樣一棵樹就做好了.
下面開始說右邊的內容區
右邊是採用jQuery easyUI tab面板詳情請參考tab文檔
在head頭部境加代碼
- //<--Tabs Begin-->
- $(function () {
- $('#tt').tabs({
- tools: [{
- iconCls: 'icon-add',
- handler: function () {
- alert('add');
- }
- }, {
- iconCls: 'icon-save',
- handler: function () {
- alert('save');
- }
- }]
- });
- });
- function addTab(tit, link) {
- if ($('#tt').tabs('exists', tit)) {
- $.messager.alert('提示消息', '窗口已經打開。', 'info');
- } else {
- $('#tt').tabs('add', {
- title: tit,
- //href: link,
- content: '<iframe scrolling="yes" frameborder="0" src="' + link + '" style="width:100%;height:98%;"></iframe>',
- fit: true,
- closable: true
- });
- }
- }
- //<--Tabs End-->
這樣我們的面板就好了.
下面再看面板裏的表是怎麼增加的
- $('#roleList').datagrid({
- title: '',
- loadMsg: "數據加載中,請稍後……",
- nowrap: false,
- striped: true,
- collapsible: true,
- url: 'ashx/RoleHandler.ashx',
- pageList: [10, 15, 20, 25, 30, 40, 50],
- pageSize: 15,
- sortName: 'RoleSort',
- sortOrder: 'asc',
- remoteSort: false,
- idField: 'RoleCode',
- frozenColumns: [[
- { field: 'ck', checkbox: true },
- { title: '角色編碼', field: 'RoleCode', width: 120, align: 'center', sortable: true }
- ]],
- columns: [[
- { field: 'RoleName', title: '角色名稱', width: 120, align: 'center', sortable: true },
- { field: 'RoleSort', title: '默認排序', width: 80, align: 'center', sortable: true },
- { field: 'opt', title: '操作', width: 100, align: 'center',
- formatter: function (value, rec) {
- return '<a href="#" οnclick="parent.addTab(\'編輯角色[' + rec.RoleName + ']\', \'Role/Edit.aspx?RoleCode=' + rec.RoleCode + '&RoleName=' + rec.RoleName + '\')"><span style="color:red">編輯</span></a>';
- }
- }
- ]],
- pagination: true,
- rownumbers: true,
- onLoadSuccess: function () {
- $('.datagrid-toolbar').append($('#txtSearch'));
- $('#txtSearch').show();
- },
- toolbar: [
- {
- id: 'btnadd',
- text: '添加',
- iconCls: 'icon-add',
- handler: function () {
- parent.addTab('添加角色', 'Role/Edit.aspx');
- }
- }, {
- id: 'btncut',
- text: '刪除',
- iconCls: 'icon-cut',
- handler: function () {
- var codes = getSelections();
- if (codes == '') {
- $.messager.alert('提示消息', '請選擇要刪除的數據!', 'info');
- } else {
- $.messager.confirm('提示消息', '確定要刪除所選數據嗎?', function (r) {
- if (r) {
- $('#processWindow').window('open', 'aadasdsads');
- $.ajax({
- url: 'ashx/RoleHandler.ashx?Codes=' + codes,
- type: 'post',
- datatype: 'text',
- success: function (returnValue) {
- if (returnValue) {
- $('#processWindow').window('close');
- $('#roleList').datagrid('reload');
- $('#roleList').datagrid('clearSelections');
- }
- }
- });
- }
- });
- }
- }
- }, '-',
- {
- id: 'btnSearch',
- text: '搜索',
- disabled: false,
- iconCls: 'icon-search',
- handler: function () {
- $('#roleList').datagrid('options').url = 'ashx/RoleHandler.ashx?RoleName=' + escape($('#txtSearch').val());
- $('#roleList').datagrid("reload");
- }
- }
- ]
- }).datagrid("columnMoving");
- });
- function getSelections() {
- var ids = [];
- var rows = $('#roleList').datagrid('getSelections');
- for (var i = 0; i < rows.length; i++) {
- ids.push(rows[i].RoleCode);
- }
- return ids.join(',');
- }
- <table id="roleList">
- </table>
- <div id="processWindow" class="easyui-window" closed="true" modal="true" title="提示消息"
- style="width: 300px; height: 60px;">
- <div id="windowContent" class="general-font">
- <img src="jqueryPager/jquery-easyui/themes/gray/images/panel_loading.gif" />
- 操作進行中,請稍後...
- </div>
- </div>
- <input type="text" id="txtSearch" title="請輸入角色名稱" style="display: none;" />
下面是後臺處理的代碼
- <%@ WebHandler Language="C#" Class="RoleHandler" %>
- using System;
- using System.Web;
- using System.Data;
- using System.Collections;
- using System.Collections.Generic;
- using System.Web.Script.Serialization;
- public class RoleHandler : IHttpHandler
- {
- #region IHttpHandler Members
- public bool IsReusable
- {
- get { return true; }
- }
- public void ProcessRequest(HttpContext context)
- {
- context.Response.ContentType = "text/plain";
- SqlHelper sqlhelper=new SqlHelper();
- if (!String.IsNullOrEmpty(GetRoleCodes(context)))
- {
- String codes = GetRoleCodes(context);
- codes = "'" + codes.Replace(",", "','") + "'";
- SqlHelper.ExecuteNonQuery(string.Format("delete from Roles where RoleCode in({0})", codes));
- context.Response.Write("true");
- }
- else
- {
- int Count;
- int pagesiz=GetPageSize(context);
- int page=GetPageIndex(context);
- DataTable dt = new DataTable();
- string sqlWhere = string.Format("RoleName like '%{0}%'", GetRoleName(context));
- DataSet ds= SqlHelper.m_QueryPagination("Roles","*",sqlWhere,"RoleSort",pagesiz,page,out Count);
- dt = ds.Tables[0];
- IList<Roles> list = new List<Roles>();
- if (dt != null && dt.Rows.Count > 0)
- {
- foreach (DataRow dr in dt.Rows)
- {
- list.Add(new Roles()
- {
- RoleCode = dr["RoleCode"].ToString(),
- RoleName = dr["RoleName"].ToString(),
- RoleSort = int.Parse(dr["RoleSort"].ToString())
- });
- }
- }
- if (list.Count > 0)
- {
- dt.Clear();
- string data = FormatToJson.ListToJson<Roles>(list, "rows");
- data = data.Substring(1);
- context.Response.Write(
- "{ \"total\":" +Count + "," +data);
- }
- }
- }
- public String GetRoleCodes(HttpContext context)
- {
- return context.Request["Codes"];
- }
- public Int32 GetPageSize(HttpContext context)
- {
- try
- {
- return Int32.Parse(context.Request["rows"].ToString());
- }
- catch
- {
- return 10;
- }
- }
- public Int32 GetPageIndex(HttpContext context)
- {
- try
- {
- return Int32.Parse(context.Request["page"].ToString());
- }
- catch
- {
- return 1;
- }
- }
- public String GetRoleName(HttpContext context)
- {
- return context.Request["RoleName"];
- }
- #endregion
- }
- #region jquery easyUI專用帶返回總數分頁存儲過程
- /**
- USE [Roles]
- GO
- -- Object: StoredProcedure [dbo].[AspNetPage] by guyongqing52' Script Date: 12/04/2012 11:38:50
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- ALTER procedure [dbo].[AspNetPage]
- @tblName varchar(1000), -- 表名
- @SelectFieldName varchar(4000), -- 要顯示的字段名(不要加select)
- @strWhere varchar(4000), -- 查詢條件(注意: 不要加 where)
- @OrderFieldName varchar(255), -- 排序索引字段名
- @PageSize int , -- 頁大小
- @PageIndex int = 1, -- 頁碼
- @iRowCount int output, -- 返回記錄總數
- @OrderType bit = 0 -- 設置排序類型, 0 值則升序,1爲降序
- AS
- declare @strSQL varchar(4000) -- 主語句
- declare @strTmp varchar(4000) -- 臨時變量
- declare @strOrder varchar(400) -- 排序類型
- declare @strRowCount nvarchar(4000) -- 用於查詢記錄總數的語句
- --去掉排序字段的空格
- set @OrderFieldName=ltrim(rtrim(@OrderFieldName))
- --如果降序
- if @OrderType != 0
- begin
- set @strTmp = '<(select min'
- set @strOrder = ' order by ' + @OrderFieldName +' desc'
- end
- --如果升序
- else
- begin
- set @strTmp = '>(select max'
- set @strOrder = ' order by ' + @OrderFieldName +' asc'
- end
- --查詢主語句
- set @strSQL = 'select top ' + str(@PageSize) + @SelectFieldName+' from ' + @tblName + ' where ' + @OrderFieldName + @strTmp + '('
- + right(@OrderFieldName,len(@OrderFieldName)-charindex('.',@OrderFieldName)) + ') from (select top ' + str((@PageIndex-1)*@PageSize)
- + @OrderFieldName + ' from ' + @tblName + @strOrder + ') as tblTmp)' + @strOrder
- --如果條件不爲空
- if @strWhere != ''
- set @strSQL = 'select top ' + str(@PageSize) + @SelectFieldName+' from ' + @tblName + ' where ' + @OrderFieldName + @strTmp + '('
- + right(@OrderFieldName,len(@OrderFieldName)-charindex('.',@OrderFieldName)) + ') from (select top ' + str((@PageIndex-1)*@PageSize)
- + @OrderFieldName + ' from ' + @tblName + ' where ' + @strWhere + ' ' + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
- --如果頁面爲1
- if @PageIndex = 1
- begin
- set @strTmp = ''
- if @strWhere != ''
- set @strTmp = ' where ' + @strWhere
- set @strSQL = 'select top ' + str(@PageSize) + @SelectFieldName+' from ' + @tblName + @strTmp + ' ' + @strOrder
- end
- --執行語句
- exec(@strSQL)
- --如果條件不爲空
- if @strWhere!=''
- begin
- set @strRowCount = 'select @iRowCount=count(*) from ' + @tblName+' where '+@strWhere
- end
- else
- begin
- set @strRowCount = 'select @iRowCount=count(*) from ' + @tblName
- end
- --執行語句
- exec sp_executesql @strRowCount,N'@iRowCount int out',@iRowCount out
- **/
- #endregion
這樣基本上就完成了,看下再這幾個效果,說不定會有意外的收穫.
這個圖說明easyUi gridview本身就有鼠標經過每行裏自動改變背景色的功能,
這個圖有點類似extjs的分頁功能,說明它具有分頁大小可以根據下列表形式選擇,很不錯的功能.
這個圖片說明列寬拖動也是自帶的,哈哈,真不錯哦再看下面
這個圖充分說明了我們前面固定前面的兩例保持不變
後面的項可以滾動,這項有時候很實用.其實還有很多不錯的功能,比如說列寬自適應,數據可以格式化,列可以編緝,可以增加下列選擇項列等等,這裏不詳細介紹了
下面我們看看網上很多站點使用的很炫列支持拖動,
easyui gridview本身是不支持列拖動的,但是UI裏面卻有可支持拖動的方法,詳情請參見文檔
網上有文章這樣寫的,
- <script type="text/javascript">
- var cols = [{ field: 'testName', title: '<span class="dropitem">測試名</span>', align: 'center',width:120 },
- { field: 'testValue', title: '<span class="dropitem">測試值</span>', align: 'center', width: 120}];
- var url="/Test/Test1Data";
- $(document).ready(function () {
- init();
- drag();//綁定datagrid,綁定拖拽
- });
- function init() {
- $("#test").datagrid({
- url: url,
- type: "post",
- datatype: "json",
- width: 600,
- height: 280,
- loadMsg: "數據加載中,請稍後...",
- nowrap: true,
- rownumbers: false,
- pagination: true,
- singleSelect: true,
- columns: [cols],
- //bind數據成功重新設置拖動對象
- onLoadSuccess: function (data) {
- drag();
- }
- });
- }
- //拖動drag和drop都是datagrid的頭的datagrid-cell
- function drag() {
- $('.datagrid-header-inner .datagrid-cell').draggable({
- revert: true,
- proxy: 'clone'
- }).droppable({
- accept: '.datagrid-header-inner .datagrid-cell',
- onDrop: function (e, source) {
- //取得拖動源的html值
- var src = $(e.currentTarget.innerHTML).html();
- //取得拖動目標的html值
- var sou = $(source.innerHTML).html();
- var tempcolsrc;//拖動後源和目標列交換
- var tempcolsou;
- var tempcols=[];
- for (var i = 0; i < cols.length; i++) {
- if (cols[i].title == sou) {
- tempcolsrc = cols[i];//循環讀一遍列把源和目標列都記下來
- }
- else if (cols[i].title == src) {
- tempcolsou = cols[i];
- }
- }
- for (var i = 0; i < cols.length; i++) {
- //再循環一遍,把源和目標的列對換
- var col = {
- field: cols[i].field,
- title: cols[i].title,
- align: cols[i].align,
- width: cols[i].width
- };
- if (cols[i].title == sou) {
- col = tempcolsou;
- }
- else if (cols[i].title == src) {
- col = tempcolsrc;
- }
- tempcols.push(col);
- }
- cols = tempcols;
- //1秒後執行重綁定datagrid操作。可能是revert需要時間,這邊如果沒有做延時就直接重綁 就會出錯。
- //我目前的水平就想到這個笨辦法,各位如果有好的想法建議可以提出來討論下。
- timeid = setTimeout("init()", 1000);
- }
- });
- }
- </script>
- <div id="test"></div>
感覺這個人寫的很不錯,思路很清淅,但是這個方法我沒有采用,因爲不宜擴展,這裏還得謝謝上面提供的思路.
下面看擴展方法
- $(function () {
- //-以下是擴展移動方法
- $.extend($.fn.datagrid.methods, {
- columnMoving: function (jq) {
- return jq.each(function () {
- var target = this;
- var cells = $(this).datagrid('getPanel').find('div.datagrid-header td[field]');
- cells.draggable({
- revert: true,
- cursor: 'pointer',
- edge: 5,
- proxy: function (source) {
- var height = $(source).height();
- var width = $(source).width() - 20;
- var bordercolor = $(source).css("background-color");
- var p = $('<div class="tree-node-proxy tree-dnd-no" style="position:absolute;border:1px solid ' + bordercolor + '"/>').appendTo('body');
- p.css({ "background-color": bordercolor });
- p.html($(source).text());
- p.height(height);
- p.width(width);
- p.hide();
- return p;
- },
- onBeforeDrag: function (e) {
- e.data.startLeft = $(this).offset().left;
- e.data.startTop = $(this).offset().top;
- },
- onStartDrag: function () {
- $(this).draggable('proxy').css({
- left: -10000,
- top: -10000
- });
- },
- onDrag: function (e) {
- $(this).draggable('proxy').show().css({
- left: e.pageX - 30,
- top: e.pageY - 5
- });
- return false;
- }
- }).droppable({
- accept: 'td[field]',
- onDragOver: function (e, source) {
- $(source).draggable('proxy').removeClass('tree-dnd-no').addClass('tree-dnd-yes');
- $(this).css('border-left', '1px solid #ff0000');
- var left = $(this).offset().left -5;
- var top1 = $(this).offset().top - 10;
- var top2 = $(this).offset().top +24;
- var pgb1 = $('<div id="guang1" style="position:absolute; index-z:888888;background:#fff url(img/guangbiao1.gif) no-repeat 0 0;width:10px;height:8px"></div>').appendTo('body');
- var pgb2 = $('<div id="guang2" style="position:absolute; index-z:888888;background:#fff url(img/guangbiao2.gif) no-repeat 0 0;width:12px;height:12px"></div>').appendTo('body');
- pgb1.css({ "top": top1, "left": left });
- pgb2.css({ "top": top2, "left": left });
- },
- onDragLeave: function (e, source) {
- $(source).draggable('proxy').removeClass('tree-dnd-yes').addClass('tree-dnd-no');
- $(this).css('border-left', 0);
- $("body #guang1").hide();
- $("body #guang2").hide();
- },
- onDrop: function (e, source) {
- $(this).css('border-left', 0);
- $("body #guang1").hide();
- $("body #guang2").hide();
- var fromField = $(source).attr('field');
- var toField = $(this).attr('field');
- setTimeout(function () {
- moveField(fromField, toField);
- $(target).datagrid();
- $(target).datagrid('columnMoving');
- }, 0);
- }
- });
- // move field to another location
- function moveField(from, to) {
- var columns = $(target).datagrid('options').columns;
- var cc = columns[0];
- var c = _remove(from);
- if (c) {
- _insert(to, c);
- }
- function _remove(field) {
- for (var i = 0; i < cc.length; i++) {
- if (cc[i].field == field) {
- var c = cc[i];
- cc.splice(i, 1);
- return c;
- }
- }
- return null;
- }
- function _insert(field, c) {
- var newcc = [];
- for (var i = 0; i < cc.length; i++) {
- if (cc[i].field == field) {
- newcc.push(c);
- }
- newcc.push(cc[i]);
- }
- columns[0] = newcc;
- }
- }
- });
- }
- });
調用的時候只要在後面加上$('#roleList').datagrid({...}).datagrid("columnMoving");這句就行了,怎麼樣,簡單吧,還有聽過幾位網友的說,把拖動的時候上下指示箭頭做成閃動的效果更好些,這些細節這裏不作多解釋,好了就寫到這吧,祝使用asp.net C#語言的人能夠參考,
轉載請註明原出處!http://blog.csdn.net/guyongqing52/article/details/7833211