Bug très étrange lors de l'utilisation de Show Dialog sur C # Winform
-
10-07-2019 - |
Question
J'ai créé 2 formulaires dans VS Studio 2008 Express Edition et les déclare avec des sources publiques statiques dans le fichier principal program.cs
Je veux juste basculer entre les deux formulaires avec ShowDialog et Close, mais lorsque vous essayez de fermer le deuxième formulaire et d'ouvrir à nouveau le premier formulaire avec showdialog, vous ne pouvez pas utiliser showDialog lorsque le formulaire est déjà visible, alors qu'il ne l'est pas. vrai puisque je l'ai fermé avant de montrer le deuxième formulaire.
Il m'a demandé de définir la propriété visible du formulaire sur false avant d'utiliser showdialog. Je l'ai donc fait
internal static void CloseSecondForm(FirstForm FirstForm)
{
FirstForm .Close();
SecondForm.Visible = false;
SecondForm.ShowDialog();
}
Mais ensuite, il est indiqué que je ne peux pas utiliser ShowDialog car le formulaire est déjà affiché en mode de dialogue et que je dois le fermer. Alors j'ai fait ce qu'il m'a demandé
internal static void CloseSecondForm(FirstForm FirstForm)
{
FirstForm .Close();
SecondForm.Visible = false;
SecondForm.Close();
SecondForm.ShowDialog();
}
Mais il prétend toujours que le formulaire est déjà ouvert avec ShowDialog!
Est-ce un bug dans mon prog ou dans Winform?
Mise à jour: il s’agit de tout le code que j’ai posté dans la cinquième réponse (je souhaite utiliser showdialog et ne pas le montrer car j’ai peut-être un troisième formulaire en arrière-plan auquel je ne souhaite pas que l’utilisateur accède):
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 = new Form1();
Form2 = new Form2();
Form1.ShowDialog();
Application.Run();
}
// called from Form1 BUTTON
internal static void ShowForm2(Form1 Form1)
{
Form1.Hide();
Form2.ShowDialog();
}
// called from Form2 BUTTON
internal static void ShowForm1(Form2 Form2)
{
Form2.Hide();
Form1.ShowDialog();
}
J'ai essayé avec Hide comme suggéré mais cela ne fonctionne pas non plus. C’est tout le programme, ce que je veux faire est très simple: j’ai deux formulaires créés initialement dans le programme avec un bouton sur chaque formulaire pour se fermer et ouvrir l’autre. Je mets toute la logique dans program.cs ci-dessous:
using System;
using System.Windows.Forms;
namespace twoforms
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
///
public static Form1 Form1;
public static Form2 Form2;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 = new Form1();
Form2 = new Form2();
Form1.ShowDialog();
Application.Run();
}
// called from Form1 BUTTON
internal static void ShowForm2(Form1 Form1)
{
Form1.Hide();
Form2.ShowDialog();
}
// called from Form2 BUTTON
internal static void ShowForm1(Form2 Form2)
{
Form2.Hide();
Form1.ShowDialog();
}
}
}
La solution
Cela provient de MSDN:
Quand un formulaire est affiché sous forme de modal boîte de dialogue, en cliquant sur le bouton Fermer (le bouton avec un X à la coin supérieur droit du formulaire) provoque la forme à cacher et la La propriété DialogResult doit être définie sur DialogResult.Cancel. Contrairement au modèle formulaires, la méthode Close n'est pas appelée .NET Framework lorsque l'utilisateur clique sur le bouton de fermeture d'un formulaire boîte de dialogue ou définit la valeur de la Propriété DialogResult. Au lieu de cela le formulaire est caché et peut être montré à nouveau sans créer une nouvelle instance du boite de dialogue. Parce qu'un formulaire affiché comme une boîte de dialogue n'est pas fermée, vous doit appeler la méthode Dispose du forme lorsque la forme n'est plus nécessaire par votre application.
Ainsi, une fois que vous affichez un formulaire à l'aide de ShowDialog et que vous souhaitez le fermer, laissez-le simplement renvoyer DialogResult.Cancel. Ceci cachera (il sera toujours en mémoire) votre première forme. Vous pouvez maintenant appeler ShowDialog sur votre deuxième formulaire. Encore une fois, si vous souhaitez passer au premier formulaire, laissez le deuxième formulaire renvoyer DialogResult.Cancel et appelez simplement ShowDialog dans le premier formulaire.
Autres conseils
Ceci est un bogue dans votre programme. Lorsque vous avez deux occurrences d'un formulaire (appelez-les A et B), vous ne pouvez évidemment pas toujours montrer l'une de l'autre à l'aide de ShowDialog. Si vous pouviez faire cela, cela voudrait dire que A montre B modalement, et B montre ensuite A modale, et A montre ensuite B modale, etc. Cela serait comme construire une maison avec deux briques, où vous continuez simplement à prendre la brique inférieure. en le plaçant au-dessus de l'autre.
Votre meilleure solution consiste à ne pas rendre ces formulaires statiques, mais simplement à créer de nouvelles instances de chaque formulaire selon vos besoins. Votre deuxième solution consiste à utiliser Show au lieu de ShowDialog; de toute façon, si vous n’avez qu’un de ces formulaires à la fois, ShowDialog n’a aucun but.
Les formes statiques sont presque toujours une mauvaise idée (et je suis poli sur "presque"). Si la création de vos formulaires prend beaucoup de temps, vous devez identifier la ressource qui met si longtemps à se charger et la mettre en cache sous forme d'objet statique, au lieu d'essayer de mettre en cache l'intégralité du formulaire sous forme statique.
Essayez d’utiliser Hide () au lieu de Close (). J'ai eu un problème similaire dans le passé et Hide () a travaillé pour moi.
Je pense que vous devriez vraiment traiter les dialogues Modal comme des appels de méthodes et essayer d'utiliser le résultat de l'appel à ShowDialog pour déterminer ce que vous voulez faire ensuite. si vous devez basculer entre les boîtes de dialogue, vous devez utiliser une sorte de résultat (peut-être simplement DialogResult voir mon exemple) ou une propriété publique de la boîte de dialogue pour déterminer si vous devez afficher une autre boîte de dialogue, Si vous devez appeler une boîte de dialogue modale une autre, vous devriez la considérer comme une pile de formulaires, qui effectivement (même si vous rendez l’invisible invisible avant d’en appeler une autre) placent l’une sur l’autre. Vous voulez vraiment minimiser cet empilement de formulaires.
Ceci est un peu un exemple artificiel, mais chaque formulaire ici a simplement un seul bouton avec DialogResult défini sur OK.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
bool exit = false;
while (true)
{
if (exit) break;
using (Form1 frm = new Form1())
{
switch(frm.ShowDialog())
{
case DialogResult.OK:
break;
default:
exit = true;
break;
}
}
if(exit) break;
using (Form2 frm = new Form2())
{
switch(frm.ShowDialog())
{
case DialogResult.OK:
break;
default:
exit = true;
break;
}
}
}
}
pour quitter, cliquez simplement sur le bouton rouge de fermeture (x).
Vérifiez la différence entre Fermer
et Masquer
. Et la différence entre Show
et ShowDialog
.
Ce que vous voulez accomplir n’est pas vraiment clair. vous décrivez seulement (partiellement) ce que vous avez fait dans le code et le symptôme du problème que vous rencontrez. Pourriez-vous s'il vous plaît décrire ce que vous essayez de faire?
Si votre objectif est d’avoir deux boîtes de dialogue apparaissant dans la fenêtre principale et qu’un seul des deux puisse être visible en même temps, il existe peut-être de meilleures solutions que d’utiliser deux Form
instances que vous affichez à l'aide de ShowDialog
.
Avez-vous pensé à utiliser un Formulaire
de dialogue qui ne change que l'apparence en fonction de la situation?