How is one binding to a custom type in TextBox.Text?

I have my own type C # type (just an example):

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

And I want it to bind to TextBox.Text:

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

Essentially, I need to convert to and from a string for my custom value type. In the text box, I need something like "x, y, z" that you can edit to update the vector type. I suggested that I can do this by adding the TypeConverter 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 linking it to my structure:

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

This seems to end half the battle. I see that MyVectorConverter getting a call, but something is wrong. It is called to find out if it knows how to convert to a string, then it is called to convert to a string. However, it is never asked if it can convert the FROM string or actually perform the conversion. In addition, immediately after editing in the text field, the old value is immediately replaced (another sequence of CanConvertTo and ConvertTo, restoring the old value). The end result is that the newly entered entry in the text field is returned immediately after its application.

It seems to me that there is simply something simple. Here? Is this whole project / approach doomed to failure? Is anyone else trying such madness? How to bidirectionally associate a custom, multi-page type with string control?

Solution: In particular, all that is needed is that β€œformatting” must be enabled on the Binding object. (thanks, John Skeet):

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

Oddly enough, everything that my MSDN mentions about this parameter (formattingEnabled):

"true to format the displayed data, otherwise false

It does not say that it is a requirement to return data from control (in these conditions).

+7
c # data-binding typeconverter winforms textbox
source share
1 answer

Got it!

Set the Binding.FormattingEnabled property to true. It seems to make everything work. You can do this with an overload to the ControlBindingsCollection.Add method, which at the end takes a Boolean parameter. It is strange that it worked in one direction, but not before, but, of course, my test application now works ...

(Old answer below)

I would not be surprised if the fact that you have a structure instead of a class, as well as how you use fields instead of properties, was more important here.

Try using a class using automatically implemented properties:

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

This may not be the root of the problem, but using a volatile structure with public fields just causes problems with IMO.

EDIT: As mentioned in the comments, I now have an example and work. Binding.Parse rises with the correct value. Now, to find out why TypeConverter is not being called ...

EDIT: I found a useful article that describes the binding in more detail. It seems that the type converter is only used to convert "to" another type - so you will need a type converter for string to know how to convert to a custom type. This seems to be pretty weird, but there are two more options:

  • Use formatting and parsing events to convert
  • Make an implementation of type IConvertible

None of them fits exactly the same, but a workaround may be sufficient for them. I'm sure there is a way to get this to work using TypeConverters, but I'm blown up if I can see it at the moment.

+10
source share

All Articles