7

私は(ほんの一例)のようなカスタム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!

奇妙なことに、このパラメーター (formattingEnabled) について MSDN で言及されているのは次のとおりです。

"表示されたデータをフォーマットする場合は true、それ以外の場合は false"

(これらの条件下で)データがコントロールから返されるための要件であることについては何も言及されていません。

4

1 に答える 1

10

とった!

Binding.FormattingEnabledプロパティを true に設定します。これですべてうまくいくようです。ControlBindingsCollection.Addこれは、最後にブール値パラメーターを取るメソッドへのオーバーロードで行うことができます。以前は一方の方法で機能し、もう一方の方法では機能しなかったのは奇妙ですが、確かに私のテストアプリは現在機能しています...

(以下の古い回答)

ここで、クラスではなく構造体を使用しているという事実と、プロパティではなくフィールドを使用する方法が重要であったとしても、まったく驚かないでしょう。

代わりに、自動実装されたプロパティを使用するクラスを試してください。

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

これは問題の根本ではないかもしれませんが、パブリック フィールドで変更可能な構造体を使用すると、IMO の問題が発生するだけです。

編集:コメントで述べたように、私は今、例を実行しています。Binding.Parse が正しい値で発生しています。TypeConverter が呼び出されない理由を調べるために...

編集:バインディングについて詳しく説明している便利な記事を見つけました。string型コンバーターは別の型に「変換」するためにのみ使用されることを示唆しているようです-そのため、カスタム型に変換する方法を知るには型コンバーターが必要です。確かに、これはかなり奇妙に思えますが、他に 2 つのオプションがあります。

  • Binding の Format イベントと Parse イベントを使用して変換を行う
  • 型に IConvertible を実装させる

どちらもまったく同じように魅力的ではありませんが、回避策としては十分かもしれません. TypeConverters を使用してこれを機能させる方法があると確信していますが、現時点でそれを見ることができれば、私は吹き飛ばされます。

于 2009-01-22T17:03:58.863 に答える