2009-01-22 20 views
7

tengo un tipo personalizado C# como (es un ejemplo):¿Cómo enlaza un dato un tipo personalizado con TextBox.Text?

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

Y yo quiero que databind a TextBox.Text:

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

Esencialmente necesito conversión hacia y desde una cadena de mi tipo de valor personalizado En el cuadro de texto, quiero algo como "x, y, z" que se puede editar para actualizar el tipo de vector. Supuse que podía hacerlo añadiendo una clase derivada 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); 
    } 
} 

y asociarlo con mi estructura:

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

Esto parece completar la mitad de la batalla. Puedo ver MyVectorConverter llamando, pero algo anda mal. Se llama para ver si sabe cómo convertir a cadena, luego se llama para convertir a cadena. Sin embargo, nunca se consulta para ver si puede convertir FROM cadena ni hacer realmente la conversión. Además, justo después de una edición en el cuadro de texto, el valor anterior se reemplaza inmediatamente (otra secuencia CanConvertTo y ConvertTo, restaurando el valor anterior). El resultado final es que la entrada recién ingresada en el cuadro de texto se revierte inmediatamente después de que se aplica.

Siento como si simplemente faltara algo simple. ¿Esta ahí? ¿Todo este proyecto/enfoque está condenado al fracaso? ¿Alguien más intenta tal locura? ¿Cómo se vincula bi-direccionalmente un tipo personalizado de varias partes a un control basado en cadenas?

Solución: Curiosamente, todo lo que se necesita es que se habilite el "formateo" en el objeto de enlace. (Gracias, Jon Skeet):

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

Curiosamente, todo lo que mi MSDN menciona acerca de este parámetro (formattingEnabled) es:

"verdadero dar formato a los datos que, de lo contrario, falsa"

No menciona nada que sea un requisito para que los datos vuelvan del control (en estas condiciones).

Respuesta

10

¡Consígalo!

Establezca la propiedad Binding.FormattingEnabled en true. Esto parece hacer que todo funcione. Puede hacer esto con una sobrecarga del método ControlBindingsCollection.Add que toma un parámetro booleano al final. Es extraño que funcionaba de una forma pero no el otro antes, pero sin duda mi aplicación de prueba ahora trabaja ...

(respuesta Antiguo abajo)

No me sorprendería en absoluto si el hecho de que se Obtuve una estructura en lugar de una clase que era importante aquí, así como la forma en que está usando los campos en lugar de las propiedades.

intento con una clase utilizando las propiedades autoimplemented lugar:

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

Esto bien puede no ser la raíz del problema, pero utilizando una estructura mutable con campos comunes está metiendo en problemas de la OMI.

EDITAR: Como mencioné en los comentarios, ahora tengo un ejemplo en funcionamiento. El Binding.Parse se está levantando con el valor correcto. Ahora para descubrir por qué TypeConverter no se está llamando ...

EDIT: he encontrado un useful article que describe el enlace en más detalle. Parece sugerir que el convertidor de tipos solo se usa para convertir "a" otro tipo, por lo que necesitaría el convertidor de tipos para string para saber cómo convertir al tipo personalizado. Esto parece bastante extraño para mí, es cierto, pero hay otras dos opciones:

  • utilizar el formato y analiza los eventos de la unión para hacer la conversión
  • Hacer que el tipo de implementar IConvertible

Ninguno de los dos estos apelan de la misma manera, pero puede ser una solución suficiente para usted. Estoy seguro de que hay una forma de hacer que esto funcione con TypeConverters, pero estoy impactado si puedo verlo en este momento.

+0

Gracias por los comentarios, he aclarado el ejemplo y he hecho la pregunta más genérica. Mi ejemplo fue una estructura para la simplicidad, pero lo he cambiado a un tipo de referencia para demostrar el problema más amplio. – el2iot2

+0

Hacerlo una estructura con campos públicos ciertamente no * agrega * a la simplicidad :) ¿Esto es en Windows Forms, WPF, ASP.NET o qué? –

+0

Depende de lo que sea su heurística para "simplicidad" (simplicidad de código, simplicidad de ejemplo, simplicidad de uso del tipo de datos en interoperabilidad ... etc.), pero estoy divagando. Intento utilizar la solución en los formularios de Windows, pero la pregunta es relevante para la vinculación de datos en general, creo. – el2iot2

Cuestiones relacionadas