2009-01-22 15 views
7

Mam niestandardowy typ C# jak (tylko przykład):W jaki sposób jeden databind niestandardowy typ do TextBox.Text?

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

I chcę go do databind do TextBox.text:

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

Zasadniczo muszę konwersję do i ze strun mój niestandardowy typ wartości. W polu tekstowym chcę coś takiego jak "x, y, z", które można edytować, aby zaktualizować typ wektora. Sądziłem, że mogę to zrobić dodając klasę TypeConverter pochodzącą:

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); 
    } 
} 

i skojarzenie go z mojego struct:

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

Wydaje się zakończyć pół bitwy. Widzę, jak się wzywam, ale coś jest nie w porządku. Jest wywoływana, aby sprawdzić, czy wie, jak przekonwertować na ciąg, a następnie jest wywoływana do konwersji na ciąg. Jednak nigdy nie jest pytany, czy można przekonwertować z ciągu znaków, czy faktycznie dokonać konwersji. Ponadto, zaraz po edycji w polu tekstowym, stara wartość jest natychmiast zastępowana (kolejna sekwencja CanConvertTo i ConvertTo, przywracająca starą wartość). Końcowym wynikiem jest to, że nowo wpisany wpis w polu tekstowym zostanie przywrócony natychmiast po jego zastosowaniu.

Mam wrażenie, że czegoś brakuje. Jest tu? Czy cały projekt/podejście skazane jest na niepowodzenie? Czy ktoś inny próbuje takiego szaleństwa? W jaki sposób jedno dwukierunkowe powiązanie niestandardowego typu wieloczęściowego z kontrolką opartą na łańcuchach?

Rozwiązanie: Bizarrely, wszystko, co potrzebne jest do „formatowania” być włączona wiązanie obiektu. (Dzięki Jon Skeet):

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

dziwne, to wszystko moja MSDN wspomina o tym parametrze (formattingEnabled) wynosi:

"true do sformatowania wyświetlanych danych, w przeciwnym razie false"

Nie wspomina nic o tym, że jest to wymóg, aby dane powróciły z kontroli (w tych warunkach).

Odpowiedz

10

Gotowy!

Ustawia właściwość Binding.FormattingEnabled na true. Wydaje się, że wszystko działa. Można to zrobić z przeciążeniem do metody ControlBindingsCollection.Add, która pobiera parametr Boolean na końcu. To dziwne, że to działa w jedną stronę, ale nie wcześniej niż inne, ale na pewno moja aplikacja Test działa teraz ...

(Old odpowiedź poniżej)

nie byłbym wcale zdziwiony, gdyby fakt, że W tym miejscu ważna jest struktura, a nie klasa, a także sposób, w jaki korzystasz z pól zamiast właściwości.

Spróbuj z klasy za pomocą autoimplemented właściwości zamiast:

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

To może nie być źródłem problemu, lecz stosując zmienny struct z publicznych pól jest po prostu pytając o kłopoty IMO.

EDYCJA: Jak wspomniano w komentarzach, mam już gotowy przykład. The Binding.Parse jest podnoszony z odpowiednią wartością. Teraz, aby dowiedzieć się, dlaczego TypeConverter nie jest wywoływana ...

EDYCJA: Znalazłem useful article, który opisuje wiązanie bardziej szczegółowo. Wydaje się sugerować, że konwerter typów służy tylko do konwertowania "na" innego typu - więc aby konwertować na niestandardowy typ, potrzebujesz konwertera typów na string. Wydaje się to dość dziwne dla mnie, co prawda, ale istnieją dwie inne opcje:

  • użyć formatu i analizowania zdarzeń wiązania zrobić konwersję
  • Bądź typ wdrożenie IConvertible

żaden z te odwołania w taki sam sposób, ale mogą one być wystarczające dla obejścia tego problemu. Jestem pewien, że istnieje sposób, żeby to działało przy użyciu TypeConverters, ale jestem dmuchany, jeśli widzę go w tej chwili.

+0

Dzięki za informację zwrotną, wyjaśniłem przykład i sprawiłem, że pytanie stało się bardziej ogólne. Mój przykład był prostą konstrukcją, ale zmieniłem ją na typ odniesienia, aby pokazać szerszy problem. – el2iot2

+0

Tworzenie struktury z polami publicznymi na pewno nie * dodaje * do prostoty :) Czy to w Windows Forms, WPF, ASP.NET czy co? –

+0

Zależy od tego, jaka jest twoja heurystyka dla "prostoty" (prostota kodu, prostota przykładu, prostota korzystania z typu danych w interop..etc.), Ale dygresja. Staram się korzystać z tego rozwiązania w formularzach Windows, ale pytanie jest ogólnie związane z formatowaniem danych. – el2iot2

Powiązane problemy