您的位置:首页 > 其它

Silverlight+WCF 新手实例 象棋 主界面-实时聊天区(二十五)

2012-03-09 00:00 447 查看
在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示

演示已更新到此节介绍:Silverlight+WCF 新手实例 象棋 介绍III(二十三)

本节连着Silverlight+WCF 新手实例 象棋 主界面-在线用户区(二十四) 发,主界面就不截图了,这节我们实现“实时聊天区”:

这节内容几乎和上节一个样的逻辑

1:新建一个用户控件:就叫:Chat.xaml,用来在线聊天

2: 界面拖一个Border到Index.xaml,现在界面上有三个Border了,第三个chatBoard就是新添加进去的了。宽和高设置为230*280了。






<
Grid x:Name
=
"
LayoutRoot
"
Background
=
"
White
"
>

<
Border BorderBrush
=
"
Silver
"
BorderThickness
=
"
1
"
Height
=
"
544
"
HorizontalAlignment
=
"
Left
"
Margin
=
"
10,10,0,0
"
Name
=
"
chessBoard
"
VerticalAlignment
=
"
Top
"
Width
=
"
522
"
></
Border
>

<
Border BorderBrush
=
"
Silver
"
BorderThickness
=
"
1
"
Height
=
"
260
"
HorizontalAlignment
=
"
Left
"
Margin
=
"
756,10,0,0
"
Name
=
"
onlineUserBoard
"
VerticalAlignment
=
"
Top
"
Width
=
"
230
"
></
Border
>

<
Border BorderBrush
=
"
Silver
"
BorderThickness
=
"
1
"
Height
=
"
280
"
HorizontalAlignment
=
"
Left
"
Margin
=
"
756,276,0,0
"
Name
=
"
chatBoard
"
VerticalAlignment
=
"
Top
"
Width
=
"
230
"

/>

</
Grid
>

3:后台动态加载控件了,后台代码就两行,看今天新加的那。






public
Index()
{
InitializeComponent();
Chess chessControl
=
new
Chess();
//
实例化控件

chessBoard.Child
=
chessControl;
//
加载控件

OnlineUser onlineUserControl
=

new
OnlineUser();
//
今天新加的在线用户

onlineUserBoard.Child
=
onlineUserControl;
Chat chatControl
=

new
Chat();
//
也是今天新加的---看这里看这里两行

chatBoard.Child
=
chatControl;
}

OK,控件加载完了。接下来的任务就是要实现chatControl里的内容显示了:

接下来我们回到chat.xaml里,改一下总体宽和高为230*280:


<
UserControl ...省略一堆... d:DesignHeight
=
"
280
"
d:DesignWidth
=
"
230
"
>

<
Grid x:Name
=
"
LayoutRoot
"
Background
=
"
White
"
>

</
Grid
>

</
UserControl
>

然后呢,往里放四个TextBlock和一个ListBox..-_-...不是啦,都照着上节复制了。。。

然后呢,往里放一个TextBox;一个Button和一个ListBox,这个对了。。

看清楚按钮哦,下面Button默认多了一个Click事件,不小心双击了下,反正早晚要双击的。







<
Grid x:Name
=
"
LayoutRoot
"
Background
=
"
White
"
>

<
ListBox Height
=
"
226
"
HorizontalAlignment
=
"
Left
"
Name
=
"
lbMsg
"
VerticalAlignment
=
"
Top
"
Width
=
"
215
"
Margin
=
"
7,8,0,0
"

/>

<
TextBox Height
=
"
29
"
HorizontalAlignment
=
"
Left
"
Margin
=
"
7,238,0,0
"
Name
=
"
txtMsg
"
VerticalAlignment
=
"
Top
"
Width
=
"
143
"

/>

<
Button Content
=
"
提交
"
HorizontalAlignment
=
"
Left
"
Margin
=
"
159,240,0,13
"
Name
=
"
btnChat
"
Width
=
"
63
"
Click
=
"
btnChat_Click
"

/>

</
Grid
>

好吧,还是和上次一样截张图吧:



接着我们同样的,回WCF服务端写事件了[你点击提交,内容得提交到服务端吧,人家也提交,你这边得接收更新吧]。

打开IService.cs,加入接口:


[OperationContract(IsOneWay
=

true
)]

void
Chat(Player player);

看,我们把Player传递过去了,可是我们的聊天消息往哪放呢?Player可是没有属性来存这个消息的哦?没有?那就加呗。

打开Player.cs,加一个附加信息属性[以后这属性大有用处]:







///

<summary>

///
游戏玩家 by 路过秋天

///

</summary>

[DataContract]

public

class
Player
{

//
...省略几百个属性...

///

<summary>

///
附加信息,杂七杂八的都可以

///

</summary>

[DataMember]

public

string
AttachInfo
{

get
;

set
;
}
}

好了,现在有了,接着增加一个回调,通知大伙接收我发的消息:

打开ICallBack.cs接口,增加:



interface
ICallBack
{

//
..省略掉之前两个..两个也省,就是这么省

[OperationContract(IsOneWay
=

true
)]

void
NotifyChatUpdate(Player player);
//
通知聊天信息更新

}

接着实现接口的Chat方法,其实服务端接到消息,直接就转发了,所以代码,一行:


public

class
Service : IService
{

//
...省略几百行代码...

public

void
Chat(Player player)
{
Notify.Chat(playerList, player);
}

}

一来消息就把消息通知给大伙,可是那个Notify.Chat方法我们还没实现呢。

切回到Notify类,我们来实现,相当的简单,遍历下房间用户,除了自己,每个人发一份:





代码



///

<summary>

///
通知 by 路过秋天

///

</summary>

public

class
Notify
{

//
...省略掉之前的两个通知方法...

internal

static

void
Chat(Dictionary
<
int
, Dictionary
<
Guid, Player
>>
playerList, Player player)
{

foreach
(KeyValuePair
<
Guid, Player
>
item
in
playerList[player.RoomID])
{

if
(item.Value.ID
!=
player.ID)
{
item.Value.CallBack.NotifyChatUpdate(player);
}
}

}
}

好了,服务写完了,回客户端调用了:

记得编绎,更新服务引用。

OK,现在回到Chat.xmal.cs代码里,我们要动手了:

手痒,先写一个AddMsg(string msg)方法,用于添加消息






public

void
AddMsg(
string
msg)
{

if
(lbMsg.Items.Count
>

50
)
{

for
(
int
i
=

; i
<

40
; i
++
)
{
lbMsg.Items.RemoveAt(

);
}
}
lbMsg.Items.Add(
string
.Format(
"
[{0}]{1}
"
,DateTime.Now.ToLongTimeString(),msg));
lbMsg.SelectedIndex
=
lbMsg.Items.Count
-

1
;
lbMsg.UpdateLayout();
lbMsg.ScrollIntoView(lbMsg.SelectedItem);
}

说明:

1。如果消息内容大于50条,我们就清除前面40条

2。往ListBox里添加消息

3。设置索引定位到最后一条

4。更新下布局,为什么会有这个,详见:Silverlight4 ListBox bug

5。滚动到最后一条去。

OK,接着我们双击按钮,去Click事件里写代码:

两行代码,就三行[刚加了一行判断..-_-.]!


private

void
btnChat_Click(
object
sender, RoutedEventArgs e)
{if (txtMsg.Text.Length > 0)
{
App.player.AttachInfo
=
txtMsg.Text;
//
设置消息

App.client.ChatAsync(App.player);
//
传递消息

}

}

可是WCF是异步的,咋不见那个发送后的回调函数呢?这里,我把它放构造函数里去了,总不能每点击就来一次事件,会造成不良影响的。

看,来了,在回调里,我们添加一条消息,然后清空文本:






public
Chat()
{
InitializeComponent();
App.client.ChatCompleted
+=

new
EventHandler
<
System.ComponentModel.AsyncCompletedEventArgs
>
(client_ChatCompleted);
}

void
client_ChatCompleted(
object
sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
AddMsg(
"
我 说:
"

+
txtMsg.Text);
txtMsg.Text
=

""
;
}

发送写完了,那接收呢?也是相当的相当的简单,就一行:






public
Chat()
{

//
...省略掉刚才两行...

App.client.NotifyChatUpdateReceived
+=

new
EventHandler
<
GameService.NotifyChatUpdateReceivedEventArgs
>
(client_NotifyChatUpdateReceived);

}

void
client_NotifyChatUpdateReceived(
object
sender, GameService.NotifyChatUpdateReceivedEventArgs e)
{
AddMsg(e.player.NickName
+

"
说:
"

+
e.player.AttachInfo);
}

一收到消息就直接AddMsg进去了,OK,到此小节就结束了。

不过有时候我们喜欢用回车就发送消息,不想点按钮,那就为TextBox添加一个KeyDown事件吧

上一张图,免的大伙不知在哪加:



好,双击进去后事件代码,直接调用按钮事件:







private

void
txtMsg_KeyDown(
object
sender, KeyEventArgs e)
{

if
(e.Key
==
Key.Enter)
{

if
(txtMsg.Text.Length
>

)
{
btnChat_Click(
null
,
null
);
}
}
}

OK,至此,本节就真的结束了,现在F5运行,看看正常不正常:



如上图,一切正常,打完收工!

啊?上节那个纠结的进出房间的文本提示还没弄呢。。。-_-..下节写好了!

原文链接:
http://www.cnblogs.com/cyq1162/archive/2010/07/24/1784349.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐