如何将自定义类型数据绑定到TextBox.Text?

我有一个自定义的c#类型(只是一个例子):

public class MyVector { public double X {get; set;} public double Y {get; set;} public double Z {get; set;} //... } 

我想将它数据绑定到TextBox.Text:

 TextBox textBox; public MyVector MyVectorProperty { get; set;} //... textBox.DataBindings.Add("Text", this, "MyVectorProperty"); 

基本上我需要转换为自定义值类型的字符串。 在文本框中,我想要“x,y,z”之类的东西,可以编辑它来更新矢量类型。 我假设我可以通过添加TypeConverter派生类来实现:

 public class MyVectorConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) return true; //... return base.CanConvertFrom(context, sourceType); } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(string)) return true; //... return base.CanConvertTo(context, destinationType); } public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { if (value is string) { MyVector MyVector; //Parse MyVector from value return MyVector; } return base.ConvertFrom(context, culture, value); } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string)) { string s; //serialize value to string s return s; } //... return base.ConvertTo(context, culture, value, destinationType); } } 

并将其与我的结构相关联:

 [TypeConverter(typeof(MyVectorConverter))] public class MyVector { //... } 

这似乎完成了一半的战斗。 我可以看到MyVectorConverter被调用,但有些不对劲。 它被调用以查看它是否知道如何转换为字符串,然后调用它来转换为字符串。 但是,永远不会查询它是否可以转换FROM字符串,也不会实际进行转换。 此外,在文本框中编辑后,立即替换旧值(另一个CanConvertTo和ConvertTo序列,恢复旧值)。 最终结果是文本框中新键入的条目在应用后立即恢复。

我觉得好像有一些简单的遗漏。 在那儿? 整个项目/方法注定要失败吗? 有没有其他人尝试这种疯狂? 如何将自定义多部分类型双向绑定到基于字符串的控件?

解决方案:奇怪的是,所需的只是在Binding对象上启用“格式化”。 (谢谢Jon Skeet):

 textBox.DataBindings.Add("Text", this, "MyVectorProperty"); //FAILS textBox.DataBindings.Add("Text", this, "MyVectorProperty", true); //WORKS! 

奇怪的是,我的MSDN提到的关于这个参数(formattingEnabled)的所有内容是:

“如果格式化显示的数据,则为true;否则为false”

它没有提到要求数据从控制中返回(在这些条件下)。

得到它了!

Binding.FormattingEnabled属性设置为true。 这似乎使一切顺利。 您可以通过ControlBindingsCollection.Add方法的重载来执行此操作,该方法在结尾处采用布尔参数。 奇怪的是它以前的方式工作,但之前没有,但我的测试应用程序现在肯定有效……

(旧答案如下)

如果你有一个结构而不是一个类的事实在这里很重要,我会不会感到惊讶 – 以及你使用字段而不是属性的方式。

尝试使用自动实现属性的类:

 public class MyClass { public int IntPart { get; set; } public string StringPart { get; set; } //... } 

这可能不是问题的根源,但是使用带有公共字段的可变结构只是在寻找IMO的麻烦。

编辑:正如评论中所提到的,我现在已经开始运行了一个例子。 正在使用正确的值引发Binding.Parse。 现在找出为什么没有调用TypeConverter …

编辑:我发现了一篇有用的文章 ,更详细地描述了绑定。 似乎建议类型转换器仅用于将“转换”为另一种类型 – 因此您需要string的类型转换器才能知道如何转换为自定义类型。 对我而言,这似乎很奇怪,但还有两个选择:

  • 使用Binding的Format和Parse事件进行转换
  • 使类型实现IConvertible

这些都没有完全相同的吸引力,但它们可能足以为您提供解决方案。 我确信有一种方法可以使用TypeConverters让它工作,但是如果我现在可以看到它,我会感到很震惊。