.NET为我们提供了一套数据绑定的方式,可以将空间的属性映射到对象的属性中,我们来看下面的代码。
1 public Form1 : Form
2 {
3 private MyType myDataValue;
4 private TextBox textBoxName;
5
6 private void InitializeComponent( )
7 {
8 textBoxName.Text = myDataValue.Name;
9 this.textBoxName.Leave += new
10 System.EventHandler( this.OnLeave );
11 }
12
13 private void OnLeave( object sender, System.EventArgs e )
14 {
15 myDataValue.Name = textBoxName.Text;
16 }
17 }
18
19
上述代码中,空间txtBoxName和对象MyDataValue之间的对应关系,可以使用下面的代码进行描述。
textBoxName.DataBindings.Add ( "Text",
myDataValue, "Name" );
使用这种方式的好处:1)代码比较简洁;2)它可以绑定控件的很多其他属性,应用范围比较广;3)对应Windows Forms来说,数据绑定能够处理多个控件同步的检查相关数据源。
当我们使用DataBindings方式进行数据绑定时,需要注意,如果绑定的数据对象不同,那么会创建多个BindManager实例,这样是不好的,例如如下代码
1 // Bad practice: creates two binding managers
2 textBox1.DataBindings.Add ("Text",
3 src.Results, "Profit");
4 textBox1.DataBindings.Add ("ForeColor",
5 src, "ProfitForegroundColor");
上述代码中,绑定的数据对象分别是src.Results和src,这样会创建两个BindManger实例,分别对这两个对象进行管理,针对上述代码,我们应该写成这样:
1 // Use the same datasource. That creates one Binding Manager
2 textBox1.DataBindings.Add ("Text",
3 src, "Results.Profit");
4 textBox1.DataBindings.Add ("ForeColor",
5 src, "ProfitForegroundColor");
在绑定的过程中,框架还能处理字符串到值类型之间的转换,它会设法将用户的输入转换成合适的类型,如果转换失败,就会重新存储原始值。如果你不希望这样处理,那么可以在Form的Parse事件中进行处理,如下。
1 private void Form1_Parse( object sender, ConvertEventArgs e )
2 {
3 try {
4 Convert.ToInt32 ( e.Value );
5 } catch
6 {
7 MessageBox.Show (
8 string.Format( "{0} is not an integer",
9 e.Value.ToString( ) ) );
10 e.Value = 0;
11 }
12 }
我们还可以通过Form的Format事件提前对数据源中的数据进行格式化。
.NET框架提供了通用的框架,用来支持数据绑定,我们的主要工作是为应用程序和数据提供特定的事件处理器,运行时已经包含了我们需要的所有工具,所以UI代码应该描述出数据源、想要显示的属性以及将这些元素回溯到数据源时应该遵循的规则。我们可以将精力集中在构建描述显示参数的数据类型上。
补充 2010/2/21:
经过几年的编程,现在如果画面中的控件数目比较多,一般会按照功能切分画面,然后让每个功能对应一个DataModel,将DataModel作为表示层、逻辑层以及数据层进行通信的桥梁。
在这种情况下,我们使用控件的DataBindings方式将控件和DataModel关联起来就变得非常方便,而且在用户改变控件的属性后,可以直接映射到DataModel中,这样对于我们收集画面数据来说,也可以变得很容易。
来看下面的代码。
1 public partial class Form1 : Form
2 {
3 private Employee m_emp = new Employee();
4 public Form1()
5 {
6 InitializeComponent();
7 }
8
9 private void Form1_Load(object sender, EventArgs e)
10 {
11 m_emp.Name = "Wing";
12 m_emp.Address = "Beijing";
13 BindControlWithDataModel();
14 }
15
16 private void button1_Click(object sender, EventArgs e)
17 {
18 lblName.Text = m_emp.Name;
19 lblAddress.Text = m_emp.Address;
20 }
21
22 private void BindControlWithDataModel()
23 {
24 txtName.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnValidation;
25 txtAddress.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.OnValidation;
26
27 txtName.DataBindings.Add("Text", m_emp, "Name");
28 txtAddress.DataBindings.Add("Text", m_emp, "Address");
29 txtAddress.DataBindings.Add("BackColor", m_emp, "ExceedLength");
30 }
31 }
32
33 internal class Employee
34 {
35 private string m_strName;
36
37 public string Name
38 {
39 get { return m_strName; }
40 set { m_strName = value; }
41 }
42 private string m_strAddress;
43
44 public string Address
45 {
46 get { return m_strAddress; }
47 set { m_strAddress = value; }
48 }
49 private string m_nAge;
50
51 public Color ExceedLength
52 {
53 get
54 {
55 if (Address != null && Address.Length > 5)
56 {
57 return Color.Red;
58 }
59 else
60 {
61 return Color.Transparent;
62 }
63 }
64 }
65 }
上面的代码中,我们定义了一个业务模型来表示职员信息,然后将其绑定到画面中对应的TextBox控件中,当用户手动改变TextBox中的内容后,对应的DataModel中的属性值也会发生改变。
说明:控件的DataBindings中包含一个名为DefaultDataSourceUpdateMode的属性,它是一个DataSourceUpdateMode类型的枚举,该枚举包含三个值:Never、OnPropertyChanged、OnValidated,对于Windows应用程序来说,默认值是OnValidated。