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 } }