演示地址:
http://task.24city.com/default.html
预览界面:
一、布局
采用Grid布局,5行2列
第一行:为登录/注册信息区
第二行:左列为聊天记录区,右列为"最近联系人,我的好友,当前在线"等常见功能区
第三行:显示当前聊天对象以及"加为好友","从好友列表中删除"二个按钮
第四行: 打字聊天栏
第五行:发送按钮
二、机制
a.采用wcf通讯,silverlight调用wcf得到返回结果和发送聊天内容,wcf与数据库交互----即silverlight以wcf为桥梁来操作数据库
b.聊天记录的刷新采用Timer定时器,每隔5秒通过调用wcf更新
c.在线列表利用website中的Global全局字典来实现,每登录或注销一个用户时,均通过wcf向该字典中插入或删除指定key的"记录"
三、一些小技巧:
a.Ctrl+回车 键发送的实现代码:
private void txtContent_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
ModifierKeys keys = Keyboard.Modifiers;
if (e.Key == Key.Enter && keys == ModifierKeys.Control)
{
btnSend_Click(sender, e);
}
}
b.TabControl中加载ListBox并附加滚动条的代码:
ListBox _listBox = new ListBox();
_listBox.ItemsSource = _list;
_listBox.DisplayMemberPath = "Value";
_listBox.MouseLeftButtonUp += new MouseButtonEventHandler(_listBox_MouseLeftButtonUp);
ScrollViewer _viewer = new ScrollViewer();
_viewer.Content = _listBox;
_listBox.BorderThickness = new Thickness(0);
this.tblItemRecently.Content = _viewer;
_viewer.Height = pnlTab.ActualHeight - 38;
即TabItem的Content指定为一个ScrollViewer,而这个ScrollViewer的Content再指定为ListBox,用二层嵌套实现
c.客户端登录Ip的取得
silverlight并不能直接取得IP地址,所以这里用website中的wcf做了中转,xap加载时就先利用wcf取回当前Ip,呵
四、代码
代码有点乱,也相对比较长,关键代码全部折叠贴在下面了:
MainPage.Xaml
<UserControl xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input" x:Class="Talker.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot" ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="250"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="35"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="35"></RowDefinition>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="35"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2" x:Name="pnlLogin" Visibility="Collapsed">
<dataInput:Label Content="用户名:" VerticalAlignment="Center" HorizontalAlignment="Center" ></dataInput:Label>
<TextBox Width="100" x:Name="txtLoginName" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBox>
<dataInput:Label Content="密 码:" Margin="3,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" ></dataInput:Label>
<PasswordBox Width="100" x:Name="txtPwd" VerticalAlignment="Center" HorizontalAlignment="Center"></PasswordBox>
<Button Content="登录" Width="60" Margin="3,0,0,0" x:Name="btnLogin" Click="btnLogin_Click" VerticalAlignment="Center" HorizontalAlignment="Center" ></Button>
<Button Content="注册" Width="60" Margin="3,0,0,0" x:Name="btnGoToReg" Click="btnGoToReg_Click" VerticalAlignment="Center" HorizontalAlignment="Center" ></Button>
</StackPanel>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2" x:Name="pnlReg">
<dataInput:Label Content="用户名:" VerticalAlignment="Center" ></dataInput:Label>
<TextBox Width="90" x:Name="txtRegName" VerticalAlignment="Center"></TextBox>
<dataInput:Label Content="呢称:" Margin="3,0,0,0" VerticalAlignment="Center"></dataInput:Label>
<TextBox Width="90" x:Name="txtNickName" VerticalAlignment="Center"></TextBox>
<dataInput:Label Content="密 码:" Margin="3,0,0,0" VerticalAlignment="Center" ></dataInput:Label>
<PasswordBox Width="60" x:Name="txtRegPwd" VerticalAlignment="Center"></PasswordBox>
<dataInput:Label Content="再次输入密码:" Margin="3,0,0,0" VerticalAlignment="Center" ></dataInput:Label>
<PasswordBox Width="60" x:Name="txtRegPwd2" VerticalAlignment="Center"></PasswordBox>
<Button Content="注册" Width="50" Margin="3,0,0,0" x:Name="btnReg" VerticalAlignment="Center" Click="btnReg_Click"></Button>
<Button Content="返回登录" Width="60" Margin="3,0,0,0" x:Name="btnBackToLogin" Click="btnBackToLogin_Click" VerticalAlignment="Center" ></Button>
</StackPanel>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2" x:Name="pnlLoginOk" Visibility="Collapsed">
<TextBlock x:Name="txtLoginOk" Text="1^yjmyzz@126.com@^菩提树下的杨过" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
<Button Content="退出" Margin="3,0,0,0" x:Name="btnLogOut" Width="50" VerticalAlignment="Center" HorizontalAlignment="Center" Click="btnLogOut_Click" ></Button>
</StackPanel>
<TextBox Grid.Row="1" Grid.Column="0" TextWrapping="Wrap" Text="" IsReadOnly="True" x:Name="txtRecord" VerticalScrollBarVisibility="Auto"></TextBox>
<StackPanel Grid.Row="1" Grid.Column="1" x:Name="pnlTab">
<controls:TabControl x:Name="tblTitle" Margin="3,0,0,0">
<controls:TabItem Header="最近联系人" x:Name="tblItemRecently" MouseLeftButtonUp="tblItemRecently_MouseLeftButtonUp" />
<controls:TabItem Header="我的好友" x:Name="tblItemMyFriend" MouseLeftButtonUp="tblItemMyFriend_MouseLeftButtonUp" />
<controls:TabItem Header="当前在线" x:Name="tblItemOnline" MouseLeftButtonUp="tblItemOnline_MouseLeftButtonUp" />
</controls:TabControl>
</StackPanel>
<StackPanel Grid.Row="2" Grid.ColumnSpan="2" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="3,0,0,0">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">
<Run>您正在跟 </Run>
<Run Foreground="Red" x:Name="txtTarget"></Run>
<Run> 聊天:</Run>
</TextBlock>
<Button x:Name="btnAddFriend" Content="加为好友" Width="60" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3,0,0,0" Click="btnAddFriend_Click" Visibility="Collapsed" />
<Button x:Name="btnDeleteFriend" Content="从好友列表中删除" Width="140" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="3,0,0,0" Click="btnDeleteFriend_Click" Visibility="Collapsed" />
<dataInput:Label x:Name="lblId" Visibility="Collapsed" Content=""></dataInput:Label>
</StackPanel>
<TextBox x:Name="txtContent" Text="" Grid.Row="3" Grid.ColumnSpan="2" KeyDown="txtContent_KeyDown" GotFocus="txtContent_GotFocus"></TextBox>
<TextBlock Text="按“Ctrl+回车”发送" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center"></TextBlock>
<Button x:Name="btnSend" Grid.Row="4" Grid.Column="1" Content="发送" Width="80" HorizontalAlignment="Right" VerticalAlignment="Center" Click="btnSend_Click" ></Button>
</Grid>
</UserControl>
MainPage.Xaml.cs
using System;
using System.Collections.Generic;
using System.Json;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using Talker.BLL;
using Talker.Entity;
namespace Talker
{
public partial class MainPage : UserControl
{
string _wcfBasePath = "http://localhost:9002/Wcf/talk.svc/";
string _Ip = "";
private DispatcherTimer _timer;
public MainPage()
{
InitializeComponent();
GetIP();
ShowLogin();
}
/**//// <summary>
/// 格式化登录信息
/// </summary>
/// <returns></returns>
string FormatLoginInfo()
{
string[] _arr = Helper.GetLoginInfo().Split('^');
return "欢迎回来 " + _arr[1] + "(" + _arr[2] + "),最近登录时间:" + _arr[3] + ",最近登录Ip:" + _arr[4];
}
/**//// <summary>
/// 显示登录面板
/// </summary>
void ShowLogin()
{
if (Helper.IsLogined())
{
pnlLoginOk.Visibility = Visibility.Visible;
pnlLogin.Visibility = Visibility.Collapsed;
pnlReg.Visibility = Visibility.Collapsed;
txtLoginOk.Text = FormatLoginInfo();
//向服务器在线列表中添加自己
InsertOnline();
//获取历史聊天记录
GetMessageList();
//获取最近联系人
GetRecentList();
this._timer = new DispatcherTimer();
this._timer.Interval = new TimeSpan(0, 0, 5);
this._timer.Tick += new EventHandler(timer_Tick);
this._timer.Start();
}
else
{