Listing Flags with Many Null Values ​​(TextFormatFlags)

While trying to write a custom control, I ran into a problem with the System.Windows.Forms.TextFormatFlags enumeration in combination with the Visual Studio editor (2005/2008). The reason for this problem is apparently due to the fact that this enumeration has several members that display a null value. Selecting any of these elements (GlyphOverhangPadding, Left, Default, Top) causes the editor to set the property

this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.GlyphOverhangPadding; 

The code compiles as expected. However, the selection of any nonzero element (for example, "on the right") from the editor properties grid leads to the following:

 this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right; 

Obviously, this does not compile. Selecting more than one non-zero element (via UITypeEditor, for example, "Right | Bottom") leads to the following:

 this.customControl.TextFormatFlags = ((System.Windows.Forms.TextFormatFlags)((System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right | System.Windows.Forms.TextFormatFlags.Left, Default, Top, Bottom))); 

As you can see, the editor adds three of the four members with a zero value to any selected item.

If you want to reproduce this problem:

  • Create a new project in Visual Studio 2005/2008 (Windows Forms Application)
  • Add a custom control to the project.
  • Add private field and public property to the new class:

    private TextFormatFlags tff = TextFormatFlags.Default;

    public TextFormatFlags TFFProperty {get {return this.tff; } set {this.tff = value; }}

  • Compile code

  • Open Form1 in the constructor and add CustomControl1 to it
  • The code compiles fine
  • Now open the properties of CustomControl1 in the PropertyGrid editor
  • You should see TFFProperty in the Miscellaneous section.
  • The property offers several values, most of which contain a comma.
  • Choosing any of the values ​​with a comma (for example, "Left", "Default", "Top", "Horizontal center") leads to the absence of compilation code

The same thing happens if you create your own enumeration with the Flags attribute and add more than one member matched to zero (which is a kind of malformed enum flags?). I checked that this is not an error with the UITypeEditor that I am using (the same problem occurs without using UITypeEditor). I tried to get around the converter problem so far without success. If anyone has any ideas on how to solve this problem, I would be happy to hear them.

+2
source share
1 answer

I checked the various classes in the System.ComponentModel.Design.Serialization namespace using Reflector, and I think the CodeDom serializer is a little mischievous.

Enums are processed by EnumCodeDomSerializer.Serialize , whose purpose is to list and turn it into a System.CodeDom.CodeExpression object, which represents what you see in the constructor file.

This method correctly uses the CodeBinaryOperatorExpression to handle the aspect | expressions. However, for individual enumeration values, it uses Enum.ToString via EnumTypeConverter and binds the resulting string directly to the expression tree.

I think Enum.ToString is the main reason that you see:

If several enumeration elements have the same base value, and you are trying to get a string representation of the name of an enumeration member based on its base value, your code should not make any assumptions about which name the method returns.

Admittedly, the MSDN page on Enum.ToString doesn't talk about commas, but it still doesn't seem safe to rely on Enum.ToString output, which is a valid C # expression.

I'm not sure what this means for your control:

  • Clearly, you can define your own replacement for TextFormatFlags and do this without duplicate zero flags
  • You can hack it with a custom type converter, possibly convertible to InstanceDescriptor . This gives you a little more control over what appears in the code created by the developer.
  • You could set an int for the constructor serializer, but TextFormatFlags into the property grid

Edit: Actually registered Enum.ToString list Enum.ToString , separated by commas

+3
source

All Articles