2009-12-01 5 views
-1

J'ai trouvé une question que je belive est ce que je cherchais, mais il y avait certaines choses que je ne suivais pas dans les réponses. Par conséquent, je voudrais poser la question d'une manière différente (merci pour votre patience). Voici le lien que je fais référence à:C# - Éviter la duplication entre la logique WinForm et UserControl

How to avoid duplicating logic on two similar WinForms?

OK. J'ai un dialogue que j'ai créé. Nous avons des contrôles pour l'entrée utilisateur, des boutons pour afficher d'autres dialogues (pour obtenir d'autres entrées), etc. Esthétiquement, je préfère le dialogue avec les contrôles disposés verticalement. De toute façon, je pensais aussi à créer une version UserControl de cette boîte de dialogue. Ce contrôle UserControl aurait tous les mêmes contrôles, et tous la même logique, mais les contrôles seraient disposés tout à fait différent (plus horizontal, puis vertical).

Donc, je ne peux pas créer un autre (3) UserControl que je laisse tomber la forme Orignal, et sur le UserControl je veux créer. (Ce 3ème UserControl contiendrait alors toute la logique - donc, le partage entre les deux). Je ne peux pas le faire à cause des différentes dispositions.

Je n'ai aucun problème à créer les deux (Form, UserControl), avec les contrôles disposés différemment, mais je ne veux pas 'copier-coller' toute la logique de l'un à l'autre.

Cela ne semble pas être le cas pour MVP ou MVC. Mon modèle est le dialogue lui-même. La boîte de dialogue est initialisée avec certaines valeurs, oui, mais une fois initialisée, le "Modèle" devient une nouvelle Entrée Utilisateur (que je saisis ensuite quand ils pressent le bouton OK).

Prenez par exemple ce code (un événement pour un de mes boutons de cette boîte de dialogue):

private void EditQuery_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      EditQueryParameters(); 
     } 
     catch (System.Exception ex) 
     { 
      // TODO: Write ErrMsg to Log file. 
      MessageBox.Show("Edit Query Parameters Error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
    } 

    private void EditQueryParameters() 
    { 
     if (m_ReportType.QueryScoreDetails && optPickDetail.Checked) 
     { 
      // This brings up a different type of dialog 
      QueryDetails(); 
      return; 
     } 

     // DateRange, StartDate, and EndDate are all saved from the last time 
     // I called this dialog 
     DateType DtType = new DateType(m_ReportType.DBDateRangeField, 
      m_DateRange, m_StartDate, m_EndDate); 
     // StartTime, EndTime too! 
     TimeType TmType = new TimeType(m_ReportType.DBTimeRangeField, 
      m_StartTime, m_EndTime); 

     List<AdvancedFilter> Filters = null; 
     if (lstAdvancedQuery.Items.Count > 0) 
     { 
      Filters = new List<AdvancedFilter>(); 
     } 
     for (int i = 0; i < lstAdvancedQuery.Items.Count; ++i) 
     { 
      Filters.Add((AdvancedFilter)lstAdvancedQuery.Items[i]); 
     } 

     // QueryType is also saved from the last time I called QueryBuilder 
     QueryBuilder QryBuilder = new QueryBuilder(m_ReportType.DBCatalog, m_ReportType.DBTable, 
      m_QueryType, ref DtType, ref TmType, ref Filters); 

     // I am using Visual WebGUI, I have to do it this way 
     QryBuilder.Closed += new EventHandler(QryBuilder_Closed); 
     QryBuilder.ShowDialog(); 
    } 

Je veux dire, je suppose que je pourrais avoir une certaine classe « logique », ce qui expose quelque chose comme:

public void EditQueryParameters(ref ReportType RptType, bool PickDetail, 
     string DateRange, DateTime StartDate, DateTime EndDate, 
     DateTime StartTime, DateTime EndTime, string QueryType) 
    { 
     if (ReportType.QueryScoreDetails && PickDetail) 
     { 
      // This brings up a different type of dialog 
      QueryDetails(); 
      return; 
     } 


     DateType DtType = new DateType(ReportType.DBDateRangeField, 
      DateRange, StartDate, EndDate); 
     TimeType TmType = new TimeType(ReportType.DBTimeRangeField, 
      StartTime, EndTime); 

     // Yikes, more stuff to add to the signature of my method 
     // Will have to pull this outside the method and pass in Filters 
     List<AdvancedFilter> Filters = null; 
     if (lstAdvancedQuery.Items.Count > 0) 
     { 
      Filters = new List<AdvancedFilter>(); 
     } 
     for (int i = 0; i < lstAdvancedQuery.Items.Count; ++i) 
     { 
      Filters.Add((AdvancedFilter)lstAdvancedQuery.Items[i]); 
     } 

     // QueryType is also saved from the last time I called QueryBuilder 
     QueryBuilder QryBuilder = new QueryBuilder(ReportType.DBCatalog, ReportType.DBTable, 
      QueryType, ref DtType, ref TmType, ref Filters); 

     // I am using Visual WebGUI, I have to do it this way 
     QryBuilder.Closed += new EventHandler(QryBuilder_Closed); 
     QryBuilder.ShowDialog(); 
    } 

Il y a beaucoup de réglages à utiliser cette méthode. Je ne sais pas, peut-être que je cherche quelque chose de plus .. "slick"? En plus de cela, regardez un peu (pas tout) mon code init (cela est appelé par constructor ou form_Load, il ne semble pas utile de l'ajouter à la classe logique, donc tout est "coupé" et coller » entre les deux):

private void InitializeUserDefinedTitle() 
    { 
     txtUserTitle.Text = m_UserTitle; 
    } 

    private void InitializePrintSelectionCriteria() 
    { 
     // Print Selection Criteria 
     chkSelectionCriteria.Checked = m_printSelectionCriteria; 
    } 

    private void InitializeTrendBy() 
    { 
     cmbTrend.Items.AddRange(Enum.GetNames(typeof(TrendBy))); 
     cmbTrend.SelectedIndex = (int)m_TrendBy; 
     cmbTrend.Visible = m_ReportType.TrendVisible; 
     lblTrend.Visible = m_ReportType.TrendVisible; 
    } 

En résumé, le WinForm original est une boîte de dialogue qui intialized avec les données (constructeur), est affiché à l'utilisateur pour l'entrée, quand ils OK la boîte de dialogue que les données sont extraites (et que les données sont stockées en dehors de la boîte de dialogue, dans les variables membres, pour la prochaine fois qu'elles appellent la boîte de dialogue - c'est parce que nous voulons montrer ce qu'ils ont choisi/entré en dernier).

Ce type de dialogue que je viens de décrire sera également un contrôle utilisateur et la logique devrait être partagée entre les deux.

Merci.

+1

Si c'est juste la mise en page que vous cherchez à modifier, avez-vous regardé dans le contrôle FlowLayoutPanel? Il permet un positionnement rapide et facile vers l'horizon et le dos ... –

+0

Je suis un programmeur C++ qui a appris le C# à la volée (le mois dernier), donc je n'en ai jamais entendu parler. Merci beaucoup. (Comment puis-je vous donner un certain type de points ou quelque chose?) – JustLooking

Répondre

1

au lieu d'encapsuler la logique, j'intégrerait la mise en page. Utilisez une propriété du contrôle utilisateur pour spécifier la mise en page souhaitée. Ensuite, où que ce soit (forme autonome, une des trois instances sur le même formulaire, peu importe), vous y accédez et spécifiez la mise en page de la même manière.

Comme pour comment pour encapsuler la mise en page, il y a un tas de possibilités. Vous pouvez simplement le faire par programmation, c'est-à-dire écrire chaque version du code de disposition.(La version programamatic serait plus propre si vous utilisiez une sorte de conteneur de disposition, comme les panneaux dans WPF.) Vous pouvez dessiner la disposition dans un concepteur et copier le code généré. Les différentes versions de la logique de mise en page peuvent être placées dans des méthodes privées ou encapsulées dans des objets.

+0

C'est aussi une bonne idée. Je n'utilise pas WPF, et j'aime bien l'idée de "copier le code généré" (mais pas vendue dessus). Vous m'avez donné quelques idées à manipuler aujourd'hui. – JustLooking

2

Vous pouvez faire deux contrôles A et B, chacun contenant les mêmes boutons et/ou d'autres contrôles d'entrée disposés différemment. Les contrôles A et B auront des propriétés et des événements identiques. Le formulaire (ou le troisième contrôle) contiendra les gestionnaires d'événements qui permettent à la logique d'être contenue dans un seul endroit.

Vous pouvez afficher commande A ou B en utilisant la propriété visible ou en ajoutant un à la propriété container.controls, le récipient étant la forme contenant ou de contrôle. Et, par exemple, au lieu d'avoir un gestionnaire pour button1 dans les contrôles A et B qui gère la logique complète de la pression sur le bouton, les gestionnaires pour button1 dans le contrôle A et B souleveraient juste un événement qui sera géré par le conteneur du contrôle A ou B.

+0

Idée intéressante, je vais l'essayer aujourd'hui. – JustLooking

Questions connexes