在尝试编写自定义控件时,我遇到了System.Windows.Forms.TextFormatFlags枚举与Visual Studio(2005/2008)编辑器结合的问题。这个问题的原因似乎来自这个枚举有多个成员映射到零值的事实。选择任何这些成员(GlyphOverhangPadding,Left,Default,Top)会导致编辑器将属性设置为
this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.GlyphOverhangPadding;
代码按预期编译。但是,从编辑器的属性网格中选择任何非零成员(例如“右”)会产生以下结果:
this.customControl.TextFormatFlags = System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right;
显然这不会编译。选择多个非零成员(通过UITypeEditor,例如“Right | Bottom”)会产生以下结果:
this.customControl.TextFormatFlags = ((System.Windows.Forms.TextFormatFlags)((System.Windows.Forms.TextFormatFlags.Left, Default, Top, Right | System.Windows.Forms.TextFormatFlags.Left, Default, Top, Bottom)));
如您所见,编辑器将四个零值成员中的三个添加到任何选定的项目中。
如果您希望重现此问题:
将私有字段和公共属性添加到新类:
私有TextFormatFlags tff = TextFormatFlags.Default;
public TextFormatFlags TFFProperty { 得到{return this.tff; } 设置{this.tff = value; } }
编译代码
如果使用Flags属性创建自己的枚举并添加多个映射到零的成员(这是一种格式错误的标记枚举?),也会发生同样的情况。我已经验证这不是我正在使用的UITypeEditor的错误(不使用UITypeEditor也会出现同样的问题)。我试图用转换器来解决这个问题,到目前为止还没有成功。如果有人对如何解决这个问题有任何想法,我会很高兴听到他们。
答案 0 :(得分:3)
我使用Reflector检查了System.ComponentModel.Design.Serialization
命名空间中的各个类,我认为CodeDom序列化器有点顽皮。
枚举由EnumCodeDomSerializer.Serialize
处理,其目的是获取枚举并将其转换为代表您在设计器文件中看到的System.CodeDom.CodeExpression
对象。
此方法正确使用CodeBinaryOperatorExpression
来处理表达式的|
方面。但是,对于单个枚举值,它使用Enum.ToString
通过EnumTypeConverter
并将结果字符串直接粘贴到表达式树中。
我认为Enum.ToString
是你所看到的最终原因:
如果多个枚举成员具有相同的基础值,并且您尝试根据其基础值检索枚举成员名称的字符串表示形式,则您的代码不应对该方法将返回的名称做出任何假设。
诚然,Enum.ToString
上的MSDN页面没有谈论逗号,但依赖Enum.ToString
作为有效C#表达式的输出似乎仍然不安全。
我不确定这对你的控制意味着什么:
TextFormatFlags
定义自己的替代品,并且无需重复的零标记InstanceDescriptor
。这使您可以更好地控制设计器生成的代码中显示的内容。int
,但向属性网格公开TextFormatFlags
修改: The comma-separated list behaviour of Enum.ToString
is in fact documented