【问题标题】:Binding custom properties' values of an instance of ExpandoObject to a .NET Windows Forms controls将 ExpandoObject 实例的自定义属性值绑定到 .NET Windows 窗体控件
【发布时间】:2013-03-13 02:24:23
【问题描述】:

上下文:Visual Studo 2012/C# 5.0

我有一个带有三个文本框控件的 .NET Windows 窗体:firstNameTextBoxlastNameTextBoxageTextBox,以及一个简单的自定义类

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 上找到的技术)但我失败了。

这是一个基于 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);
}

【问题讨论】:

    标签: winforms expandoobject 2-way-object-databinding


    【解决方案1】:

    数据绑定使用反射,它在 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);
    

    这行得通,但当然不会获得任何优雅分数。

    【讨论】:

    • 实际上您的解决方案对我来说效果很好,并且可以变得优雅。非常感谢!
    • 汉斯,我刚刚根据您的提示在我的问题正文的底部发布了解决方案。谢谢。
    • 汉斯,请看看我在C# 5.0 'Universal' WinForms TextBox Text 'Two-Way' Binder'StackOverflow note'中使用了你的提示。如果您觉得有趣,请发表评论。谢谢。
    猜你喜欢
    • 2013-01-23
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 2011-06-22
    • 2013-12-25
    相关资源
    最近更新 更多