コンテキスト:Visual Studo 2012 / C#5.0
3つのテキストボックスコントロール(firstNameTextBox、lastNameTextBox、ageTextBox)と単純なカスタムクラスを備えた.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);
}