У меня есть собственный тип 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"
В нем ничего не говорится о том, что это требование возврата данных из системы управления (при этих условиях).