Programmation d'un Chat type IRC

 

Nous allons maintenant coder un Chat assez basique : nous allons commencer par coder la partie client, qui va se connecter à un serveur (adresse et port, définis par l'utilisateur) et lui envoyer des messages avec le protocole UDP. Le client pourra se mettre en écoute sur un port lui aussi défini par l'utilisateur.

Apparence du chat :

Première étape :

Créer le GUI. Il sera défini dans deux fichiers nommé ChatClientView.xaml et ChatClientView.xaml.cs

Passez par une Grid pour placer vos éléments, par un StackPanel pour les éléments situés dans le bandeau à droite.

Vous donnerez un style à vos boutons, comme sur le screen: dégradé de couleur (LinearGradientBrush), texte en gras, etc... Le style étant partagé par les boutons, vous créerez un dossier Resources dans votre projet, et vous y ajouterez le fichier définissant le style des boutons : ChatClientButtonStyle.xaml. L'élément racine de ce fichier doit être un ResourceDictionary car on pourra y ajouter plusieurs éléments si besoin.

Dans les ressources de votre fénêtre principale, vous importerez ce ou ces styles en fusionnant le ResourceDictionary de celle-ci avec celui importé, on utilisera donc la balise ResourceDictionary.MergedDictionaries.

 

Seconde étape :

Créer les modèles. Dans une architecture MVVM, nous voulons séparer la vue du modèle, avec qu'un changement de code sur l'un n'impacte pas le code de l'autre.

Nous allons donc créer deux classes : une Connection qui va représenter toute la partie réseau, et une Message qui va représenter les messages envoyés et reçus. Chaque classe sera définie dans son propre fichier.

La classe Message sera pour le moment très simple. Elle va posséder 3 attributs :

  • Sender, qui sera l'IP de celui qui a envoyé le message reçu

  • TimeStamp, qui sera l'horodatage du message reçu

  • Content, le contenu du message proprement dit.

La classe Connection va elle contenir :

  • ServerAdress

  • ServerPort

  • ListenerPort

  • Server, de type UdpClient

  • Listener, de type UdpClient

  • Des méthodes permettant de : se connecter au serveur, de déclencher une boucle d'écoute, d'envoyer un message au serveur, de recevoir un message.

 

Troisième étape :

Nous allons ensuite créer une classe ChatClientViewModel. Cette classe va assurer la liaison entre le GUI et nos modèles. Elle sera donc instanciée une fois au démarrage de l'application, sera définie comme DataContext de notre fenêtre principale, et c'est elle qui instanciera les modèles et les manipulera.

Cela implique que lors d'un événement déclenché par l'utilisateur, la fonction appelée dans la fenêtre appellera elle-même une fonction du View-Model qui gèrera cet évènement en manipulant le ou les modèles nécessaires.

Ce View-Model devra donc instancier la Connection nécessaire et les Message à chaque réception pour les afficher dans le GUI.

 

Quatrième étape :

Il faut maintenant coller tous les éléments ensemble pour que ça fonctionne !

On commencera par ajouter des attribut à notre View-Model :

  • ConnectionStatus, qui nous renseignera sur le statut de la connexion, à l'aide d'un enum : Pas connecté, connecté ou erreur de connexion. Avec un DataBinding, un Converter et un DataTrigger, on le reliera à notre GUI à un TextBlock qui nous indiquera le statut de la connexion comme ceci :

 ou ou

  • ListeningStatus, qui sera relié au bouton idoine dans le GUI avec DataBinding et Converter :

 ou

  • TextDisplayed qui servira à afficher les messages entrants dans la fenêtre de chat.

  • MessageTyped qui sera bindé au message entré par l’utilisateur

  • connection, de type Connection

 

De quelle interface doit hériter votre View-Model pour avertir l'IHM en cas de changement d'un de ses attributs ? Et que faut-il implémenter pour rendre cela fonctionnel ?

Lorsque l'utilisateur clique sur Listen, il faut que cela appelle une boucle d'écoute de messages. Implémentez-là de la manière la plus simple, sans thread ou autre. Lancez votre application, mettez-vous en écoute. Que remarquez-vous ?

Pour palier le problème observé, on pourrait lancer le processus d'écoute dans un nouveau thread. Mais le FrameWork .Net 4.5 permet d'utiliser les mots clés async / await qui vont nous éviter ce travail parfois fastidieux.

On veillera à gérer correctement les exceptions, notamment les problèmes de connexion, qui doivent être notifiés à l'utilisateur par l'affichage d'une MessageBox explicitant le problème.

 

 

Les messages devront faire 160 caractères maximum, sinon l’envoi sera bloqué. On implémentera un compteur de caractères « à la twitter » : il nous indiquera en temps réel combien de caractères on peut encore écrire, et sera mis en rouge gras si on a dépassé la limite :

On utilisera pour cela, DataBinding, Converter et DataTrigger. Rien d’autre.