我有一个自定义的 c# 类型,例如(只是一个例子):
I have a custom c# type like (just an example):
public class MyVector
{
public double X {get; set;}
public double Y {get; set;}
public double Z {get; set;}
//...
}
我希望它数据绑定到 TextBox.Text:
And I want it to databind to TextBox.Text:
TextBox textBox;
public MyVector MyVectorProperty { get; set;}
//...
textBox.DataBindings.Add("Text", this, "MyVectorProperty");
基本上,我需要在自定义值类型的字符串之间进行转换.在文本框中,我想要x, y, z"之类的内容,可以对其进行编辑以更新矢量类型.我假设我可以通过添加一个 TypeConverter
派生类来做到这一点:
Essentially I need conversion to and from a string for my custom value type. In the text box, I want something like "x, y, z" that can be edited to update the vector type. I assumed that I could do so by adding a TypeConverter
derived class:
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);
}
}
并将其与我的结构相关联:
and associating it with my struct:
[TypeConverter(typeof(MyVectorConverter))]
public class MyVector { //... }
这似乎完成了一半的战斗.我可以看到 MyVectorConverter
被调用,但有些不对劲.调用它看它是否知道如何转换为字符串,然后调用它转换为字符串.但是,永远不会查询它是否可以转换 FROM 字符串,也不会实际进行转换.此外,在文本框中进行编辑后,旧值立即被替换(另一个 CanConvertTo 和 ConvertTo 序列,恢复旧值).最终结果是文本框中新键入的条目在应用后立即恢复.
This appears to complete half of the battle. I can see MyVectorConverter
getting called into, but something is amiss. It is called to see if it knows how to convert to string, then it is called to convert to string. However, it is never queried to see if it can convert FROM string nor to actually do the conversion. Furthermore, right after an edit in the textbox, the old value is immediately replaced (another CanConvertTo and ConvertTo sequence, restoring the old value). The end result is that the newly typed entry in the text box is reverted immediately after it is applied.
我觉得好像缺少了一些简单的东西.在那儿?这整个项目/方法注定要失败吗?还有其他人尝试这种疯狂吗?如何将自定义的多部分类型双向绑定到基于字符串的控件?
I feel as if there is just something simple missing. Is there? Is this entire project/approach doomed to failure? Does anyone else attempt such madness? How does one bi-directionally bind a custom, multipart type to a string-based control?
解决方案: 奇怪的是,只需要在 Binding 对象上启用格式化"即可.(感谢 Jon Skeet):
Solution: Bizarrely, all that is needed is for the "formatting" to be enabled on the Binding object. (thanks, Jon Skeet):
textBox.DataBindings.Add("Text", this, "MyVectorProperty"); //FAILS
textBox.DataBindings.Add("Text", this, "MyVectorProperty", true); //WORKS!
奇怪的是,我的 MSDN 提到的关于这个参数 (formattingEnabled) 的全部内容是:
Oddly, all that my MSDN mentions about this parameter (formattingEnabled) is:
"true 格式化显示的数据;否则为 false"
"true to format the displayed data; otherwise, false"
它没有提到它是从控件返回数据的要求(在这些条件下).
It mentions nothing about it being a requirement for the data to come back from the control (under these conditions).
知道了!
设置 Binding.FormattingEnabled
属性为真.这似乎使一切正常.您可以通过重载 ControlBindingsCollection.Add
方法来做到这一点最后采用布尔参数.奇怪的是,它以一种方式工作,但以前不是另一种,但我的测试应用现在可以工作了......
Set the Binding.FormattingEnabled
property to true. This seems to make it all work.
You can do this with an overload to the ControlBindingsCollection.Add
method which takes a Boolean parameter at the end.
It's odd that it worked one way but not the other before, but certainly my test app now works...
(下面的旧答案)
如果你有一个结构而不是一个类这一事实在这里很重要 - 以及你使用字段而不是属性的方式,我一点也不感到惊讶.
I wouldn't be at all surprised if the fact that you're got a struct instead of a class was important here - as well as the way you're using fields instead of properties.
尝试使用自动实现属性的类:
Try with a class using autoimplemented properties instead:
public class MyClass
{
public int IntPart { get; set; }
public string StringPart { get; set; }
//...
}
这很可能不是问题的根源,但是使用带有公共字段的可变结构只是在 IMO 上自找麻烦.
This may well not be the root of the problem, but using a mutable struct with public fields is just asking for trouble IMO.
正如评论中提到的,我现在已经启动并运行了一个示例.Binding.Parse 正在以正确的值引发.现在找出为什么没有调用 TypeConverter...
As mentioned in the comments, I've now got an example up and running. The Binding.Parse is being raised with the right value. Now to find out why the TypeConverter isn't being called...
我找到了一篇有用的文章,它更详细地描述了绑定.似乎表明类型转换器仅用于将转换为"另一种类型-因此您需要 string
的类型转换器才能知道如何转换为自定义类型.诚然,这对我来说似乎很奇怪,但还有其他两种选择:
I've found a useful article which describes binding in more detail. It seems to suggest that the type converter is only used to convert "to" another type - so you'd need the type converter for string
to know how to convert to the custom type. This seems pretty strange to me, admittedly, but there are two other options:
这两种方式都不一样,但它们可能足以成为您的解决方法.我确信有一种方法可以使用 TypeConverters 让它工作,但如果我现在能看到它,我会感到震惊.
Neither of these appeal in quite the same way, but they may be enough of a workaround for you. I'm sure there's a way to get this to work using TypeConverters, but I'm blowed if I can see it at the moment.
这篇关于如何将自定义类型数据绑定到 TextBox.Text?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!