7

我有一个自定义的 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 对象上启用“格式化”即可。(谢谢,乔恩斯基特):

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

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

"true 以格式化显示的数据;否则为 false"

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

4

1 回答 1

10

知道了!

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 让它工作,但如果我现在能看到它,我会感到震惊。

于 2009-01-22T17:03:58.863 回答