= Chat Server and WPF Client = Download the code on [[https://github.com/scotpatti/chatdemo|github]] or an older version from here: [[attachment:ChatServer2013.zip]] == Chat Client == For the client code I used WPF and the MVVM pattern. From the bottom up the first thing I used is a DelegateCommand for the ICommands needed for buttons and what not. This makes the use of ICommand almost easy. {{{#!csharp using System; using System.Windows.Input; namespace ChatClient { class DelegateCommand : ICommand { private readonly Predicate _canExecute; private readonly Action _execute; public event EventHandler CanExecuteChanged; public DelegateCommand(Action execute, Predicate canExecute) { _execute = execute; _canExecute = canExecute; } public bool CanExecute(object parameter) { return _canExecute == null || _canExecute(parameter); } public void Execute(object parameter) { _execute(parameter); } public void RaiseCanExecuteChanged() { if (CanExecuteChanged != null) { CanExecuteChanged(this, EventArgs.Empty); } } } } }}} You can see this in the ViewModel used below: {{{#!csharp using System.ComponentModel; using ChatClient.Models; namespace ChatClient.ViewModels { /// /// Adaptive code only. You should only see things here that adapt /// the Model to the view. This is an abstraction of the Model for /// the express use by the View. /// class ClientViewModel : INotifyPropertyChanged { #region Properties //Elements bound to by the view public string Message { get { return _clientModel.CurrentMessage; } set { _clientModel.CurrentMessage = value; NotifyPropertyChanged("Message"); } } public string MessageBoard { get { return _clientModel.MessageBoard; } set { _clientModel.MessageBoard = value; NotifyPropertyChanged("MessageBoard"); } } public DelegateCommand ConnectCommand { get; set; } public DelegateCommand SendCommand { get; set; } #endregion #region Private and Internal Vars/Props private readonly ClientModel _clientModel; #endregion /// /// Constructor creates the Model! /// public ClientViewModel() { //Create ourselves a model _clientModel = new ClientModel(); //Subscribe to the Model's PropertyChanged event _clientModel.PropertyChanged += ClientModelChanged; //Create our two Command objects ConnectCommand = new DelegateCommand( a => _clientModel.Connect(), b => !_clientModel.Connected ); SendCommand = new DelegateCommand( a => _clientModel.Send(), b => _clientModel.Connected ); } #region Event Listeners private void ClientModelChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName.Equals("Connected")) { NotifyPropertyChanged("Connected"); ConnectCommand.RaiseCanExecuteChanged(); SendCommand.RaiseCanExecuteChanged(); } else if (e.PropertyName.Equals("MessageBoard")) { NotifyPropertyChanged("MessageBoard"); } } #endregion #region NPC Implementation public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string prop) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } #endregion NPC Implementation } } }}} The ViewModel above creates the Model in the constructor. The Model is shown below. {{{#!csharp using System.ComponentModel; using System.Net.Sockets; using System.Text; using System.Threading; namespace ChatClient.Models { class ClientModel : INotifyPropertyChanged { private TcpClient _socket; private NetworkStream _stream; private string _messageBoard; public string MessageBoard { get { return _messageBoard; } set { _messageBoard = value; NotifyPropertyChanged("MessageBoard"); } } private string _currentMessage; public string CurrentMessage { get {return _currentMessage;} set { _currentMessage = value; NotifyPropertyChanged("CurrentMessage"); } } private bool _connected; public ClientModel() { _connected = false; } public bool Connected { get {return _connected; } set { _connected = value; NotifyPropertyChanged("Connected"); } } public void Connect() { _socket = new TcpClient(); _socket.Connect("127.0.0.1", 8888); _stream = _socket.GetStream(); Connected = true; Send(); _messageBoard = "Welcome: " + _currentMessage; var thread = new Thread(GetMessage); thread.Start(); } public void Send() { WriteString(_currentMessage + "$"); } private void GetMessage() { while (true) { string msg = ReadString(); MessageBoard += "\r\n" + msg; } } private string ReadString() { var bytes = new byte[16384]; _stream.Read(bytes, 0, _socket.ReceiveBufferSize); string msg = Encoding.ASCII.GetString(bytes); int index = msg.IndexOf("$") > 0 ? msg.IndexOf("$") : msg.IndexOf('\0'); return msg.Substring(0, index); } private void WriteString(string msg) { byte[] bytes = Encoding.ASCII.GetBytes(msg); _stream.Write(bytes, 0, bytes.Length); _stream.Flush(); } #region NPC public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string prop) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } #endregion } } }}} Finally the XAML View for this project was very simple and is bound (e.g. it creates its controller) to the ViewModel which is started from App.xaml in the {{{StartupUri="MainWindow.xaml"}}} ). Here is the view: {{{