继上一篇: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小时,写篇文章花了一天了,不容易啊!]