Suite à cette question , est-il possible de détecter si on est en mode conception ou en mode exécution à partir du constructeur d'un objet?
Je me rends compte que ce n'est peut-être pas possible et que je devrai changer ce que je veux, mais pour l'instant je m'intéresse à cette question spécifique.
Vous pouvez utiliser l'énumération LicenceUsageMode dans l'espace de noms System.ComponentModel
:
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Cherchez-vous quelque chose comme ça:
public static bool IsInDesignMode()
{
if (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1)
{
return true;
}
return false;
}
Vous pouvez également le faire en vérifiant le nom du processus:
if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
return true;
Composant ... autant que je sache n'a pas la propriété DesignMode. Cette propriété est fournie par Control. Mais le problème est que lorsque CustomControl est situé dans un formulaire dans le concepteur, ce CustomControl s'exécute en mode exécution.
J'ai constaté que la propriété DesignMode ne fonctionne correctement que dans Form.
IMPORTANT
Il existe une différence entre Windows Formulaires ouWPF!!
Ils ont des concepteurs différents et ont besoin de contrôles différents . En outre, il est délicat de mélanger des contrôles Forms et WPF. (par exemple, des contrôles WPF dans une fenêtre de formulaire)
Si vous avez Windows Formulaires uniquement , utilisez ceci:
Boolean isInWpfDesignerMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Si vous avez WPF uniquement , utilisez cette vérification:
Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");
Si vous avez un usage mixte de Forms et WPF, utilisez un chèque comme celui-ci:
Boolean isInWpfDesignerMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");
if (isInWpfDesignerMode || isInFormsDesignerMode)
{
// is in any designer mode
}
else
{
// not in designer mode
}
Pour voir le mode actuel, vous pouvez afficher un MessageBox pour le débogage:
// show current mode
MessageBox.Show(String.Format("DESIGNER CHECK: WPF = {0} Forms = {1}", isInWpfDesignerMode, isInFormsDesignerMode));
Remarque:
Vous devez ajouter les espaces de noms System.ComponentModel et System.Diagnostics .
Les contrôles (Forms, UserControls, etc.) héritent de Component class
qui a bool property DesignMode
so:
if(DesignMode)
{
//If in design mode
}
Vous devez utiliser la propriété Component.DesignMode. Autant que je sache, cela ne devrait pas être utilisé par un constructeur.
Une autre méthode intéressante est décrite sur ce blog: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode -ou-usermode/
Fondamentalement, il teste l'assemblage d'exécution référencé statiquement à partir de l'entrée Assembly. Cela élimine la nécessité de suivre les noms des assemblées ('devenv.exe', 'monodevelop.exe' ..).
Toutefois, cela ne fonctionne pas dans tous les autres scénarios, où l'assembly est chargé dynamiquement (VSTO en est un exemple).
Avec la coopération du concepteur ... Il peut être utilisé dans les contrôles, les composants, dans tous les lieux
private bool getDesignMode()
{
IDesignerHost Host;
if (Site != null)
{
Host = Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (Host != null)
{
if (Host.RootComponent.Site.DesignMode) MessageBox.Show("Design Mode");
else MessageBox.Show("Runtime Mode");
return Host.RootComponent.Site.DesignMode;
}
}
MessageBox.Show("Runtime Mode");
return false;
}
Les lignes MessageBox.Show(
doivent être supprimées. Cela ne fait que m'assurer que cela fonctionne correctement.
C'est la méthode que j'ai utilisée dans mon projet:
//use a Property or Field for keeping the info to avoid runtime computation
public static bool NotInDesignMode { get; } = IsNotInDesignMode();
private static bool IsNotInDesignMode()
{
/*
File.WriteAllLines(@"D:\1.log", new[]
{
LicenseManager.UsageMode.ToString(), //not always reliable, e.g. WPF app in Blend this will return RunTime
Process.GetCurrentProcess().ProcessName, //filename without extension
Process.GetCurrentProcess().MainModule.FileName, //full path
Process.GetCurrentProcess().MainModule.ModuleName, //filename
Assembly.GetEntryAssembly()?.Location, //null for WinForms app in VS IDE
Assembly.GetEntryAssembly()?.ToString(), //null for WinForms app in VS IDE
Assembly.GetExecutingAssembly().Location, //always return your project's output Assembly info
Assembly.GetExecutingAssembly().ToString(), //always return your project's output Assembly info
});
//*/
//LicenseManager.UsageMode will return RunTime if LicenseManager.context is not present.
//So you can not return true by judging it's value is RunTime.
if (LicenseUsageMode.Designtime == LicenseManager.UsageMode) return false;
var procName = Process.GetCurrentProcess().ProcessName.ToLower();
return "devenv" != procName //WinForms app in VS IDE
&& "xdesproc" != procName //WPF app in VS IDE/Blend
&& "blend" != procName //WinForms app in Blend
//other IDE's process name if you detected by log from above
;
}
Attention !!!: Le code retourné bool indiquePASen mode création!
private void CtrlSearcher_Load(object sender, EventArgs e)
{
if(!this.DesignMode) InitCombos();
}
Vous pouvez utiliser ceci
if (DesignerProperties.GetIsInDesignMode(this))
{
...
}
Si vous souhaitez exécuter certaines lignes lors de son exécution, mais pas dans le concepteur Visual Studio, vous devez implémenter la propriété DesignMode comme suit:
// this code is in the Load of my UserControl
if (this.DesignMode == false)
{
// This will only run in run time, not in the designer.
this.getUserTypes();
this.getWarehouses();
this.getCompanies();
}
La solution LicenseManager ne fonctionne pas dans OnPaint, pas plus que this.DesignMode. J'ai eu recours à la même solution que @Jarek.
Voici la version en cache:
private static bool? isDesignMode;
private static bool IsDesignMode()
{
if (isDesignMode == null)
isDesignMode = (Process.GetCurrentProcess().ProcessName.ToLower().Contains("devenv"));
return isDesignMode.Value;
}
Sachez que cela échouera si vous utilisez un tiers IDE ou si Microsoft (ou votre utilisateur final) décide de changer le nom de l'exécutable du VS en un nom autre que "devenv". Le taux d'échec sera très faible. Assurez-vous de gérer les erreurs qui pourraient en résulter dans le code et qui échoueraient à la suite de cela, et tout ira bien pour vous.