1

コンテキスト:Visual Studo 2012 / C#5.0

3つのテキストボックスコントロール(firstNameTextBoxlastNameTextBoxageTextBox)と単純なカスタムクラスを備えた.NETWindowsフォームがあります。

public class Customer
{
 public string FirstName { get; set; }
 public string LastName { get; set; }
 public int Age { get; set; }
}

そして、 CustomerカスタムクラスのインスタンスのプロパティをWindowsフォームコントロールにバインドしたいと思います。だから私は書く:

private dynamic _customer;
private void Form_Load(object sender, EventArgs e)
{
    _customer = new Customer()
    {
        FirstName = "Andrew",
        LastName = "Chandler",
        Age = 23
    };
    this.firstNameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text",     _customer, "FirstName"));
    this.lastNameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "LastName"));
    this.ageTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "Age"));
}

そしてそれはうまくいきます。次に、匿名タイプを使用してコードを少し変更します。

private dynamic _customer;
private void Form_Load(object sender, EventArgs e)
{
    _customer = new 
    {
        FirstName = "Andrew",
        LastName = "Chandler",
        Age = 23
    };
    this.firstNameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "FirstName"));
    this.lastNameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "LastName"));
    this.ageTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "Age"));

}

この場合、私は一方向のバインディングしか持っていませんが、それもかなりうまく機能します。次に、コードをさらに変更します。

private dynamic _customer;
private void Form_Load(object sender, EventArgs e)
{   
    _customer = new ExpandoObject();
    _customer.FirstName = "Andrew";
    _customer.LastName = "Chandler";
    _customer.Age = 23;

     this.firstNameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "FirstName"));
     this.lastNameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "LastName"));
     this.ageTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", _customer, "Age"));
}

ランタイムエラーが発生します:

'データソースのプロパティまたは列FirstNameにバインドできません。パラメータ名:dataMember '

質問:動的カスタムプロパティのセットを持つSystem.Dynamic.ExpandoObject(またはSystem.Dynamic.DynamicObject)のインスタンスを(テキストボックス)コントロールのWindowsフォームセットにバインドするにはどうすればよいですか?

注1:アグリゲーション/コンテナーヘルパークラスを使用したソリューションは、私にとっては問題ありません。

注2:数時間グーグルしてさまざまなテクニック(StackOverflowで見つけたテクニックを含む)を適用しようとしましたが、失敗しました。

HansPassantのヒントに基づく「エレガントな」ソリューションは次のとおりです。

private dynamic _customer;
private void Form_Load(object sender, EventArgs e)
{
    _customer = new ExpandoObject();
    _customer.FirstName = "Andrew";
    _customer.LastName = "Chandler";
    _customer.Age = 23;

    bindExpandoField(this, "FirstNameTextBox", "Text", _customer, "FirstName");
    bindExpandoField(this, "lastNameTextBox", "Text", _customer, "LastName");
    bindExpandoField(this, "ageTextBox", "Text", _customer, "Age");
}


private void bindExpandoField(
      Control hostControl,
      string targetControlName,
      string targetPropertyName,
      dynamic expandoObject,
      string sourcePropertyName)
{
    Control targetControl = hostControl.Controls[targetControlName];
    var IDict = (IDictionary<string, object>)expandoObject;
    var bind = new Binding(targetPropertyName, expandoObject, null);
    bind.Format += (o, c) => c.Value = IDict[sourcePropertyName];
    bind.Parse += (o, c) => IDict[sourcePropertyName] = c.Value;
    targetControl.DataBindings.Add(bind);
}
4

1 に答える 1

3

データバインディングはReflectionを使用しますが、その「プロパティ」は実際には基になるオブジェクトのプロパティではないため、ExpandoObjectではうまく機能しません。ExpandoObjectはIDictionaryを実装しますが、これはListBoxのようなリストコントロールにのみ簡単にバインドします。

完全に不可能というわけではありません。Binding.FormatイベントとParseイベントを明示的に実装する必要があります。このような:

dynamic bag = new ExpandoObject();
bag.foo = "bar";
var bind = new Binding("Text", bag, null);
bind.Format += (o, c) => c.Value = bag.foo;
bind.Parse += (o, c) => bag.foo = c.Value;
textBox1.DataBindings.Add(bind);

それは機能しますが、もちろんエレガンスポイントを獲得することはありません。

于 2013-03-13T03:25:32.987 に答える