导航
.NET实现DWZ富客户端框架 <一> 前言概要
.NET实现DWZ富客户端框架<一.1> WebForm中使用DWZ之建立项目
前言
本文主要是对.net在使用dwz富客户端的一些经验总结。主要的内容有:
- 列表的分页,批量删除
- 表单验证,提交与提示
项目的结构说明
项目名称为:药监局诚信管理系统(托大的)
_ReSharper.yjjWeb:这个是ReSharper插件生成的文件,与项目无关,没用过可以用用,最喜欢它的重构代码,让我知道我又写出了烂代码。
App_Code:SysHelper系统类,存放一些系统操作代码。WebHelper一些Web中使用的代码。来源已经不清,感谢作者!
DrugStoreAssessment:药店管理模块。其中
GradeManage:评分模块
SysManage:系统模块
images:存放一些非dwz的照片。
javascripts:除了dwz的js,还下载了一个CLEditor的Html编辑器。
themes:图片和css文件。即dwz的皮肤文件。
数据操作说明
不合适使用服务端控件数据交互!
dwz的框架是以jquery组件形式搭建而成。基本上就是以Html与js来输出页面的。服务端控件基本上没有了数据交互的价值。因为一旦服务端事件触发,表单开始回传,那么整个页面即将面临刷新,所有的html与javascript需要重新载入(但浏览器有缓存,这里可能没有重新回传。整个以jquery搭建的组件界面需要重新载入构建。
但如果依然想使用服务端控件,就我所知的方法:
- 使用iframe。在页面内签入页面,当然就不会刷新整个主页面(问题是内嵌页面是没有js与css的)
- 使用asp.net的ScriptManager。这是我最开始的想法。后来发现,服务端控件好像没啥用,没地方放…
这里需要说明,无法回传但我们可以使用数据输出的服务端控件。使用Repeater为主要数据输出控件。
那如何进行数据交互?
主要是通过dwz的ajax表单与jquery的ajax进行数据交互。用服务端做第一次输入,整个项目没有IsPostBack。该项目使用ajax直接与aspx进行输入交互。但我不是使用aspx页面,而是通过ashx文件进行交互。ashx可以说是没有html的aspx。虽然它主要是cs代码构成。但奇怪的是它可以运行是编辑。可见还是个页面。
当然还有其它方法:Webserver,WCF都可以用于数据交互。
列表的分页,批量删除
前台效果图:药房列表
有点像ext,比较清爽,个人比较喜欢,而jquery ui 看着怪怪的
DrugStoreList.aspx 页面代码
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DrugStoreList.aspx.cs" Inherits="DrugStoreAssessment_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="pagerForm" method="post" action="DrugStoreAssessment/DrugStoreList.aspx"> <input type="hidden" name="status" value="status" /> <input type="hidden" name="keywords" value="keywords" /> <input type="hidden" name="numPerPage" value="<% =NumPerPage %>" /> <input type="hidden" name="pageNum" value="1" /> <input type="hidden" name="orderField" value="" /> </form> <div class="pageHeader"> <!--<搜索栏>--> <form onsubmit="return navTabSearch(this);" action="DrugStoreAssessment/DrugStoreList.aspx" method="post"> <div class="searchBar"> <ul class="searchContent"> <li> <label>模糊搜索:</label> <input name="keyString" type="text" value="<%=keyString %>"/> </li> </ul> <div class="subBar"> <ul> <li><div class="buttonActive"><div class="buttonContent"><button type="submit">检索</button></div></div></li> <!-- <li><a class="button" href="demo_page6.html" target="dialog" rel="dlg_page1" title="查询框"><span>高级检索</span></a></li>--> </ul> </div> </div> </form> <!--</搜索栏>--> </div> <div class="pageContent"> <div class="panelBar"> <ul class="toolBar"> <li> <a class="add" target="dialog" href="DrugStoreAssessment/DrugStoreAdd.aspx"> <span>添加药房</span> </a> </li> <li> <a class="delete" href="DrugStoreAssessment/DrugStoreHandler.ashx?title=delete" posttype="string" rel="ids" target="selectedTodo" title="确实要删除这些记录吗?"> <span>批量删除</span> </a> </li> <li class="line">line</li> <li><a class="icon" href="javascript:void(0);"><span>导入EXCEL</span></a></li> </ul> </div> <table class="table" width="100%" layoutH="138"> <thead> <tr> <th width="22"><input type="checkbox" group="ids" class="checkboxCtrl"></th> <th width="40" class="asc">ID</th> <th width="80">名称</th> <th width="120">详细地址</th> <th width="80" >负责人</th> <th width="100">开办时间</th> <th width="100" align="center" orderField="accountLevel">最后评估时间</th> <th width="70">操作</th> </tr> </thead> <tbody> <asp:Repeater ID="RepeaterTr" runat="server"> <ItemTemplate> <tr > <td><input name="ids" type="checkbox" value=<%#DataBinder.Eval(Container.DataItem, "DrugStoreID")%> /></td> <td> <%# DataBinder.Eval(Container.DataItem, "DrugStoreID")%> </td> <td> <%# DataBinder.Eval(Container.DataItem, "Name")%> </td> <td> <%# DataBinder.Eval(Container.DataItem, "Address")%> </td> <td> <%# DataBinder.Eval(Container.DataItem, "ResponsiblePerson")%> </td> <td> <%# DataBinder.Eval(Container.DataItem, "GreateDate")%> </td> <td> <%# DataBinder.Eval(Container.DataItem, "LastGradeDate")%> </td> <td> <a title="删除" target="ajaxTodo" href="DrugStoreAssessment/DrugStoreHandler.ashx?title=delete&ids=<%# DataBinder.Eval(Container.DataItem, "DrugStoreID")%>" class="btnDel">删除</a> <a title="编辑" target="dialog" href="DrugStoreAssessment/DrugStoreEdit.aspx?id=<%# DataBinder.Eval(Container.DataItem, "DrugStoreID")%>" class="btnEdit">编辑</a> </td> </tr> </ItemTemplate> </asp:Repeater> </tbody> </table> <div class="panelBar"> <div class="pages"> <span>显示</span> <select class="combox" name="numPerPage" change="navTabPageBreak" param="numPerPage" > <option value="<%=NumPerPage%>">选择</option> <option value="20">20</option> <option value="30">30</option> <option value="50">50</option> <option value="100">100</option> </select> <span>条,共<%=TotalCount%>条</span> </div> <div class="pagination" targetType="navTab" totalCount="<%=TotalCount%>" numPerPage="<%=NumPerPage%>" pageNumShown="<%=PageNumShown%>" currentPage="<%=PageNum%>">"></div> </div> </div> </body> </html>
DrugStoreList.aspx.cs 后台代码
(注:本代码用于演示,如想雷同,定需优化)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class DrugStoreAssessment_Default : System.Web.UI.Page { #region 分页变量,与UI绑定 private int numPerPage; /// <summary> /// 每页显示的条数 /// </summary> public int NumPerPage { get { int temp = Convert.ToInt32(Request.Form["numPerPage"]); return temp == 0 ? 20 : temp; } set { numPerPage = value; } } private int pageNumShown = 10; /// <summary> /// 页数导航的个数 /// </summary> public int PageNumShown { get { return pageNumShown; } set { pageNumShown = value; } } private int pageNum; /// <summary> /// 当前显示的页数 /// </summary> public int PageNum { get { int temp = Convert.ToInt32(Request.Form["pageNum"]); return temp == 0 ? 1 : temp; } set { pageNum = value; } } private int totalCount; /// <summary> /// 总条数 /// </summary> public int TotalCount { get { return totalCount; } set { totalCount = value; } } private string keywords; /// <summary> /// where语句,不加where与空格 /// </summary> public string Keywords { get { string temp = Request.Form["keywords"]; return temp; } set { keywords = value; } } private string orderField; /// <summary> /// 排序关键字 /// </summary> public string OrderField { get { string temp = Request.Form["orderField"]; return temp; } set { orderField = value; } } #endregion public string keyString; protected void Page_Load(object sender, EventArgs e) { bindData(); } /// <summary> /// 数据绑定,同时需要设置数据总条数 /// 当前页与每页条数由页面中的pagerForm回传得到 /// </summary> private void bindData() { keyString = Request.Form["keyString"]; DataYJJDBDataContext dc = new DataYJJDBDataContext(); var List = from ds in dc.DSA_DrugStore orderby ds.DrugStoreID ascending where keyString == null || ds.Name.Contains(keyString) || ds.Address.Contains(keyString) || ds.ResponsiblePerson.Contains(keyString) select ds; TotalCount = List.Count(); RepeaterTr.DataSource = List.Skip((PageNum - 1) * NumPerPage).Take(NumPerPage); RepeaterTr.DataBind(); } }
细说代码:
(提示:可以查看dwz关于列表与分页的说明文档做参考)
这里自上而下的进行说明,前后台结合说明。
此处的html与body标签都可以不需要,因为每个页面都是通过ajax异步读取并加载到主页的一个div中。
隐藏的from
这里是dwz需要提供的一个隐藏form,用于分页,列表的相关属性的页面级的字段。此处的<% =NumPerPage %>是从后台生成当分页列表每页数据行数。后台代码如下:
写成该页面的一个属性。再加载页面的时候复制到前台,但dwz使用jquery构造这个表格的时候就会从隐藏from中读取numPerPage的值。
搜索栏
以下代码生成的就是图片中红色部分的内容。
注意:这里很明显,对于action的路径划上了红色波浪号代表无法搜索到该文件。因为vs2010是从相对路径去查询这个文件的,确实不能找到这个文件。如图,DrugStoreHandler.ashx与DrugStoreList.aspx是一个文件夹下,在DrugStoreList.aspx去搜索应该是action="DrugStoreList.aspx" 就可以了。
但是,我们的页面以后会被无刷新载入Default.aspx页面,也就是说我们应该是从Default.aspx的相对路径去写这个路径。使用dwz一定要理解这一路径问题。
这里的keyString就是模糊搜索的关键字。获取数据使用了linq to sql。如果不知道linq也没关系,简单的说就是获取数据的一个技术。可以使用ado.net执行sql拼接where或存储过程实现也是一样的。
第一个红框:获取从 <input name="keyString" type="text" value="<%=keyString %>"/>传过来的关键字
第二个红框:使用where进行模糊查询,这里是对药店名称,地址,负责人进行包含keyString查询,并生成数据集List用于绑定。
工具条与批量删除:
注意:url地址划红色波浪线的路径问题同上所述。
<a class="add" target="dialog" href="DrugStoreAssessment/DrugStoreAdd.aspx">
<span>添加药房</span>
</a>
添加按钮以dialog方式打开href这个页面。
<a class="delete" href="DrugStoreAssessment/DrugStoreHandler.ashx?title=delete" posttype="string" rel="ids" target="selectedTodo" title="确实要删除这些记录吗?">
<span>批量删除</span>
</a>
对列表的批量删除说明:
class="delete" 代表是一个删除的按钮
href="DrugStoreAssessment/DrugStoreHandler.ashx?title=delete" 执行删除的页面,对应的文件如下图。
注意:这里并没有传ids过去。而title只是我这里用来标记DrugStoreHandler.ashx需要执行的操作。
posttype="string" 传送过去的类型
rel="ids" 对应传送过去ids的名称,与下面生成table中的<input name="ids" type="checkbox" value=<%对应的id值%> />对应。
target="selectedTodo" title="确实要删除这些记录吗?",这个按钮执行的是selecedTodo事件,就是对你所勾选的行执行一个ajax事件。执行前弹出需要确定的提示框,内容为title。如下图
此处第一次用到了dwz中的ajax,特此说明
dwz中的ajax:
DrugStoreHandler.ashx 接受药房管理中所有的ajax操作。如果你对ashx文件还了解,请在博客园中搜索,并认真阅读。
读取title的内容,如 DrugStoreHandler.ashx?title=delete
这里的title命名确实很烂,应该叫action会比较贴切。
为空,不执行
否则判断title内容,进行操作
操作后返回json提示,见下面几个的方法内容。
json的说明见dwz使用说明文档。
public string success()
{
return "{\"statusCode\":\"200\", \"message\":\"操作成功!\"}";
}
public string success(string str,string navTabId)//批量删除会自动刷新所在的navTab。
{
return "{\"statusCode\":\"200\", \"message\":\"操作成功!" + str + "\",\"navTabId\":\""+navTabId+"\"}";
}
public string failure()
{
return "{\"statusCode\":\"300\", \"message\":\"操作失败\"}";
}
表列名
这里和html的写法一样。
<th width="40" class="asc">ID</th> 实习一个可点击的排序按钮。注意:这个排序功能demo中没有实现。
<th width="22"><input type="checkbox" group="ids" class="checkboxCtrl"></th>多选框这里要标记group是dwz的标
签,不是html标签,所以vs2010会标记为不标准,包过排序用的orderField也是dwz中定义。
表格数据绑定
<asp:Repeater ID="RepeaterTr" runat="server">使用Repeater控件进行数据输出。
<a title="删除" target="ajaxTodo" href="DrugStoreAssessment/DrugStoreHandler.ashx?title=delete&ids=<%# DataBinder.Eval(Container.DataItem, "DrugStoreID")%>" class="btnDel">删除</a>
这个是dwz中的一个ajaxTodo的方法。
target="ajaxTodo":a标签的类型为执行ajax
href=执行该ajax的对应的页面。注意:这里与批量删除不同,这里传了ids过去,批量删除会以','拼接ids。这里只有一个id,但为了方便我也用了ids。
class="btnDel" 一个删除的按钮样式
<a title="编辑" target="dialog" href="DrugStoreAssessment/DrugStoreEdit.aspx?id=<%# DataBinder.Eval(Container.DataItem, "DrugStoreID")%>" class="btnEdit">编辑</a>
title="编辑" :让鼠标放上去有个删除两个字提示,html表情
target="dialog" 打开的方式为弹出框
href=弹出框的地址,传了id过去进行编辑。
class="btnEdit"一个编辑的按钮样式
这里编辑与添加是一样的,继续表单验证。
表单验证,提交与提示
前台效果图:编辑为dialog弹出框页面
DrugStoreAdd.aspx 药房添加后台代码与页面代码
linq to sql
根据id来获取一个药店类
First()获取第一个。
哎,好吧,这个demo是我刚刚学linq的时候写的。
获取单个对象最好这样写。
var Ds = dc.DSA_DrugStore.Single(m => m.DrugStoreID == id);
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DrugStoreAdd.aspx.cs" Inherits="DrugStoreAssessment_DrugStore" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <h2 class="contentTitle">添加药房</h2> <div class="pageContent"> <form id="form1" method="post" action="DrugStoreAssessment/DrugStoreHandler.ashx" class="pageForm required-validate" onsubmit="return validateCallback(this)"> <input type="hidden" name="title" value="add" /> <div class="pageFormContent" layoutH="97"> <p> <label>名称:</label> <input type="text" name="name" size="30" maxlength="50" class="required" alt="请输入名称" /> </p> <p> <label>负责人:</label> <input type="text" name="responsiblePerson" size="30" maxlength="50" class="required" alt="请输入负责人" /> </p> <p> <label>地址:</label> <input type="text" name="address" size="30" maxlength="50" class="required" alt="请输入地址" /> </p> <p> <label>开业时间:</label> <input class="date readonly textInput valid" type="text" value="" readonly="readonly" name="greateDate"/> <a class="inputDateButton" href="javascript:void(0)">选择</a> <span class="info">yyyy-MM-dd</span> </p> </div> <div class="formBar"> <ul> <li><div class="buttonActive"><div class="buttonContent"><button type="submit">提交</button></div></div></li> <li><div class="button"><div class="buttonContent"><button type="button" class="close">取消</button></div></div></li> </ul> </div> </form> </div> </body> </html>
同上所述,这里html body标签可以省略。
页面排版
<h2 class="contentTitle">编辑药房</h2> 上图中的四个字。
这里的<div class="pageContent"> 大家可以去看css文件。页面排版。
这里要注意,想使用dwz的表单ajax,必须在表单中写上:
οnsubmit="return validateCallback(this)" 用于表单验证与表单提交成功后的提示。
这里validateCallback方法还支持一个重载validateCallback(this,fiction())这个是表单提交后执行自己写的方法。但悲剧的发现,如果我传一个自己的方法过去,表单成功失败的提示就没了,因为有这个方法就没有dwz中默认的方法。有你没我,好吧,我只有自己写成功失败提示。相关知识见之后的文章。
<input type="hidden" name="title" value="updata" /> 一个隐藏的input放着title的值。传递表单的时候给DrugStoreHandler.ashx的title动作标记,就是上面说的title。
页面表单内容:
为了不重复描述轮子,表单验证请看dwz的说明文档吧。我觉得看示例的html文档也大概知道这些验证是怎么用的。但这里要注意:客户端的验证是不安全的。服务端是一定需要再验证的。当然,你觉得两端验证麻烦,就用mvc3吧。我又再宣扬了~~
表单页脚:
提交:执行表单提交。
取消:会关闭页面或者弹出框内容叶。
class="close" 主要是有这个close的class的button就会关闭当前页。
我也不多解释了,就复制着用吧。呵呵。
后序与源代码
上手dwz还是比较简单的。目前但个人不太认同不了解js或jquery就使用dwz。否则你会遇到更多的问题。这可能是dwz还不是很完善或者文档还不够详细引起的。
dwz 2.0的将完善api。而且dwz的.Net项目已经开始。会有更完善.net的框架。大家敬请期待!我的CVSharp 框架计划也会不懈的努力下去。
源码(仅于演示):yjjWeb.7z
使用vs2010,数据库在db文件夹中,请附加,修改webconfig文件链接字符串。