énumération Flags avec de multiples valeurs zéro problème (TextFormatFlags)
Question
Tout en essayant d'écrire un contrôle personnalisé que j'ai rencontré un problème avec le ENUM System.Windows.Forms.TextFormatFlags en combinaison avec l'éditeur Visual Studio (2005/2008). La raison de ce problème semble provenir du fait que ce ENUM a plusieurs membres qui tracent à une valeur nulle. La sélection d'un de ces membres (GlyphOverhangPadding, Gauche, par défaut, Top) des résultats dans l'éditeur définissant la propriété à
this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.GlyphOverhangPadding;
Le code compile, comme prévu. Cependant, la sélection d'un membre non nulle (par exemple, « droit ») à partir de la grille de la propriété des résultats de l'éditeur dans le texte suivant:
this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right;
Il est évident que cela ne compile pas. Sélection de plus d'un membre non nul (par un UITypeEditor, par exemple « Right | Bottom ») le résultat suivant:
this.customControl.TextFormatFlags = ((System.Windows.Forms.TextFormatFlags)((System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right | System.Windows.Forms.TextFormatFlags.Left, Default, Top, Bottom)));
Comme vous pouvez le voir, l'éditeur ajoute trois des quatre membres de valeur zéro à l'élément sélectionné.
Si vous souhaitez reproduire ce problème:
- Créer un nouveau projet dans Visual Studio 2005/2008 (application Windows Forms)
- Ajout d'un contrôle personnalisé au projet.
-
Ajoutez un champ privé et des biens publics à la nouvelle classe:
TextFormatFlags privé TFF = TextFormatFlags.Default;
publique TextFormatFlags TFFProperty { obtenir {return this.tff; } ensemble {this.tff = valeur; } }
-
Compiler le code
- Ouvrir Form1 dans le concepteur et ajouter CustomControl1 à elle
- Le code compile bien
- Ouvrez maintenant les propriétés de CustomControl1 dans PropertyGrid de l'éditeur
- Vous devriez voir la TFFProperty sous la rubrique « Divers »
- La propriété offre plusieurs valeurs, dont la plupart contiennent une virgule.
- La sélection d'une des valeurs par une virgule (par exemple « gauche, par défaut, Haut, horizontalCenter) résultats dans le code non compilable
La même chose se produit si vous créez votre propre ENUM avec les drapeaux d'attributs et d'ajouter plus d'un membre cartographié à zéro (ce qui est une sorte de drapeaux malformés ENUM?). Je l'ai vérifié que ce n'est pas un bug avec le UITypeEditor J'utilise (Le même problème se produit sans utiliser le UITypeEditor). J'ai essayé de contourner le problème avec un convertisseur, jusqu'à présent sans succès. Si quelqu'un a des idées sur la façon de résoudre ce problème, je serais heureux de les entendre.
La solution
J'ai vérifié à travers les différentes classes dans l'espace de noms System.ComponentModel.Design.Serialization
utilisant réflecteur, et je pense que le sérialiseur CodeDom est d'être un peu méchant.
énumérations se charge par EnumCodeDomSerializer.Serialize
, dont le but est de prendre un ENUM et la transformer en un objet System.CodeDom.CodeExpression
qui représente ce que vous voyez dans le fichier concepteur.
Cette méthode utilise correctement CodeBinaryOperatorExpression
pour gérer l'aspect |
de l'expression. Toutefois, pour les valeurs enum individuelles, il utilise Enum.ToString
via EnumTypeConverter
et colle directement la chaîne résultante dans l'arbre d'expression.
Je pense que Enum.ToString
est la cause ultime de ce que vous re voir:
Si plusieurs membres de l'énumération ont la même valeur sous-jacente et que vous essayez de récupérer la représentation de chaîne du nom d'un membre de l'énumération en fonction de sa valeur sous-jacente, votre code ne devrait pas faire de suppositions au sujet avec le nom de la méthode retourne.
Il est vrai que la page MSDN sur Enum.ToString
ne parle pas des virgules, mais il ne semble toujours pas sûr de compter sur la sortie de Enum.ToString
étant une expression valide C #.
Je ne sais pas ce que cela signifie pour votre commande:
- Il est clair que vous pouvez définir votre propre remplacement pour
TextFormatFlags
et de le faire sans le zéro drapeaux en double - Vous pouvez être en mesure de pirater avec un convertisseur de type personnalisé, peut-être un qui se transforme en
InstanceDescriptor
. Cela vous donne un peu plus de contrôle sur ce qui apparaît dans le code généré concepteur. - Vous pourriez éventuellement exposer une
int
au sérialiseur design maisTextFormatFlags
à la grille de la propriété
Modifier Le comportement de la liste séparés par des virgules de Enum.ToString
est en fait documenté