Le meilleur moyen d'accéder à un contrôle sur une autre forme dans les Windows Forms?
Tout d'abord, c'est une question à propos d'une application de bureau à l'aide de Windows Forms, pas un ASP.NET question.
J'ai besoin d'interagir avec les contrôles sur d'autres formes. Je suis en train d'accéder à des contrôles à l'aide, par exemple, la suite...
otherForm.Controls["nameOfControl"].Visible = false;
Il ne fonctionne pas de la façon dont je voudrais attendre. Je me retrouve avec une exception générée à partir de Main
. Cependant, si je fais les contrôles public
au lieu de private
, je peux alors accéder directement à eux, comme si...
otherForm.nameOfControl.Visible = false;
Mais est-ce la meilleure façon de le faire? Est de rendre le contrôle public
sur l'autre forme considérés comme des "meilleures pratiques"? Est-il un "meilleur" moyen de contrôles d'accès sur une autre forme?
Plus D'Explications:
C'est en fait une sorte de suite d'une autre question que j'avais posée, La meilleure méthode pour la création d'un “arbre des préférences de la boîte de dialogue” type de l'interface en C#?. La réponse que j'ai eu était grand et résolu de nombreux, de nombreux problèmes d'organisation j'ai eu en termes de maintien de la droite de l'INTERFACE utilisateur et facile à travailler à la fois dans le temps et au moment de la conception. Cependant, il a apporté cette tatillonne question de facilement contrôler d'autres aspects de l'interface.
En gros, j'ai une racine qui instancie beaucoup d'autres formes qui sont assis à une table ronde sur la racine. Ainsi, par exemple, un bouton radio sur l'un de ces sous-formulaires pourriez avoir besoin de modifier l'état d'une barre d'état icône sur l'essentiel, la forme de base. Dans ce cas, j'ai besoin d'un sous-formulaire à parler à la commande dans la barre d'état de la société mère (racine) de la forme. (J'espère qu'un sens, pas dans un "à qui la" sorte de façon.)
- Êtes-vous accès à ces contrôles de l'extérieur par un thread séparé?
- Assurez-vous de mettre cela dans sa propre classe, qui prend forme dans le constructeur. Elle doit implémenter l'interface IDisposable et les biens aliénés lorsque vous avez terminé. Il doit également utiliser le suivi de référence (augmentation/diminution d'un nombre entier de manière récursive en l'appelant ne cause pas de problèmes) et seulement de cacher les contrôles lors de cette passe de 0 à 1. Et seulement de les montrer à nouveau quand il passe de 1 à 0.
Vous devez vous connecter pour publier un commentaire.
Au lieu de faire de la commande publique, vous pouvez créer une propriété qui contrôle sa visibilité:
Cela crée un bon accesseur pour que le contrôle qui ne sont pas exposer le contrôle de l'ensemble des propriétés.
Personnellement, je recommanderais PAS de le faire... Si c'est de répondre à une sorte d'action, et il doit changer son apparence, je préfère élever un événement et de le laisser s'en sortir...
Ce type de couplage entre les formes toujours me rend nerveux. J'essaie toujours de garder l'INTERFACE utilisateur de la lumière et indépendant que possible..
J'espère que cette aide. On pourrait peut-être étendre sur le scénario si ce n'?
La première ne fonctionne pas bien. Les contrôles sur un formulaire sont privée, visible uniquement pour la forme par la conception.
Pour rendre tout cela public est également pas la meilleure façon.
Si je voudrais exposer quelque chose du monde extérieur (qui peut aussi signifier une autre forme), je fais un bien public pour elle.
Vous pouvez utiliser cette propriété publique pour masquer ou afficher la commande ou de demander le contrôle de la visibilité actuelle de la propriété:
Vous pouvez également exposer tous les contrôles, mais je pense que c'est trop beaucoup, vous devez vous rendre visible uniquement les propriétés que vous voulez vraiment utiliser de l'extérieur de la forme actuelle.
Après avoir lu les détails supplémentaires, je suis d'accord avec robcthegeek: déclencher un événement. Créer un personnalisé EventArgs et de passer les paramètres nécessaires à travers elle.
Supposons que vous avez deux formes, et que vous souhaitez masquer la propriété d'une forme par une autre:
et quand vous voulez obtenir le focus de form1 par form2 sur le bouton:
Je voudrais traiter dans le formulaire parent. Vous pouvez informer l'autre forme, il a besoin de modifier lui-même à travers un événement.
La meilleure pratique #4 si vous utilisez les formulaires non modale.
Vous pouvez
Meilleure pratique #4 si vous utilisez les formulaires non modale.
Avec la propriété (en surbrillance) je peux obtenir l'instance de la MainForm classe. Mais c'est une bonne pratique? Que recommandez-vous?
Pour cela, j'utilise la propriété MainFormInstance qui s'exécute sur la méthode OnLoad.
Je suis d'accord avec l'aide d'événements pour cela. Depuis, je soupçonne que vous êtes en train de construire un MDI-application (puisque vous créer de nombreuses formes d'enfants) et crée de windows de façon dynamique et pourrait ne pas savoir quand vous désabonner des événements, je vous recommande de prendre un coup d'oeil à La Faiblesse Des Motifs D'Événement. Hélas, ce n'est disponible que pour framework 3.0 et 3.5, mais quelque chose de semblable peut être mise en place assez facile avec les références faibles.
Cependant, si vous souhaitez trouver un contrôle dans un formulaire basé sur la forme de référence, il ne suffit pas simplement de regarder la forme du contrôle de la collecte. Puisque chaque commande de contrôle de la collecte, vous devrez répéter à travers eux tous pour trouver un contrôle spécifique. Vous pouvez le faire avec ces deux méthodes (ce qui peut être amélioré).
@Lars, bon appel sur la passant autour de la Forme des références, vu ainsi moi-même. De méchant. Jamais vu d'entre eux sont passés à la couche BLL si! Qui n'a même pas de sens! Qui pourrait avoir d'importantes répercussions sur les performances? Si quelque part dans la BLL la référence a été conservé, le formulaire de rester dans la mémoire de droit?
Vous avez toute ma sympathie! 😉
@Ed, RE votre commentaire à propos de rendre les modes UserControls. Dylan l'a déjà souligné que la racine instancie de nombreux enfant formes, donnant l'impression d'une application MDI (où je suis en supposant que les utilisateurs peuvent vouloir fermer les diverses Formes). Si je suis bon dans cette hypothèse, je pense qu'ils seraient les mieux gardés comme des formes. Tout à fait ouvert à la correction bien 🙂
Faire à votre enfant de formes vraiment besoin d'être des Formes? Pourraient-ils être les contrôles de l'utilisateur à la place? De cette façon, ils peuvent facilement déclencher des événements pour la forme principale de la poignée et vous pourriez mieux encapsuler leur logique en une seule classe (au moins, en toute logique, ils sont, après toutes les classes déjà).
@Lars: Vous êtes ici. C'était quelque chose que j'ai fait à mes débuts jours et n'ai pas eu à le faire puisque, c'est pourquoi j'ai d'abord proposé d'augmenter les un événement, mais mon autre méthode serait vraiment casser un semblant d'encapsulation.
@Rob: Oui, de sons sur la droite :). 0/2 sur celui-ci...
Vous ne devriez jamais accéder à un point de vue du contenu à partir d'un autre si vous êtes en train de créer plus de commandes complexes/modules/composants. Sinon, vous devez le faire par le biais de la norme de conception Modèle-Vue-Contrôleur de l'architecture: vous devez Vous connecter à l'état activé des contrôles vous vous souciez de pour certains au niveau du modèle de prédicat qui fournit la bonne information.
Par exemple, si je voulais activer un bouton Enregistrer uniquement lorsque toutes les informations ont été entrées, j'aurais un prédicat méthode qui indique si le modèle d'objets représentant la forme, sont dans un état qui peut être sauvé. Ensuite, dans le contexte où je suis pour choisir d'activer le bouton, je voudrais utiliser le résultat de cette méthode.
C'est beaucoup plus propre séparation de la logique métier de la présentation de la logique, permettant à la fois de leur évolution de façon plus autonome, vous permettant de créer un front-end avec plusieurs back-end, ou plusieurs front-end avec un seul back-end avec facilité.
Il sera aussi beaucoup, beaucoup plus facile à écrire unitaires et des tests d'acceptation, parce que vous pouvez suivre un "Faire Confiance, Mais Vérifier" modèle en procédant de la sorte:
Vous pouvez écrire un ensemble de tests de configurer votre modèle d'objets de différentes façons, et vérifier que le "sauvé" le prédicat renvoie un résultat approprié.
Vous pouvez écrire un ensemble distinct de vérifier si votre bouton de sauvegarde est connecté d'une façon appropriée à la "sauvé" le prédicat (tout ce qui est de votre cadre, en Cocoa sur Mac OS X ce serait souvent par une liaison).
Tant que les deux séries de tests sont de passage, vous pouvez être sûr que votre interface utilisateur va travailler de la façon dont vous le souhaitez.
Cela ressemble à un candidat de choix pour la séparation de la présentation du modèle de données. Dans ce cas, vos préférences doivent être stockés dans une catégorie distincte que les feux de l'événement mises à jour chaque fois qu'un particulier des modifications de la propriété (regardez dans INotifyPropertyChanged si vos biens sont un ensemble discret, ou dans un seul cas, s'ils sont plus libres-forme basé sur du texte touches).
Dans votre arborescence, vous allez faire les modifications à votre modèle de préférences, il sera alors le feu à un événement. Dans d'autres formes, vous pourrez vous abonner aux changements qui vous intéresse. Dans le gestionnaire d'événement que vous utilisez pour vous abonner à la modification de la propriété, vous utilisez ce.InvokeRequired pour voir si vous êtes sur le bon thread pour rendre l'INTERFACE d'appel, si ce n'est, puis de les utiliser.BeginInvoke d'appeler la méthode souhaitée pour mettre à jour le formulaire.
Étape 1:
Étape 2:
Changement modificateur public interne. .Net utilise délibérément privé modificateur au lieu de le public, en raison de prévenir tout accès illégal à vos méthodes/propriétés/contrôle de votre projet. En fait, le public modificateur peut accessibles de partout, de sorte qu'Ils sont vraiment dangereux. Tout le corps de votre projet peut accéder à vos méthodes/propriétés. Mais, En interne, pas de modificateur de corps (d'autres de votre projet en cours) peuvent accéder à vos méthodes/propriétés.
Supposons que vous créez un projet, qui a un secret les domaines. Donc, Si ces champs étant accessible de votre projet, il peut être dangereux, et à l'encontre de vos idées initiales. Comme une bonne recommandation, je peux dire toujours utiliser internes modificateur au lieu de public modificateur.
Mais une étrange!
Je dois dire aussi dans VB.Net alors que nos méthodes/propriétés sont encore privés, il peut être accessible à partir d'autres formes/classe en appelant le formulaire comme une variable sans aucun problème ailleurs.
Je ne sais pas pourquoi dans ce langage de programmation comportement est différent de C#. Comme nous le savons tous les deux sont en utilisant la même Plate-forme et ils prétendent qu'ils sont presque la même extrémité Arrière de la Plateforme, mais comme vous le voyez, ils continuent de se comporter différemment.
Mais j'ai résolu le problème avec les deux approches. Soit; à l'aide de l'Interface (Qui n'est pas à recommander, comme vous le savez, les Interfaces ont généralement besoin modificateur public, et à l'aide d'un modificateur public n'est pas recommandé (Comme je vous l'ai dit ci-dessus)),
Ou
Déclarer la totalité de votre Forme en quelque part de classe statique et statique de la variable, et il est encore interne modificateur. Puis, quand vous supposez que de l'utiliser pour montrer aux utilisateurs, donc passer de nouvelles
Form()
la construction de cette classe statique/variable. Maintenant, Il peut être Accessible à tous où que vous le souhaitez. Mais vous avez encore besoin de quelque chose de plus.Vous déclarez votre élément interne modificateur de trop dans le Fichier de Concepteur de Formulaire. Alors que votre Formulaire est ouvert, il peut être accessible de partout. Il peut fonctionner très bien pour vous.
Considérer Cet Exemple.
Supposons que vous souhaitez accéder à une Forme de zone de texte.
De sorte que la première tâche est la déclaration d'une variable statique dans une classe statique (La raison de la statique est la facilité d'accès, sans l'aide de nouvelles clétage à l'avenir).
Seconde aller à la classe de concepteur de Formulaire qui suppose d'être accessible par d'autres Formes. Le changement de son modificateur de zone de texte de la déclaration de privé interne. Ne vous inquiétez pas; .Net ne jamais changer de nouveau pour le privé modificateur après votre évolution.
Troisième, quand vous voulez l'appeler, qui forme à s'ouvrir pour passer à la nouvelle Forme de la Construction de cette variable statique-->>static de la classe.
Quatrième; de toutes les autres Formes (où que ce soit dans votre projet, vous pouvez accéder à cette forme de contrôle/alors que Depuis est ouverte.
Regardez le code ci-dessous (Nous avons trois objets.
1 - une classe statique (dans notre exemple nous le nom
A
)2 - Toute Forme d'autre qui veut ouvrir la Forme finale (a zone de texte, dans notre exemple
FormB
).3 - La Forme réelle qui nous devons être ouverts, et nous supposons qu'à l'accès à son intérieur
TextBox1
(dans notre exempleFormC
).Regarder les codes ci-dessous:
Vous pouvez accéder à cette Variable statique (ici
FormC
) et de son contrôle interne (iciTextbox1
) partout et chaque fois que vous le souhaitez, tout enFormC
est ouvert.Tout Commentaire, idée, laissez-moi savoir. Je heureux de vous entendre ou de tout le corps d'autre à propos de ce sujet plus. Honnêtement, j'ai eu quelques problèmes à l'égard de ce problème dans le passé. Le meilleur moyen est la deuxième solution qui, je l'espère, il peut travailler pour vous. Laissez-moi savoir toute nouvelle idée/suggestion.