Question

Je développe une application WinForms en C #. J'ai une expérience limitée dans la programmation GUI, et j'ai apprendre beaucoup à la volée. Cela étant dit, voici ce que je suis bâtiment.

Voir l'aspect général de l'interface graphique à l'adresse suivante:

GUI http://img227.imageshack.us/img227/1084/program0.jpg

Maintenant, je l'ai fait beaucoup de travail déjà, mais dans le modèle de conception autonome très mauvais. Je ne savais pas que le projet aurait jamais atteint une certaine taille, et, en tant que tel, il est temps de faire un peu de modification majeure.

Je suis en train d'étudier beaucoup sur les modèles de conception graphique, et le modèle que je souhaite mettre en œuvre est la vue passive (voir http://martinfowler.com/eaaDev/PassiveScreen.html ). Je cherche un peu d'aide sur la façon de mettre tout cela ensemble.

Arrière-plan:

1) En fonction de ce que l'utilisateur clique dans le « TreeView », la « Liste » dans le coin gauche main du bas affiche une liste d'objets qui peuvent renseigner la zone « Editeur ». Ces objets peuvent être une zone de texte ou un DataGridView. L'utilisateur permet de basculer la liste de choisir ce qu'il / elle veut voir dans le « Editor »

2) Le modèle est essentiellement un dossier avec des données et des fichiers de configuration. Il y a un programme externe qui fonctionne sur un répertoire donné, crée des fichiers de sortie / dossiers, etc. Ce programme je développe est conçu pour gérer efficacement / configurer ces objets de manière conviviale

3) Le problème avec la façon dont je l'ai fait des choses est qu'il est presque impossible à tester, et par conséquent le mouvement du passif Voir modèle de conception de MVP-esque

Je suis en train de faire en sorte que le programme fonctionne indépendamment de la vue. Je ne l'ai pas été en mesure de trouver des exemples où une vue plus complexe, interactif est utilisé avec le motif Voir passif.

Questions:

1) Ai-je besoin de mettre en œuvre une grande interface / vue pour l'ensemble du « look » du programme, puis mettre en œuvre des sous-interfaces / sous-vues pour chacun des TreeView, éditeur, enregistreur, etc.? Ou est-il une meilleure « structure » pour le faire?

2) En ce qui concerne « la remise de » événements de la vue au présentateur / Controller (tout ce que vous souhaitez utiliser la terminologie W.R.T. le modèle de conception Voir passif), ce qui est la façon dont je devrais faire cela? Parfois, j'ai des propriétés simples qui ont besoin d'être mis à jour, et parfois je besoin d'une série de mesures pour se dérouler.

J'aimerais suggestions et des conseils sur ce sujet. Je l'ai parcouru l'Internet, et je ne l'ai pas trouvé des exemples suffisants pour me aider poursuivre ce projet.

Merci à l'avance!

Daniel

Était-ce utile?

La solution

Voici un exemple simple qui démontre le concept de vues passives en utilisant le modèle de conception MVP. Parce que nous utilisons vues passives le point de vue n'a pas connaissance du présentateur. Le présentateur sera simplement abonner à des événements publiés par la vue et agir en conséquence.

Pour commencer, nous devons définir un contrat pour notre point de vue. Ceci est généralement réalisée à l'aide d'une interface, essentiellement, nous voulons avoir un couplage très lâche avec notre point de vue. Nous voulons que la possibilité de passer à différents points de vue ou événement créer des vues pour des simulations de tests unitaires.

Voici un contrat qui décrit une vue simple qui sera utilisé à l'information client d'affichage

public interface ICustomerManagementView
{
    void InitializeCustomers(ICustomer[] customers);
    void DisplayCustomer(ICustomer customer);
    event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged;
}

Il expose une seule méthode InitializeCustomers qui sera utilisé pour initialiser notre point de vue avec des objets de notre modèle.

Nous avons aussi un événement SelectedCustomerChanged qui sera utilisé par notre présentateur recevoir une notification qu'une action a eu lieu dans la vue.

Une fois que nous avons notre contrat, nous pouvons commencer à gérer ces interactions dans notre présentateur.

public class CustomerManagementPresenter
{
    private ICustomer _selectedCustomer;
    private readonly ICustomerManagementView _managementView;
    private readonly ICustomerRepository _customerRepository;

    public CustomerManagementPresenter(ICustomerManagementView managementView, ICustomerRepository customerRepository)
    {
        _managementView = managementView;
        _managementView.SelectedCustomerChanged += this.SelectedCustomerChanged;

        _customerRepository = customerRepository;

        _managementView.InitializeCustomers(_customerRepository.FetchCustomers());
    }

    private void SelectedCustomerChanged(object sender, EventArgs<ICustomer> args)
    {
        // Perform some logic here to update the view
        if(_selectedCustomer != args.Value)
        {
            _selectedCustomer = args.Value;
            _managementView.DisplayCustomer(_selectedCustomer);
        }
    }
}

Dans le présentateur nous pouvons utiliser un autre modèle appelé de href="http://en.wikipedia.org/wiki/Dependency_injection" pour donner accès à notre point de vue et toutes les classes de modèle que nous pourrions avoir besoin. Dans cet exemple, j'ai un CustomerRepository qui est responsable de la récupération des détails du client.

Dans le constructeur, nous avons deux lignes importantes de code, d'une part, nous avons souscrit à l'événement SelectedCustomerChanged à notre avis, il est que nous pouvons effectuer des actions associées. Deuxièmement, nous avons appelé InitilaizeCustomers avec les données du référentiel.

En ce moment, nous avons pas réellement défini une mise en œuvre concrète de notre point de vue, tout ce que nous devons faire est de créer un objet qui implémente ICustomerManagementView . Par exemple, dans une application Windows Forms, nous pouvons faire ce qui suit

public partial class CustomerManagementView : Form, ICustomerManagementView
{
    public CustomerManagementView()
    {
        this.InitializeComponents();
    }

    public void InitializeCustomers(ICustomer[] customers)
    {
        // Populate the tree view with customer details
    }

    public void DisplayCustomer(ICustomer customer)
    {
        // Display the customer...
    }

    // Event handler that responds to node selection
    private void CustomerTreeViewAfterSelect(object sender, TreeViewEventArgs e)
    {
        var customer = e.Node.Tag as ICustomer;
        if(customer != null)
        {
            this.OnSelectedCustomerChanged(new EventArgs<ICustomer>(customer));
        }
    }

    // Protected method so that we can raise our event
    protected virtual void OnSelectedCustomerChanged(EventArgs<ICustomer> args)
    {
        var eventHandler = this.SelectedCustomerChanged;
        if(eventHandler != null)
        {
            eventHandler.Invoke(this, args);
        }
    }

    // Our view will raise an event each time the selected customer changes
    public event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged;
}

Si nous voulions tester notre logique de présentation, nous pourrions se moquer de notre point de vue et d'effectuer certaines affirmations.

EDIT: Inclus args d'événements personnalisés

public class EventArgs<T> : EventArgs
{
    private readonly T _value;

    public EventArgs(T value)
    {
        _value = value;
    }

    public T Value
    {
        get { return _value; }
    }
}

Autres conseils

Je les décomposer en vues séparées avec leurs propres cadeaux, et d'utiliser un « contrôle » présentateur / vue de gérer la délégation de messages entre tous. Non seulement cette testabilité d'aide, mais il va garder vos contrôles remplir SRP aussi.

Donc, dans votre cas, vous pourriez avoir une IFormManager que la fenêtre principale mettra en œuvre, puis un IFileManager, ILoggerWindow etc etc.

Bien qu'il puisse être un peu exagéré à utiliser, je suggère que vous avez un regard sur Smart Client Software Factory (des modèles Microsoft et l'équipe des pratiques) - il n'est pas activement développé plus, mais il a une bonne mise en œuvre de MVP et fait ce genre de choses composition assez bien vue, donc pourrait vous donner quelques bonnes idées.

scroll top