演示已更新到此节介绍: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 " name = " chessBoard " VerticalAlignment = " top " WIDth = " 522 " ></ border >
< border borderBrush = " Silver " borderThickness = " 1 " Height = " 260 " HorizontalAlignment = " left " margin = " 756,0 " name = " onlineUserBoard " VerticalAlignment = " top " WIDth = " 230 " ></ border >
< border borderBrush = " Silver " borderThickness = " 1 " Height = " 280 " HorizontalAlignment = " left " margin = " 756,276,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 " />
< TextBox Height = " 29 " HorizontalAlignment = " left " margin = " 7,238,0 " name = " txtMsg " VerticalAlignment = " top " WIDth = " 143 " />
< button Content = " 提交 " HorizontalAlignment = " left " margin = " 159,240,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 = 0 ; i < 40 ; i ++ )
{
lbMsg.Items.RemoveAt( 0 );
}
}
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 > 0 )
{
btnChat_Click( null , null );
}
}
}
OK,至此,本节就真的结束了,现在F5运行,看看正常不正常:
如上图,一切正常,打完收工!
啊?上节那个纠结的进出房间的文本提示还没弄呢。。。-_-..下节写好了!
总结以上是内存溢出为你收集整理的Silverlight+WCF 新手实例 象棋 主界面-实时聊天区(二十五)全部内容,希望文章能够帮你解决Silverlight+WCF 新手实例 象棋 主界面-实时聊天区(二十五)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)