上下文:Visual Studo 2012/C# 5.0
我有一个带有三个文本框控件的 .NET Windows 窗体:firstNameTextBox、lastNameTextBox和ageTextBox,以及一个简单的自定义类
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
我想将客户自定义类的实例的属性绑定到我的 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"));
}
我收到运行时错误:
'无法绑定到 DataSource 上的属性或列 FirstName。参数名称:dataMember'
问题:如何将具有一组动态自定义属性的 System.Dynamic.ExpandoObject(或 System.Dynamic.DynamicObject)实例绑定到 Windows 窗体(文本框)控件集?
注 1:具有聚合/容器辅助类的解决方案对我来说是可以的。
注意 2:我花了几个小时在谷歌上搜索并尝试应用不同的技术(包括我在 StackOverflow 上找到的技术),但我失败了。
这是基于 Hans Passant 提示的“优雅”解决方案:
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);
}