Контекст: Visual Studio 2012/C# 5.0
У меня есть форма .NET Windows Form с тремя элементами управления текстовыми полями: firstNameTextBox, lastNameTextBox и ageTextBox, а также простой пользовательский класс
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
и я хочу связать свойства экземпляра пользовательского класса Customer с моими элементами управления Windows Forms. Поэтому я пишу:
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 Forms (текстовое поле)?
Примечание 1. Решение с вспомогательным классом агрегации/контейнера меня вполне устроит.
Примечание 2: я потратил несколько часов на гугление и попытки применить различные методы (в том числе те, которые я нашел здесь, в StackOverflow), но потерпел неудачу.
Вот «Элегантное» решение, основанное на подсказке Ханса Пассана:
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);
}