IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Utilisation pattern MVC en C#


Sujet :

C#

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut Utilisation pattern MVC en C#
    Bonjour,

    J’essaye d’implémenter le pattern MVC en C#.
    Après plusieurs lectures j’ai créé mes 3 projets (Control, Model, et View = GUI)



    Pour apprendre j’ai fait : une WinForm du GUI contient un DataGridView, qui est censé afficher et rafraichir les données qui proviennent d’une base de données SQLite. J’ai codé les opérations connect/deconnect/insert/update/delete propre à la base SQLite dans le projet Model (Database.cs).
    Mais maintenant, je suis bloqué : dans quelle partie dois-je lancer la connexion à la base ? Comment est-ce que la form va-t-elle se rafraichir dès que ma base sql est modifiée ? J’ai lu que c’était le Model qui déclenchait la mise à jour du GUI. Comment faire cela ?

    Merci bcp.

  2. #2
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    Personnellement, je trouve que le modele View Presenter est amplement suffisant. Ceux qui veulent me contredire sont les bienvenus.

    Ton viewer doit exposer des methodes de Rafraichissement :
    OnConnected()
    OnAnswer(object datas);
    etc...
    Pour que le présenter puisse lui ordonner de modififer son affichage à chaque evenements.

    Ton présenteur lui s'abonne aux evenements de ta base, qu'il relaye au viewer en ne lui donnant que les infos relatives à l'affichage.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Salut,
    Merci pour ta réponse.

    J'ai avancé un peu (finalement). En fait l'utilise le MVC car sur la base décrite précédemment je vais ajouter pas mal de chose, et à force ca sera plus souple à maintenir.
    Quel est l'avantage du MVP par rapport au MVC ?

    J'ai une question plus précise désormais :
    Une fois que le Modèle a modifié la base de données, il envoie un event au Controller pour lui signaler de mettre à jour la listview Winform.
    Mon problème est : comment, depuis mon Controller, je peux interagir avec ma listview ? En gros j'ai ma fonction Form1.UpdateListViewData() qui doit etre appelé depuis ma classe Controller.cs, mais je sais pas comment faire ?

    Merci !


    edit: mon nouveau model :


  4. #4
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    je ne connais pas le pattern avec le controller, mais quelque chose me choque malgres tout :

    Pourquoi ta classe controlleur est dans ta dll UI?
    On dirait que ca casse tout l'interret de la chose : pouvoir changer d'interface graphique sans probleme de dépendance.

    Car aujourd'hui c'est une windowsForm, demain ca sera peut etre une page web, que deviendra alors ton controleur?

    Un petit tuto du site qui peut etre te fera voir la chose sous un autre angle :

    http://jab.developpez.com/tutoriels/dotnet/mvppattern/

    C'est d'ailleur par ce tuto que j'ai appris le pattern, merci à son auteur au passage.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Citation Envoyé par giova_fr Voir le message
    Pourquoi ta classe controlleur est dans ta dll UI?
    En fait je voulais 'rapprocher' le Controller de l'UI, afin de pouvoir accéder à ma winform.. en vain !

    Je suis bloqué quoi

    Je vais regarder ton site merci. Mais le problème sera toujours d'accéder à la Form en cours depuis une autre classe pour rafraichir les infos..

  6. #6
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    donc mes craintes etaient justifiés.

    C'est justement tout l'interret du pattern que de casser la dépendance.

    Ton controleur ne doit en aucun cas savoir comment fonctionne ta form, tout ce qu'il doit connaitre, c'est quelques methodes publiques pour dire à ta form de faire telle ou telle action visuelle.

    Et inversement, ta form ne doit pas savoir ce que fait Controleur, tout ce qu'elle doit connaitre c'est quelques methodes pour lui dire que l'utilisateur a cliqué sur tel ou tel bouton.

    Tout ceci se fait normalement par le biais d'interfaces :

    MesInterfaces.dll :
    IControler
    IViewer

    Controleur.dll:
    Controleur implémentant IControler

    GUI.dll:
    Viewer implémentant IViewer et prennant un IControler comme argument dans son constructeur pour pouvoir parler "à l'aveugle" au controleur.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Je suis d'accord avec tes premières phrases, du moins c'est comme ca comme je l'ai compris. Après la mise en oeuvre me pose problème.

    Pour les Interfaces je pensais m'en passer. Je n'en voyais pas trop l’intérêt en fait.
    Ca ma parait un flou l'implémentation que tu me conseilles. Aurais-tu un exemple concret ?
    Merci bcp.

  8. #8
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    Pour les Interfaces je pensais m'en passer.
    Erreur fatale ! sauf si Controler et viewer heritent chacun de leur propre classe abstraite contenant les methodes à exposer. Ce qui ne semble pas etre le cas.

    Je n'en voyais pas trop l’intérêt en fait
    C'est justement là que réside tout l'interret de la chose ! Pas étonnant si tu zappe cette étape absolument primordiale, que tu ne sache pas comment implémenter, que tu te retrouve avec des problemes de dépendances.

    Les interfaces (ou classes abstraites mais concentrons nous sur les interfaces) permette à viewer de donner une coquille vide au controleur, et vis et versa.

    Place tes interfaces dans un projet à part, disons IMesInterfaces.dll ainsi ton projet UI.dll dépendra de IMesInterfaces.dll , ton projet Controler.dll dépendra aussi de IMesInterfaces.dll, mais Controler.dll ne dépendra plus de UI.dll,idem UI.dll ne dépendra plus de Controler.dll, tu casse la dépendance.

    Du coup, Controleur ne sait pas qu'il parle à viewer, il parle à IViewer qui pourrait etre une winform, une page web, une application console, n'importe quoi.

    Et pareil dans l'autre sens.

    Alors biensur il faudra bien que quelque chose dans ton code sache comment assembler le puzzle, quel viewer choisir, quel controleur choisir. Dans un premier temps tu peux faire ca dans le main, qui du coup dépendra de tout : IMesInterfaces.dll, Controler.dll ,UI.dll . Mais cela ne concernera que 2 ou 3 lignes de code, le temps d'appeller les constructeurs voulus sur les classes choisies.

    Apres il existent d'autres pattern pour jouer justement ce role.

    Pour l'exemple : suis le tuto que je t'ai filé, l'exemple c'est le tuto

    Et n'oublie pas, ton viewer ne doit gérer que 2 choses :
    • l'affichage (dessiner le bouton en position relevée ou pas, selon les ordres qu'il recoit de l'interface IControler)
    • Informer l'interface IControler lorsque l'utilisateur réalise une action (il presse sur un bouton)

    C'est tout !

    Controleur lui prend les décisions, l'utilisateur a cliqué, je suis dans quel contexte? ok j'interroge la base, j'ai un resultat? ok je demande au viewer d'afficher le resultat.

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Bonjour,

    Merci bcp pour ton aide.
    J'ai compilé et éxécuté le tuto MVP, ca fonctionne ben en effet.
    Question : Pourquoi le projet n'a-t-il pas d'interface Presenter (IPresenter) alors qu'il a IAstuceView ? C'est inutile ?
    Dans mon cas puis-je supprimer IController.cs ?

    Pour revenir à mon code j'ai cette erreur récurrente :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public partial class Form1 : Form, IViewer {
    Erreur sur IViewer :
    'Interfaces.IViewer' est inaccessible en raison de son niveau de protection.
    Idem pour IController.

    Je ne comprend pas, j'ai bien mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    namespace Interfaces
    {
        interface IViewer
        {
            DataTable dt { set; }
    	string plan { set; }
        }
    }
    Voici le schema actuel :

  10. #10
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    Dans mon cas puis-je supprimer IController.cs ?

    sert principalement si il y a plusieurs type de controleur derriere. DOnc dans ton cas ca n'est pas indispensable.

    Jusqu'au moment où ca le deviendra, va savoir

    Ton nouveau probleme, est je pense celui que l'on rencontre le plus sous visual studio.

    Il t'as créé ton interface, sans préciser si il est public ou private ou ...

    La Norme c# dit, si il n'y a rien c'est privé.

    D'ou ton probleme d'ailleur tu as du etre surpris en voyant qu'intellisense ne trouvait pas ton interface, un signe qui ne trompe pas

  11. #11
    Membre chevronné
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2009
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Février 2009
    Messages : 317
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    namespace Interfaces
    {
        public interface IViewer
        {
            DataTable dt { set; }
    	string plan { set; }
        }
    }

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Ok !
    J'ai donc passé mes interfaces en public, je ne sais pas si c'est propre mais au moins ca résout le problème.
    J'ai cette erreur maintenant :
    'UI.Views.Form1' n'implémente pas le membre d'interface 'Interfaces.IViewer.dt'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    namespace Interfaces
    {
        public interface IViewer
        {
            DataTable dt { set; }
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    //UI.Views
    public partial class Form1 : Form, IViewer  // erreur ici
    {
            DataTable dt;
    Ce n'a pas l'air un problème d'IntelliSense ?


    Sinon, concernant mon pattern, il fonctionne comme cela actuellement :
    - un hardware externe envoie des données à mon Controller
    - le controller vérifie que les données sont ok, créer une requête sql avec ses données, et envoie la requete au Modele
    - le modèle rempli la bdd avec les données du controller
    - à chaque modification de la base (insert/delete/update) le modèle prévient (event) le controller que la base a été modifiée
    - le controller demande alors au modèle cette nouvelle base et l'envoie à la Vue
    - La vue met à jour ses données

    Est-ce la bonne logique du modèle MVC/P ? Ai-je tout faux ?

    Merci.

  13. #13
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    J'ai donc passé mes interfaces en public, je ne sais pas si c'est propre
    c'est tres propre, dans ce contexte.

    Pour ton probleme, c'est normal !
    dans ton interface, dt est une propriété (get) alors que dans ta classe c'est un champ (une simple variable), donc c'est pas la meme chose, le compilo ne trouve pas, et n'est pas content.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //UI.Views
    public partial class Form1 : Form, IViewer  // erreur ici
    {
            private DataTable m_dt;
            public DataTable dt
           {
                 get{return m_dt;}
            }
    passera.

    du point de vue technique c'est bon, mais du coté "pédaguogique" tu t'ecarte l'esprit du pattern car ta form a un DataTable demain ca peut etre remplacé par une page web qui aura un tableau html.

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Ok merci pour la correction.
    Je comprend ce que veut dire à propos du tableau htlm.. dans mon cas on va dire que ca restera une datatable !

    Je suis confronté à une autre ambiguïté, j'ai mis dans un tread à part (backgroundworker) l'insertion de requete dans ma base de donnée, et donc la mise à jour de la winform (listview) jette une exception car le thread qui modifie la form n'est pas le thread principal.
    Comment s'en sortir ? Comment faire du multi-thread tout en gardant la logique du pattern ?
    Merci infiniment !

  15. #15
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    encore une fois si ton thread fait la requette SQL, alors il doit etre dans ta classe controler, et non dans ta classe form qui ne gere que l'affichage du resultat + transmet au controleur les ordres de recherche.

    Concernant ton exception, tu dois :
    -Soit comme il t'a été dit dans l'autre thread, le faire dans la callback (me rappelle plus le nom exact) "jobdone"
    -Soit tu fois faire un Invoke, qui permet de relayer l'appel au thread qui gere ta form.

    Cherche Control Invoke.

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Citation Envoyé par giova_fr Voir le message
    encore une fois si ton thread fait la requette SQL, alors il doit etre dans ta classe controler, et non dans ta classe form
    Mon thread est dans le Modèle, vu que c'est lui le 'métier' c'est lui qui fait les calcul. Je pensais que le Controller ne servait qu'a faire des vérifications sur ce qu'entre l'utilisateur.
    Donc ca serai logique de mettre la gestion des threads dans le controller d'après toi ?

    J'ai vu comment Invoke fonctionne merci.

  17. #17
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2005
    Messages
    700
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Juin 2005
    Messages : 700
    Par défaut
    ah je croyais que tu l'avais mis dans la form, vu que dans un autre topic, tu parle du controle BackgroundWorker.

    J'ai du t'embrouiller l'esprit du coup

    ok bah au vu de ton dernier post ca a l'air nikel, si en plus au passage tu as appris à utiliser les invokes, t'es un vrai pro maintenant

  18. #18
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 310
    Par défaut
    Invoke fonctionne bien, génial. Euh un pro pas tellement hein

    Du coup, pour respecter le pattern, le backgroundworker qui lit les données venant de mon hardware doit etre dans la classe Modele ou Controller ?
    Acutellement sur tes conseils il est dans le Controller et ca marche super.

Discussions similaires

  1. Réponses: 4
    Dernier message: 24/02/2009, 12h06
  2. Tutoriel : Implémentation du pattern MVC
    Par Ricky81 dans le forum MVC
    Réponses: 0
    Dernier message: 11/02/2008, 09h51
  3. Problème d'accessibilité avec le design patterns MVC
    Par radical_bombtracks dans le forum JSF
    Réponses: 5
    Dernier message: 24/07/2007, 13h15
  4. Faut-il combiner Spring avec Struts ou utiliser Spring MVC ?
    Par micanti dans le forum Frameworks Web
    Réponses: 3
    Dernier message: 23/04/2007, 16h31
  5. Pattern MVC et barre de progression
    Par Tiberizz dans le forum Interfaces Graphiques en Java
    Réponses: 7
    Dernier message: 05/12/2006, 18h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo