這節内容幾乎和上節一個樣的邏輯
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">
</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" />

好吧,還是和上次一樣截張圖吧:
接着我們同樣的,回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類,我們來實作,相當的簡單,周遊下房間使用者,除了自己,每個人發一份:
代碼
好了,服務寫完了,回用戶端調用了:
記得編繹,更新服務引用。
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。設定索引定位到最後一條
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()
app.client.chatcompleted += new eventhandler<system.componentmodel.asynccompletedeventargs>(client_chatcompleted);
void client_chatcompleted(object sender, system.componentmodel.asynccompletedeventargs e)
addmsg("我 說:" + txtmsg.text);
txtmsg.text = "";

發送寫完了,那接收呢?也是相當的相當的簡單,就一行:

//...省略掉剛才兩行...
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運作,看看正常不正常:
如上圖,一切正常,打完收工!
啊?上節那個糾結的進出房間的文本提示還沒弄呢。。。-_-..下節寫好了!
版權聲明:本文原創發表于部落格園,作者為路過秋天,原文連結:
http://www.cnblogs.com/cyq1162/archive/2010/07/24/1784349.html