继上一篇:CYQ.Data 轻量数据层之路 华丽升级 V1.3出世(五),本篇趁周末而且是下班时间看贴人不多,低调让其出手应用一下:
同样为了能一篇介绍完一个示例,我精简挑选了一下,本次的示例为:注册+登陆+在线聊天[省去了私聊部分]
在看此文示例之前,请先看:CYQ.Data 轻量数据层之路 应用示例篇(四) --因为注册+登陆从那直接Copy的,这节就省过了。
当前环境同样是:VS2005+SQL2005,以下进入正题:
一:数据库
起名:Chat
两个表:Users+Message,上图:
说明:和上一示例比较:Users表是一样的,Message表也几乎一样了。
二:项目初始
1:新建网站项目,如起名叫:Cyq.Data.ChatDemoProject
同样产生webconfig后添加好数据库链接!
2:添加引用:CYQ.Data.dll
3:生成分页查询存储过程与枚举:还是页面:WriteOut.aspx,用于生成输出:
生成分页存储过程新方法:CYQ.Data 轻量数据层之路 华丽升级 V1.3出世(五):[9:OutPutData:增加ExeCreateProc方法用于直接执行生成分页存储过程]
三:项目开始:
先上图,整体项目情况:
1:注册用户(Login.aspx:见示例篇(四))
2:用户登陆(Reg.aspx:见示例篇(四))
3:在线聊天:(Default.aspx)
先上图,聊天主界面:
分区域说明:
1:左侧区为聊天显示区 2:右侧上头为欢迎与退出 3:右侧下头为用户列表区 4:底部就是留言区了 5:ajax定时刷新用2.0内置ICallBack接口实现。
下面进行代码解说:
页面进来时,把能加载的都加载完:只有三个点[1:登陆者名称;2:用户列表;3:默认取10条留言显示]
1:登陆者名称与退出事件
void LoadMyInfo() { if (Session[ " ID " ] == null ) { Response.Redirect( " Login.aspx " ); } else { Session[ " ID " ] = Session[ " ID " ]; myID = Convert.ToInt32(Session[ " ID " ]); MAction action = new MAction(TableNames.Users); if (action.Fill(myID)) { action.SetTo(labUserName); } else { labUserName.Text = " 读取数据失败! " ; } action.Close(); } } protected void btnLogout_Click( object sender, EventArgs e) { Session[ " ID " ] = null ; Response.Redirect( " Login.aspx " ); }
2与3:绑定用户列表与后十条留言
void LoadListInfo() { int rowCount; MAction action = new MAction(TableNames.Users); // 加载用户列表 rptUserList.DataSource = action.Select( 0 , 0 , " ID<> " + myID, out rowCount); rptUserList.DataBind(); if (action.ResetTable(CustomerSQL.Message)) // 切换表到留言列表,加载留言列表 { rptMessageList.DataSource = action.Select( 1 , 10 , "" , out rowCount); rptMessageList.DataBind(); action.Close(); } }
上面又有一个自定义的CustomerSQL.Message,其实我应该用一下存储过程来演示的,算了,写都写了:
还是和上次演示一下,自定义语句放到类里统一管理了:
/// <summary> /// by 路过秋天 http://cyq1162.cnblogs.com/ /// </summary> public class CustomerSQL { public const string Message = " (SELECT m.*,uA.UserName,isnull(uB.UserName,'所有人') AS UserName2 FROM Message m LEFT JOIN Users uA ON m.SendUserID=uA.ID LEFT JOIN Users uB ON m.RecvUserID=uB.ID) v " ; }
4:接下来是Ajax部分了
这里我封装了一下,新建了个PageBase类放里面了,看一下PageBase.cs代码:
/// <summary> /// 路过秋天 http://cyq1162.cnblogs.com /// </summary> public class PageBase:System.Web.UI.Page,ICallbackEventHandler { #region ICallbackEventHandler 成员 /// <summary> /// Ajax方法时的回调结果 /// </summary> public string ajaxCallBackResult = null ; /// <summary> /// 注册Ajax方法 /// 调用方法名:callAjax(arg) /// 回调方法名:callBack(result) /// </summary> public void RegisterAjax() { RegisterAjax( this , " callAjax " , " callBack " ); } public void RegisterAjax(Control ct, string functionName, string callBackName) { if ( ! ct.Page.ClientScript.IsClientScriptBlockRegistered(functionName)) { string callBack = ct.Page.ClientScript.GetCallbackEventReference(ct, " arg " , callBackName, null ); string clientFunction = " function " + functionName + " (arg){ " + callBack + " } " ; ct.Page.ClientScript.RegisterClientScriptBlock(ct.Page.GetType(), functionName, clientFunction, true ); } } public string GetCallbackResult() { return ajaxCallBackResult; } public virtual void RaiseCallbackEvent( string eventArgument) { } public virtual void RegisterCommonScript() { const string script = @" function $(id){return document.getElementById(id)}function $V(id,defaltValue){if($(id)){if(defaltValue && $(id).value.length==0){return defaltValue;} else{return $(id).value;}}return '';} " ; Page.ClientScript.RegisterClientScriptBlock( this .Page.GetType(), " GetBy " , script, true ); } #endregion }
OK,现在看一下Default.aspx的Page_Load里调用一下:
public partial class _Default :PageBase { int myID; protected void Page_Load( object sender, EventArgs e) { LoadMyInfo(); LoadListInfo(); RegisterCommonScript(); RegisterAjax(); } // ...省略N行代码... }
其实,Ajax只有两部分:
1:点提交时,用户消息要ajax提交到后台入库: 2:用户定时去取消息
关于这两个,我们看一下ICallBack的实现:
public override void RaiseCallbackEvent( string eventArgument) { int splitIndex = eventArgument.IndexOf( ' : ' ); string cmd = eventArgument.Substring( 0 , splitIndex); string data = eventArgument.Substring(splitIndex + 1 ); switch (cmd) { case " 0 " : // 送发消息 ajaxCallBackResult = " 0 " + Send(data); break ; case " 1 " : // 查询消息 ajaxCallBackResult = " 1 " + GetMessage(data); break ; } }接收时:该代码和前台html约定好分隔符,这里为“:”号;
返回时:也要约定好分隔符,这里为“”号;
接下来就是实现两个函数Send与GetMessage了。
看下Send:
string Send( string msg) { int splitIndex = msg.IndexOf( ' : ' ); string [] content = msg.Split( ' ' ); // 内容为接收者ID消息内容 MAction action = new MAction(TableNames.Message); action.Set(Message.SendUserID, myID); action.Set(Message.RecvUserID,msg.Substring( 0 ,splitIndex)); action.Set(Message.Body, msg.Substring(splitIndex + 1 )); string result = action.Insert() ? " 1 " : " 0 " ; return result; }
再看下GetMessage:
private const string msg = " <div class=\ " msg\ " ><font color=\ " Olive\ " >{0}</font> 对 <font color=\ " Olive\ " >{1}</font> 说 <font color=\ " Olive\ " >{2}</font><br /><p>{3}</p></div> " ; string GetMessage( string maxID) { string result = "" ; MAction action = new MAction(CustomerSQL.Message); if (maxID == " 0 " ) { if (action.Fill( " 1=1 order by id desc " )) // 取最大ID返回 { result = action.Get < string > (Message.ID) + " " ; action.Close(); } } else { int rowCount; MDataTable mTable = action.Select( 0 , 0 , string .Format( " ID>{0} and SendUserID<>{1} and (RecvUserID=0 or RecvUserID={1}) " , maxID, myID), out rowCount); action.Close(); if (rowCount > 0 ) { result = mTable.Rows[rowCount - 1 ][ " ID " ].Value + " " ; foreach (MDataRow row in mTable.Rows) { result += string .Format(msg,row[ " UserName " ].Value, row[ " UserName2 " ].Value,row[ " PubTime " ].Value,row[ " Body " ].Value); } } else { result += maxID + " " ; } } return result; }代码有点长,似乎不太好理解,因为和前台html界面相关的关系:其实就是组合字符串输出了。
5:前台HTML/JS
发送消息时:
// 组合成 命令:用户ID:留言内容 callAjax( " 0: " + $V( ' hdfUserID ' ) + " : " + $( ' txtBody ' ).innerHTML);
接收消息时:
// 组合成 命令:最大消息ID callAjax( " 1: " + msgMaxID);
回调时结果:
function callBack(result) { var items=result.split(''); switch(items[0]) { case "0"://发送消息返回结果 $('btnSend').disabled=false; add($V('hdfBody')); break; case "1"://查询返回结果 if(items.length>1) { msgMaxID=items[1]; } if(items.length>2) { add(items[2]); } break; } } function add(msg) { if(msg) { $('left').innerHTML+=msg; $('left').scrollTop=$('left').scrollHeight;//滚动条定位到最后面 } }
其余具体html代码就不详细贴出来了,因为我知道,我上面代码贴的再详细,估计也没多少人看,大伙看个开头,然后往下拉,看到源码下载,点击下载,差不多就拍拍屁股走人了
不过还是要提供整个示例下载:点击下载 [数据库创建脚本在App_Data目录下]
欢迎感兴趣读者讨论与留言:[上面代码注释太少,在测试使用中,如有不明请留言]。[写个示例花了1小时,写篇文章花了一天了,不容易啊!]
版权声明:本文原创发表于博客园,作者为路过秋天,原文链接: http://www.cnblogs.com/cyq1162/archive/2010/08/21/1805018.html 相关资源:敏捷开发V1.0.pptx