Telerik RadGrid AJAX更新範例
8 | 31,427 |
RadControls for ASP.NET AJAX是一套挺優秀的ASP.NET元件庫,包辦了開發ASP.NET專案時需要用到的大小控制項(如: Grid、日期選擇器、數字輸入欄位、頁籤... 等等),手上有幾個專案裡就是利用RadGrid的Client-Side Data-Binding實現AJAX式的換頁及重排效果,但中年人記憶消失之快已到了令人心驚的地步,每次要寫類似應用都要花上大半天回頭從舊程式找範例(要命的是連在哪個專案寫過都要想半天),於是催生了這篇"銀杏文"。
RadGridAjaxSample.aspx
排版顯示純文字
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="RadGridAjaxSample.aspx.cs"
Inherits="RadGridAjaxSample" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>RadGrid AJAX Sample</title>
<style>
body,input { font-size: 9pt; }
span.hi-lite { color: red; }
</style>
<script type="text/javascript"
src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.js"> </script>
<script>
function dataBinding(sender, args) {
//取得要傳給WebMethod的參數
var params = args.get_methodArguments();
//透過$.extend()加上自訂參數
$.extend(params, { "keywd": $("#tKeyword").val() });
}
function dataBound(sender, args) {
//AJAX資料Bind完成後觸發
var kw = $("#tKeyword").val();
//若有設關鍵字,做Highlight處理
if (kw.length > 0) {
var re = new RegExp(kw, "g");
$(".u-name").each(function () {
var $td = $(this);
$td.html($td.text()
.replace(re, "<span class='hi-lite'>$&</span>"));
});
}
}
$(function () {
//示範由前端觸發資料重新查詢
$("#bQuery").click(function () {
$find("RadGrid1").get_masterTableView().rebind();
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div style="padding: 10px;">
關鍵字: <input id="tKeyword" /><input type="button" value="查詢" id="bQuery" />
</div>
<telerik:RadGrid ID="RadGrid1" runat="server" Width="400px"
AutoGenerateColumns="False" CellSpacing="0" GridLines="None" AllowPaging="True"
AllowSorting="true" PageSize="10">
<MasterTableView>
<Columns>
<telerik:GridBoundColumn HeaderText="會員編號"
DataField="UserNo" UniqueName="UserNo">
<HeaderStyle Width="100px" />
</telerik:GridBoundColumn>
<telerik:GridBoundColumn HeaderText="會員名稱"
DataField="UserName" UniqueName="UserName">
<HeaderStyle Width="100px" />
<ItemStyle CssClass="u-name" />
</telerik:GridBoundColumn>
<telerik:GridBoundColumn HeaderText="加入日期" DataField="RegDate"
UniqueName="RegDate" DataFormatString="{0:yyyy/MM/dd}">
<HeaderStyle Width="100px" />
</telerik:GridBoundColumn>
<telerik:GridBoundColumn HeaderText="累積點數"
DataField="Points" UniqueName="Points" DataFormatString="{0:N0}">
<HeaderStyle Width="100px" />
<ItemStyle HorizontalAlign="Right" />
</telerik:GridBoundColumn>
</Columns>
</MasterTableView>
<AlternatingItemStyle HorizontalAlign="Center" />
<HeaderStyle HorizontalAlign="Center" />
<ItemStyle HorizontalAlign="Center" />
<FilterMenu EnableImageSprites="False">
</FilterMenu>
<HeaderContextMenu CssClass="GridContextMenu GridContextMenu_Default">
</HeaderContextMenu>
<ClientSettings>
<DataBinding Location="RadGridAjaxSample.aspx" SelectMethod="GetData">
</DataBinding>
<ClientEvents OnDataBinding="dataBinding" OnDataBound="dataBound" />
</ClientSettings>
</telerik:RadGrid>
</form>
</body>
</html>
[說明]
- 透過DataBinding指定呼叫RadGridAjaxSample.aspx的GetData WebMethod讀取資料(也可寫成一般ASHX,但要自己由POST內容解析取出分頁、篩選參數,要花點功)
- function dataBinding會在AJAX取資料前觸發,在此示範如何帶入額外參數(關鍵字查詢)
- function dataBound會在AJAX取回資料並Bind到HTML表格後觸發,在此示範用jQuery將會員名稱欄位出現的關鍵字標為紅字
- 要由Client端觸重新查詢的寫法為: $find("RadGrid1").get_masterTableView().rebind();
($find是ASP.NET AJAX的Client端函數,Telerik的這套元件仍以ASP.NET AJAX為基礎,到了MVC版本才是以jQuery為底)
後端程式RadGridAjaxSample.aspx.cs
排版顯示純文字
using System;
using System.Collections.Generic;
using System.Linq;
using Telerik.Web.UI;
using System.Web.Services;
using System.Drawing;
using System.Reflection;
public partial class RadGridAjaxSample : System.Web.UI.Page
{
//模擬資料物件
public class SimMemberInfo
{
public string UserNo; //會員編號
public string UserName; //會員名稱
public DateTime RegDate; //註冊日期
public int Points; //累積點數
}
//查詢結果,包含資料物件集合(已分頁)以及總筆數
public class RadGridQueryResult<T>
{
public int TotalCount;
public List<T> Items;
}
static List<SimMemberInfo> _SimuDataStore = null;
//模擬對資料庫進行關鍵字查詢,並依要求分頁及排序
public static RadGridQueryResult<SimMemberInfo>
QuerySimuData(string keywd, int stPos, int count, string sortBy)
{
if (_SimuDataStore == null)
{
Random rnd = new Random();
//借用具名顏色名稱來產生隨機資料
string[] colorNames =typeof(Color)
.GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(o => o.Name).ToArray();
_SimuDataStore =
colorNames
.Select(cn => new SimMemberInfo()
{
UserNo = string.Format("C{0:00000}", rnd.Next(99999)),
UserName = cn,
RegDate = DateTime.Today.AddDays(- rnd.Next(1000)),
Points = rnd.Next(9999)
}).ToList();
}
//指定關鍵字時,使用Contains()對UserName進行比對
var q = _SimuDataStore.Where(o =>
string.IsNullOrEmpty(keywd) || o.UserName.Contains(keywd));
if (!string.IsNullOrEmpty(sortBy))
{
//宣告一個函數可傳回SimMemberInfo之指定屬性值用於依動態欄位排序
Func<SimMemberInfo, string, string> GetColString =
(o, c) =>
{
switch(c)
{
case "UserNo": return o.UserNo;
case "UserName": return o.UserName;
case "RegDate": return o.RegDate.ToString("yyyyMMdd");
case "Points": return o.Points.ToString();
default: throw new ArgumentException();
}
};
//sortBy格式為ColName ASC或ColName DESC
string[] p = sortBy.Split(' ');
if (p[1] == "ASC")
q = q.OrderBy(o => GetColString(o, p[0]));
else
q = q.OrderByDescending(o => GetColString(o, p[0]));
}
return new RadGridQueryResult<SimMemberInfo>()
{
TotalCount = q.Count(),
Items = q.Skip(stPos).Take(count).ToList()
};
}
[WebMethod()]
public static Dictionary<string, object> GetData(
//前四個參數是RadGrid制式要求,分別為: 起始筆數、每頁筆數、排序設定、篩選設定
int startRowIndex, int maximumRows, List<GridSortExpression> sortExpression,
List<GridFilterExpression> filterExpression,
//若前端用args.get_methodArguments()加入額外參數,在此要宣告參數接收
string keywd)
{
Dictionary<string, object> data = new Dictionary<string, object>();
//取得排序參數(只實做支援單欄排序)
GridSortExpression gse = sortExpression.FirstOrDefault();
string sortBy = gse != null ?
string.Format("{0} {1}", gse.FieldName, gse.SortOrderAsString()) : "";
//模擬呼叫資料庫進行查詢(傳入關鍵字、分頁參數及排序欄位)
var res = QuerySimuData(keywd, startRowIndex, maximumRows, sortBy);
data.Add("Data", res.Items);
data.Add("Count", res.TotalCount);
return data;
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
[說明]
- 為了簡化起見,沒動用資料庫,只自訂了SimMemberInfo類別模擬資料物件,並以隨機方式產生模擬資料(我用Color.Red等具名顏色來當作會員名稱,很有創意吧!)
- WebMethod GetData要接入int startRowIndex, int maximumRows, List<GridSortExpression> sortExpression, List<GridFilterExpression> filterExpression等參數,傳回經篩選(本範例中未實做)、分好頁、排序過的資料集合,同時要回報總筆數。
- GetData的keywd參數是前端function dataBinding()時額外加傳的
- QuerySimuData中動了點手腳(透過GetColString函數)實現動態指定排序欄位,這在不同資料來源時玩法不同 (2014-04-28 範例中一律將欄位轉為字串排序,故會出現134比1234大的不合理結果,有Bug待修)
以下為執行畫面:
由於配合Telerik元件才能執行,大家不一定能立即在自己的機器上試用,所以我準備了一個線上展示,有興趣的人可以看看。
Comments
# by 謝謝分享
謝謝分享,每看一篇文章就覺得自己成長了一些@@ 這套元件還真貴,雖然蠻強大的 囧
# by Miller
感謝分享,每次看您的教學,都受益良多。 抱歉,最近也剛好注意到這套元件,請問您是直接在網路下單,還是台灣有經銷商可以購買? 謝謝~
# by Jeffrey
to Miller, 我們是直接網路刷卡下單取得授權序號,客服支援則透過官方網站或電子郵件管道取得(英文),回應速度挺快的。 現在有很多軟體(尤其是元件類)只走網路銷售,會計部門應該已認命接受才對(呵);若採購部門堅持要發票方能報帳,國內似乎也有代理廠商能代購Telerik,用Telerik+經銷查查不難找到。
# by Miller
To Jeffrey, 非常感謝您的經驗分享與建議,很幸運,公司的採購願意協助購買,下載試用版試用中 ︿ ︿
# by Haw
線上展示的累積點數排序怪怪的, 剛好看到,通知您一聲
# by Jeffrey
to Haw, 謝謝回饋,程式將數字轉成字串後比對,因而形成134比1234大的不合理情況,應轉成數字再比較才合理。先加註在文中,日後再找時間修正。
# by mark
黑大 您好 我常常拜讀您的文章 您的文章非常受用 感謝您的無私分享 線上展示 沒有分頁的時候 細項有部份查詢關鍵字不會反紅
# by Jeffrey
to mark, 沒分頁是指筆數不足一頁的狀況嗎?測試Gray有反紅( http://i.imgur.com/WYnGpOb.gif?1 ),可否提供你的測試案例我查查?