原创|其它|编辑:郝浩|2009-09-27 10:50:10.000|阅读 1974 次
概述:Ext4JSLint是使用ExtAspNet来展示JSLint-Toolkit检查结果的开源项目。 JSLint-Toolkit是一个使用Rhino和JSLint的开源项目,可以对一个文件夹中的所有JavaScript进行语法检查,并显示友好的检查结果。
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
界面截图
页面加载后,Grid默认按照“时间”倒序排列:
点击“时间”标题栏,改变排序:
改变其它列的排序:
如果没有选中任一项纪录时就点击“删除选中纪录”,会有客户端提示:
删除记录前会有Confirm确认对话框,注意这里对选中的数目采用红色粗体字,等会可以关注下实现:
查看详细信息页面:
Grid标签定义
01.
<
ext:Grid
ID
=
"Grid1"
runat
=
"server"
AnchorValue
=
"100% -36px"
ShowBorder
=
"true"
ShowHeader
=
"false"
02.
EnableCheckBoxSelect
=
"true"
EnableRowNumber
=
"true"
DataKeyNames
=
"Logid"
AllowSorting
=
"true"
03.
OnSort
=
"Grid1_Sort"
AllowPaging
=
"true"
IsDatabasePaging
=
"true"
OnPageIndexChange
=
"Grid1_PageIndexChange"
>
04.
<
Toolbars
>
05.
<
ext:Toolbar
ID
=
"Toolbar1"
runat
=
"server"
>
06.
<
Items
>
07.
<
ext:Button
ID
=
"btnDeleteSelected"
runat
=
"server"
Text
=
"删除选中记录"
OnClick
=
"btnDeleteSelected_Click"
>
08.
</
ext:Button
>
09.
</
Items
>
10.
</
ext:Toolbar
>
11.
</
Toolbars
>
12.
<
Columns
>
13.
<
ext:BoundField
DataField
=
"DatetimeX"
SortField
=
"DatetimeX"
DataFormatString
=
"{0:yyyy-MM-dd HH:mm:ss}"
14.
Width
=
"120px"
HeaderText
=
"时间"
/>
15.
<
ext:BoundField
DataField
=
"LogLevel"
SortField
=
"LogLevel"
Width
=
"50px"
HeaderText
=
"级别"
/>
16.
<
ext:BoundField
DataField
=
"Logger"
SortField
=
"Logger"
Width
=
"100px"
HeaderText
=
"源"
/>
17.
<
ext:BoundField
DataField
=
"Message"
ExpandUnusedSpace
=
"true"
HeaderText
=
"错误信息"
/>
18.
<
ext:BoundField
DataField
=
"Exception"
Width
=
"200px"
HeaderText
=
"异常信息"
/>
19.
<
ext:WindowField
Text
=
"查看"
Title
=
"查看"
WindowID
=
"Window1"
DataIFrameUrlFields
=
"Logid"
20.
DataIFrameUrlFormatString
=
"~/admin/log_view.aspx?id={0}"
Width
=
"50px"
/>
21.
</
Columns
>
22.
</
ext:Grid
>
btnDeleteSelected的客户端脚本
不用担心,这里不是让大家来写JavaScript,而是调用ExtAspNet定义好的方法。
01.
protected void Page_Load(object sender, EventArgs e)
02.
{
03.
if
(!IsPostBack)
04.
{
05.
LoadData();
06.
}
07.
}
08.
private void LoadData()
09.
{
10.
// 默认的排序列和排序方向
11.
Grid1.CurrentSortColumnIndex = 0;
12.
Grid1.Columns[0].SortDirection =
"DESC"
;
13.
// 每页记录数
14.
Grid1.PageSize = XConfigHelper.PageSize;
15.
// 点击删除按钮时,至少选中一项
16.
btnDeleteSelected.OnClientClick = Grid1.GetNoSelectionAlertInParentReference(
"至少选中一项!"
);
17.
btnDeleteSelected.ConfirmTarget =
"_parent"
;
18.
btnDeleteSelected.ConfirmText = String.Format(
"确定要删除 <span style=\"color:red;font-weight:bold;\"><script>{0}</script></span> 项纪录吗?"
, Grid1.GetSelectCountReference());
19.
BindGrid();
20.
}
我们重点来看下为按钮添加删除之前的确认提醒,去除其中为选中数添加样式的部分,精简后的代码如下:
1.
btnDeleteSelected.ConfirmText = String.Format(
"确定要删除 <script>{0}</script> 项纪录吗?"
, Grid1.GetSelectCountReference());
这里ExtAspNet会自动查找ConfirmText字符串中<script></script>的部分,并生成正确的JavaScript代码。
如果你打开页面源代码的话,你会发现上面简单的两句C#代码的调用被转化为复杂的JS函数,而这一切都是ExtAspNet已经封装好的:
当有人ExtAspNet能给我们带来什么好处时,我经常会说ExtAspNet让Web2.0开发变得简单。
ExtAspNet尽量把一些常见的任务封装起来,呈现在程序员面前的是最佳实践的调用方法,这样就不必每个人都重新实现了。
当然,ExtAspNet不是万能的,我们的设计初衷就是能够覆盖80%以上应用场景的快速开发。
因此如果你觉得ExtAspNet中缺少什么特性的话,尽管发信给我,我会在评估不会增加ExtAspNet复杂度的前提下增加这些特性。
排序,数据库分页与SubSonic
1. 如果要使用Grid排序,必须满足如下条件:
2. 如果使用Grid的数据库分页,必须满足如下条件:
3. SubSonic支持数据库分页,非常方便:
需要注意的是,SubSonic的分页是从1开始的,而ExtAspNet中Grid的PageIndex是从0开始的。
现在看一下BindGrid的完整代码:
01.
private
void
BindGrid()
02.
{
03.
SqlQuery q =
new
Select().From<XLog>();
04.
q.Where(
"1"
).IsEqualTo(
"1"
);
05.
// 在错误信息中搜索
06.
string
searchText = ttbSearchMessage.Text.Trim();
07.
if
(!String.IsNullOrEmpty(searchText))
08.
{
09.
q.And(XLog.MessageColumn).ContainsString(searchText);
10.
}
11.
// 过滤错误级别
12.
if
(ddlSearchLevel.SelectedValue !=
"ALL"
)
13.
{
14.
q.And(XLog.LogLevelColumn).IsEqualTo(ddlSearchLevel.SelectedValue);
15.
}
16.
// 过滤搜索范围
17.
if
(ddlSearchRange.SelectedValue !=
"ALL"
)
18.
{
19.
DateTime today = DateTime.Parse(DateTime.Now.ToString(
"yyyy-MM-dd"
));
20.
switch
(ddlSearchRange.SelectedValue)
21.
{
22.
case
"TODAY"
:
23.
q.And(XLog.DatetimeXColumn).IsGreaterThanOrEqualTo(today);
24.
break
;
25.
case
"LAST3DAYS"
:
26.
q.And(XLog.DatetimeXColumn).IsGreaterThanOrEqualTo(today.AddDays(-3));
27.
break
;
28.
case
"LAST7DAYS"
:
29.
q.And(XLog.DatetimeXColumn).IsGreaterThanOrEqualTo(today.AddDays(-7));
30.
break
;
31.
case
"LASTMONTH"
:
32.
q.And(XLog.DatetimeXColumn).IsGreaterThanOrEqualTo(today.AddMonths(-1));
33.
break
;
34.
case
"LASTYEAR"
:
35.
q.And(XLog.DatetimeXColumn).IsGreaterThanOrEqualTo(today.AddYears(-1));
36.
break
;
37.
}
38.
}
39.
// 在查询添加之后,排序和分页之前获取总记录数
40.
// Grid1总共有多少条记录
41.
Grid1.RecordCount = q.GetRecordCount();
42.
// 排列
43.
q.OrderBys.Add(GetSortExpression(Grid1, XLog.Schema));
44.
// 数据库分页
45.
q.Paged(Grid1.PageIndex + 1, Grid1.PageSize);
46.
XLogCollection logs = q.ExecuteAsCollection<XLogCollection>();
47.
Grid1.DataSource = logs;
48.
Grid1.DataBind();
49.
}
其实这里面进行了两次数据库查询,第一次在Grid1.RecordCount = q.GetRecordCount();,第二次是查询XLogCollection logs集合。
这段代码其实隐藏了很多应用技巧,我会一一列出:
1. q.And(XLog.MessageColumn).ContainsString(searchText);
这个是用来在Message字段中查找包含searchText文本的记录,如果使用SqlServer数据库,这段代码等价于:
1.
q.And(XLog.MessageColumn).Like(String.Format(
"%{0}%"
, searchText));
从这一点也可以看到SubSonic考虑的很周全,其实ContainsString这个函数是兼容多种数据库的。
2. q.Where("1").IsEqualTo("1");
可能有些网友就觉得奇怪了,为什么要加上这段奇怪的代码。
这是为了防止查询中缺少Where子句,也防止查询中有多个Where子句而导致SubSonic解析错误。
这也类似于我们这些写SQL语句:select * from Log where 1=1 and .....
3. Grid1.RecordCount = q.GetRecordCount();这句话的摆放位置
这是很有讲究的,它应该放在添加查询条件之后,排序和分页之前。这是获取总记录数的SQL语句效率才高。
不过或者SubSonic本身做了优化,GetRecordCount时忽略排序的SQL子句也说不定。
4. q.OrderBys.Add(GetSortExpression(Grid1, XLog.Schema));
我们就来看看定义在PageBase中的GetSortExpression的声明:
01.
protected
string
GetSortExpression(ExtAspNet.Grid grid, TableSchema.Table schema)
02.
{
03.
ExtAspNet.GridColumn column = grid.Columns[grid.CurrentSortColumnIndex];
04.
string
columnName = GetTableColumnName(schema, column.SortField);
05.
return
String.Format(
"{0} {1}"
, columnName, column.SortDirection);
06.
}
07.
protected
string
GetTableColumnName(TableSchema.Table table,
string
propertyName)
08.
{
09.
foreach
(TableSchema.TableColumn column
in
table.Columns)
10.
{
11.
if
(column.PropertyName == propertyName)
12.
{
13.
return
column.ColumnName;
14.
}
15.
}
16.
return
String.Empty;
17.
}
可见GetSortExpression也就是根据当前排序的列CurrentSortColumnIndex来生成排序SQL子句而已。
GetTableColumnName是做啥的?
可能另一个函数 GetTableColumnName 更让大家迷惑,它的作用是将 column.SortField 转化为数据库列的名称。
有网友就问了:column.SortField 不就是 数据库列的名称 吗?
------------不是这样的!
我们都知道SubSonic这类的工具有一个通用的名称是ORM,也就是Object Releation Mapping(对象与关系数据库的映射)。
SubSonic会将数据库表的列映射为C#实体类的属性,比如messgage映射为Message,user_name映射为UserName,而DateTime则被映射为DateTimeX,这是为了防止和C#的关键字冲突。
所以你看我们在声明Grid列的时候:
1.
<
ext:BoundField
DataField
=
"DatetimeX"
SortField
=
"DatetimeX"
DataFormatString
=
"{0:yyyy-MM-dd HH:mm:ss}"
2.
Width
=
"120px"
HeaderText
=
"时间"
/>
对比下数据库中的定义:
而GetTableColumnName正是为了将实体类的属性(DateTimeX)转化为数据库的列名称(DateTime)。
批量删除,翻页与排序
01.
protected
void
btnDeleteSelected_Click(
object
sender, EventArgs e)
02.
{
03.
// 从每个选中的行中获取Logid(在Grid1中定义的DataKeyNames)
04.
List<
int
> logids =
new
List<
int
>();
05.
foreach
(
int
rowIndex
in
Grid1.SelectedRowIndexArray)
06.
{
07.
logids.Add(Convert.ToInt32(Grid1.DataKeys[rowIndex][0]));
08.
}
09.
// 执行数据库操作
10.
new
Delete().From<XLog>()
11.
.Where(XLog.LogidColumn).In(logids)
12.
.Execute();
13.
// 清空当前选中的项
14.
Grid1.SelectedRowIndexArray =
null
;
15.
// 重新绑定表格
16.
BindGrid();
17.
}
18.
19.
protected
void
Grid1_Sort(
object
sender, ExtAspNet.GridSortEventArgs e)
20.
{
21.
Grid1.CurrentSortColumnIndex = e.ColumnIndex;
22.
BindGrid();
23.
}
24.
protected
void
Grid1_PageIndexChange(
object
sender, ExtAspNet.GridPageEventArgs e)
25.
{
26.
Grid1.PageIndex = e.NewPageIndex;
27.
BindGrid();
28.
}
至此,日志管理模块已经介绍完毕。下一章开始我们将关注用户权限管理方面的实现。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn
文章转载自:博客园