Chat Server and WPF Client
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 ICommand thing almost easy.
using System;
using System.Windows.Input;
namespace ChatClient
{
class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute, Predicate<object> 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:
using System.ComponentModel;
using ChatClient.Models;
namespace ChatClient.ViewModels
{
/// <summary>
/// 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.
/// </summary>
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
/// <summary>
/// Constructor creates the Model!
/// </summary>
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
}
}