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

时间:2009-01-22 16:46:44

标签: c# winforms data-binding textbox typeconverter

我有一个自定义的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”

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

1 个答案:

答案 0 :(得分:10)

知道了!

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

(下面的旧答案)

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

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

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

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

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

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

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

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