Quelqu'un at-il trouvé une solution utile au problème DesignMode lors du développement de contrôles?
Le problème est que si vous imbriquez des contrôles, DesignMode ne fonctionne que pour le premier niveau. Le deuxième niveau et les niveaux inférieurs DesignMode renverront toujours FALSE.
Le hack standard a été de regarder le nom du processus en cours d'exécution et si c'est "DevEnv.EXE" alors il doit être studio donc DesignMode est vraiment VRAI.
Le problème avec cela est de rechercher le ProcessName se fraye un chemin dans le registre et d'autres parties étranges avec le résultat final que l'utilisateur n'a peut-être pas les droits requis pour voir le nom du processus. De plus cet étrange itinéraire est très lent. Nous avons donc dû empiler des hacks supplémentaires pour utiliser un singleton et si une erreur est générée lors de la demande du nom du processus, supposons que DesignMode est FALSE.
Une bonne manière propre de déterminer DesignMode est en ordre. En fait, il serait encore mieux que Microsoft le corrige en interne au framework!
la source
Réponses:
En revisitant cette question, j'ai maintenant `` découvert '' 5 façons différentes de le faire, qui sont les suivantes:
Pour essayer de m'accrocher aux trois solutions proposées, j'ai créé une petite solution de test - avec trois projets:
J'ai ensuite intégré le SubSubControl dans le SubControl, puis un de chaque dans le TestApp.Form.
Cette capture d'écran montre le résultat lors de l'exécution.
Cette capture d'écran montre le résultat avec le formulaire ouvert dans Visual Studio:
Conclusion: Il semblerait que sans réflexion, le seul qui soit fiable au sein du constructeur soit LicenseUsage, et le seul qui soit fiable en dehors du constructeur soit 'IsDesignedHosted' (par BlueRaja ci-dessous)
PS: Voir le commentaire de ToolmakerSteve ci-dessous (que je n'ai pas testé): "Notez que la réponse IsDesignerHosted a été mise à jour pour inclure LicenseUsage ..., donc maintenant le test peut simplement être if (IsDesignerHosted). Une autre approche est de tester LicenseManager dans le constructeur et mettez en cache le résultat . "
la source
if(LicenseUseage == LicenseUsageMode.Designtime || IsDesignerHosted)
serait la bonne approche à 100%?LicenseUsage...
, donc maintenant le test peut simplement êtreif (IsDesignerHosted)
. Une autre approche consiste à tester LicenseManager dans le constructeur et à mettre en cache le résultat .Depuis cette page :
( [Edit 2013] Modifié pour fonctionner dans les constructeurs, en utilisant la méthode fournie par @hopla)
J'ai soumis un rapport de bogue avec Microsoft; Je doute que cela ira n'importe où, mais votez quand même, car c'est évidemment un bug (que ce soit ou non "par conception" ).
la source
Pourquoi ne vérifiez-vous pas LicenseManager.UsageMode. Cette propriété peut avoir les valeurs LicenseUsageMode.Runtime ou LicenseUsageMode.Designtime.
Si vous souhaitez que le code s'exécute uniquement au moment de l'exécution, utilisez le code suivant:
la source
C'est la méthode que j'utilise dans les formulaires:
De cette façon, le résultat sera correct, même si l'une des propriétés DesignMode ou LicenseManager échoue.
la source
J'utilise la méthode LicenseManager, mais je mets en cache la valeur du constructeur pour une utilisation pendant toute la durée de vie de l'instance.
Version VB:
la source
Nous utilisons ce code avec succès:
la source
Ma suggestion est une optimisation de @ blueraja-danny-pflughoeft réponse . Cette solution ne calcule pas le résultat à chaque fois, mais seulement à la première fois (un objet ne peut pas changer UsageMode de la conception à l'exécution)
la source
Je n'ai jamais été attrapé par cela moi-même, mais ne pourriez-vous pas simplement remonter la chaîne Parent à partir du contrôle pour voir si DesignMode est défini n'importe où au-dessus de vous?
la source
Étant donné qu'aucune des méthodes n'est fiable (DesignMode, LicenseManager) ou efficace (processus, contrôles récursifs), j'utilise un
public static bool Runtime { get; private set }
au niveau du programme et je le place explicitement dans la méthode Main ().la source
DesignMode est une propriété privée (d'après ce que je peux dire). La réponse est de fournir une propriété publique qui expose la prop DesignMode. Ensuite, vous pouvez cascasde sauvegarder la chaîne de contrôles utilisateur jusqu'à ce que vous tombiez sur un contrôle non utilisateur ou un contrôle en mode conception. Quelque chose comme ça....
Où tous vos UserControls héritent de MyBaseUserControl. Vous pouvez également implémenter une interface qui expose le "RealDeisgnMode".
Veuillez noter que ce code n'est pas un code en direct, juste des réflexions spontanées. :)
la source
Je n'avais pas réalisé que vous ne pouvez pas appeler Parent.DesignMode (et j'ai aussi appris quelque chose sur 'protected' en C # ...)
Voici une version réfléchissante: (Je soupçonne qu'il pourrait y avoir un avantage en termes de performances à faire de designModeProperty un champ statique)
la source
J'ai récemment dû lutter contre ce problème dans Visual Studio 2017 lors de l'utilisation de UserControls imbriqués. J'ai combiné plusieurs des approches mentionnées ci-dessus et ailleurs, puis j'ai peaufiné le code jusqu'à ce que j'aie une méthode d'extension décente qui fonctionne de manière acceptable jusqu'à présent. Il effectue une séquence de vérifications, stockant le résultat dans des variables booléennes statiques de sorte que chaque vérification ne soit effectuée au plus qu'une seule fois au moment de l'exécution. Le processus est peut-être excessif, mais il empêche le code de s'exécuter en studio. J'espère que cela aide quelqu'un.
la source