如何使用 lambda 表达式更新 属性?

How to use a lambda expression to update a property?

我有以下 class:

public class MyClass
{
    public int? Field1 { get; set; }
    public int? Field2 { get; set; }
}

表单上的文本框控件通过 BindingSource 绑定到此 class 的一个实例,并且数据源在 OnValidated 事件上更新。

但是,当文本框为空时,它所绑定的 属性 不会更新(再次显示之前的值):

因此,在控件的 OnValidating 事件中,我添加了以下内容:

int value;
bool ok = int.TryParse(((TextBox)sender).Text, out value);
if (!ok)
{
    myClassInstance.Field1 = null;
}

问题:

  1. TextBox 的值为空时,以上是 BindingSource 的正常行为吗?

  2. 是否可以有一个我可以在我的 OnValidating 事件中调用的通用方法。类似于:

    OnValidatingMethod((TextBox)sender, x => x.Field1);
    

上面这行代码显然是行不通的,因为没有引用对象实例。但我想知道这样的事情是否可能?也许是 class:

的扩展
myClassInstance.SetProperty(((TextBox)sender).Text, x => x.Field1);

数据绑定的整个思想就是从源中抽象出目标。如果您创建了这样的事件处理程序,那么抽象就结束了。

您看到的当然不正常,但这是为 "backward compatibility" 保留的非常古老的错误的结果。很久以前就通过向 Binding class 添加额外的属性来修复它,但同样为了向后兼容,默认值设置为模仿旧行为。

要使其按预期工作,您需要设置的属性是 FormattingEnabled to true, and NullValue""。我通常使用允许指定所有信息的 DataBindings.AddBinding 构造函数重载之一,如下所示:

textBox.DataBindings.Add("Text", bs, "Field1", true, DataSourceUpdateMode.OnValidation, "");

这是一个完整的演示:

using System;
using System.Windows.Forms;

namespace Samples
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var textBox1 = new TextBox { Parent = form, Left = 16, Top = 16 };
            var textBox2 = new TextBox { Parent = form, Left = 16, Top = textBox1.Bottom + 16 };
            var bs = new BindingSource { DataSource = typeof(MyClass) };
            textBox1.DataBindings.Add("Text", bs, "Field1", true, DataSourceUpdateMode.OnValidation, "");
            textBox2.DataBindings.Add("Text", bs, "Field2", true, DataSourceUpdateMode.OnValidation, "");
            bs.DataSource = new MyClass { Field1 = 1, Field2 = 2 };
            Application.Run(form);
        }
    }

    public class MyClass
    {
        public int? Field1 { get; set; }
        public int? Field2 { get; set; }
    }
}

最后,如果你真的想参与解析部分,你应该将处理程序附加到Binding.Parse事件。