自定义TypeConverter的ConvertTo方法未对char属性触发调用
问题:自定义Char类型转换器的ConvertTo方法未触发
我有一个类包含char类型属性,用于通信协议,可能存储不可打印字符。依赖默认CharConverter时,不可打印字符无法在属性表单中显示或编辑,因此我编写了自定义TypeConverter,将char转换为Unicode码点的十六进制值展示。
但自定义转换器的CanConvertTo和ConvertTo方法在显示属性值时未被调用:可打印字符仍显示字符本身,不可打印字符无输出,仿佛默认CharConverter仍在生效。奇怪的是,自定义转换器的CanConvertFrom方法(从string转换)能被正常调用并返回true。
相关代码如下:
目标类代码
using System.ComponentModel; public class SomeClass { // ... // Property for setting a communications character. [ DisplayName("SomeCharacter"), Category("Configuration"), Description("Some special communications character, as a hex value."), TypeConverter(typeof(CustomCharConverter)), ] public char SpecialChar { get => // ... set => // ... } }
自定义转换器代码
public class CustomCharConverter: TypeConverter { // ... // Overridden CanConvertTo. This is never called. public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { // This code never executes. if(destinationType == typeof(string) || destinationType == typeof(char)) { return true; } return base.CanConvertTo(context, destinationType); } // Overridden ConvertTo. This is never called. public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { // This code never executes. if(destinationType == typeof(string)) { return $"0x{((int)((char)value)):X2}"; // Convert char to hex value. } return base.ConvertTo(context, culture, value, destinationType); } }
解决方案
问题根源在于PropertyGrid对char类型的特殊处理逻辑:它会优先直接调用Char.ToString(),而非触发自定义TypeConverter的ConvertTo方法——除非你的转换器是CharConverter的子类,而非直接继承基础的TypeConverter。
核心修改:继承CharConverter而非TypeConverter
PropertyGrid内部针对char类型有优化,当检测到转换器是CharConverter的子类时,才会完整调用其所有转换逻辑。直接继承TypeConverter会被绕过ConvertTo流程。
修改后的转换器代码:
public class CustomCharConverter : CharConverter // 改为继承CharConverter { // 保留原有的CanConvertFrom实现(处理字符串输入) public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) return true; return base.CanConvertFrom(context, sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { // 实现字符串转char的逻辑(解析十六进制值) if (value is string s) { // 处理带0x前缀的输入 if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) s = s.Substring(2); // 解析十六进制为int后转char if (int.TryParse(s, System.Globalization.NumberStyles.HexNumber, culture, out int code)) return (char)code; } return base.ConvertFrom(context, culture, value); } // 重写CanConvertTo,明确支持转string public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(string)) return true; return base.CanConvertTo(context, destinationType); } // 重写ConvertTo,将char转为十六进制字符串 public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string) && value is char c) { return $"0x{(int)c:X2}"; } return base.ConvertTo(context, culture, value, destinationType); } }
额外说明
- 继承
CharConverter后,PropertyGrid会正确触发你的ConvertTo逻辑,无论字符是否可打印 - 如果需要支持常用通信控制字符的快速选择,可以额外重写
GetStandardValues方法添加标准值列表
内容的提问来源于stack exchange,提问作者FunctionalFolds
相关产品推荐
相关产品推荐

