2016-10-09 2 views
0

Je rencontre souvent cette situation lorsque j'écris du code pour une interface graphique et je voudrais savoir comment résoudre ce problème. La situation est la suivante:Conception d'une boucle for avec des éléments spécifiquement nommés

J'ai un certain nombre d'éléments identiques sur mon interface graphique qui ont des noms de variables, à savoir je 10 boutons « identiques » qui sont nommés Button1, Button2, Button3, etc ...

Le texte affiché des boutons est mis à jour dans le code et je veux vérifier quand ils sont mis à jour s'ils remplissent une certaine condition, puis changer la couleur du texte en fonction de cette condition. Donc, pour button1 j'écrire:

if (Button1.text == "true"){ 
    Button1.textcolor = blue} 
else if (Button1.text == "false"){ 
    Button1.textcolor = red} 

Maintenant, il semble inutile d'avoir à écrire ce code à nouveau pour chacun des 10 boutons, en remplaçant le nom de la variable Button1 avec de Bouton2 et ainsi de suite jusqu'à Button10. Y at-il un moyen de modifier la partie "Button1" du code dans une boucle et de garder tout le reste le même? Ainsi, un exemple pseudo-code de ce que je suis à la recherche serait:

for (all buttons in (button1-button10)){ 
    if (thisbutton.text == "true"){ 
     thisbutton.textcolor = blue} 
    else if (thisbutton.text == "false"){ 
     thisbutton.textcolor = red}} 

Je ne sais pas comment aborder le mieux ce scénario et recevoir des suggestions et des conseils à ce sujet.

Merci

+1

Il existe plusieurs façons, mais en fonction de votre configuration, vous pourriez être bien meilleur que l'autre. Utilisez-vous WinForms? Où sont ces boutons déclarés? –

+0

@Uno J'utilise Wpf en C# - j'ajoute graphiquement les boutons dans Visual Studio, puis je peux les référencer dans mon code. Je crois qu'ils sont déclarés dans le code xaml de l'interface graphique. –

+0

Vous devez mettre à jour vos balises de questions pour inclure WPF. Ma réponse est pour winforms. –

Répondre

1

Chaque fois que vous avez un ensemble d'objets similaires ne pas créer une variable pour chaque instance de ces objets, au lieu de les mettre dans une seule collection. Ensuite, vous pouvez facilement en boucle cette liste et manipuler les objets en son sein:

var buttons = new List<Button>(); 

// put the buttons into the list using buttons.Add 

for (var b in buttons) 
{ 
    if (b.text == "true") 
    { 
     b.textcolor = blue 
    } 
    else 
    { 
     b.textcolor = red 
    } 
} 

Vous pouvez également utiliser un GridView pour mettre tous ces boutons dans une grille ragular.

+0

Merci pour votre réponse, cela semble être une bonne solution. Je me demande s'il pourrait y avoir un moyen de le faire "à la volée" sans créer un objet spécial pour cela? Je suis encore nouveau à C# et je me demande s'il existe un moyen de faire défiler les différents objets et de ne pas utiliser un conteneur spécial? Merci –

+0

Bien sûr que vous * pourriez * le faire par réflexion lorsque vos boutons sont membres de votre classe (pas seulement les variables dans une méthode !!). Cependant vous * ne devriez pas *. Vous n'aurez pas besoin de 10 variables pour 10 instances, tout ce dont vous avez besoin est une liste * one * contenant ces 10 instances. – HimBromBeere

0

Créez votre propre bouton.

using System.Windows.Forms; 
using System.Drawing; 

namespace TestApp 
{ 
    public class TheButton : Button 
    { 
     public void ChangeColor() 
     { 
      ForeColor = (Text == "true") ? Color.Blue : Color.Red ; 

     } 
    } 
} 

Reconstruire votre solution, et vous devriez voir theButton dans la boîte à outils, dans votre formulaire, ajoutez une classe de conteneur, comme un panneau, et ajoutez vos instances de la classe theButton.

Vous pouvez alors écrire une méthode, comme:

private void ChangeAllButtons() 
    { 
     foreach (var control in panel1.Controls.Cast<object>().Where(control => (control as TheButton) != null)) 
     { 
      (control as TheButton).ChangeColor(); 
     } 
    } 

Vous devrez décider du meilleur endroit pour appeler ChangeAllButtons().

+0

Merci pour votre réponse, cela semble aussi une solution viable. Votre boucle foreach est intéressante car il me semble que je pourrais faire une boucle sur les objets qui se trouvent dans l'objet parent des boutons et les utiliser de la même manière que votre exemple. Je devrai regarder dans les boucles foreach plus en détail. –

+0

Est-ce que WPF a .Controls? Pensez-vous à WinForms? Je ne peux pas voir cette propriété dans mon assemblée. –

0

Il y a plusieurs façons d'aborder cela. Comme les boutons sont créés par le concepteur comme des champs de la fenêtre/du panneau, pour les lister, vous devez analyser l'arborescence WPF (ou utiliser une réflexion sur le panneau de la fenêtre principale qui n'est pas vraiment élégante).

Pour obtenir tous les Button enfants, vous pouvez utiliser cette méthode:

public static IEnumerable<T> EnumVisualOfType<T>(Visual visual) where T : Visual 
{ 
    for (var i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++) 
    { 
     var visualChild = (Visual)VisualTreeHelper.GetChild(visual, i); 

     foreach (var child in EnumVisualOfType<T>(visualChild)) 
      yield return child; 

     var childVisual = visualChild as T; 

     if (childVisual != null) 
      yield return childVisual; 
    } 
} 

Et puis invoquer:

var allButtons = EnumVisualOfType<Button>(window).ToList(); 

Et vous avez la liste de tous les boutons (que vous pouvez, Bien sûr, filtrez sur une propriété spécifique si vous le souhaitez) et vous pouvez écrire votre code une fois et l'utiliser dans une boucle foreach.

Vous pouvez également ajouter explicitement tous vos boutons à une liste lorsque le panneau est créé, mais vous devrez alors vous souvenir de les ajouter manuellement chaque fois que vous en créez un nouveau.