Windows Forms 2.0 Programming (Microsoft .NET Development Series)

The fundamental building block of the Windows Forms data binding engine is the Binding object, which binds control properties to object properties:

// RaceCarDriver.cs class RaceCarDriver {...} // SimpleBindingAndItemDataSources.cs partial class SimpleBindingAndItemDataSources : Form { RaceCarDriver raceCarDriver = new RaceCarDriver("M. Schumacher", 500); public SimpleBindingAndItemDataSources() { InitializeComponent(); // Bind the Name and Wins properties to the Name and Wins text boxes Binding nameBinding = new Binding("Text", this.raceCarDriver, "Name", true); this.nameTextBox.DataBindings.Add(nameBinding); Binding winsBinding = new Binding("Text", this.raceCarDriver, "Wins", true); this.winsTextBox.DataBindings.Add(winsBinding); } void addWinButton_Click(object sender, EventArgs e) { // Causes the RaceCarDriver object's PropertyChanged event to fire, // which is used to keep the Wins text box up-to-date ++this.raceCarDriver.Wins; } }

Two interesting things are going on in this code. First, two Binding objects are created, each requiring four parameters: the name of the property on the control to set (nameTextBox.Text and winsTextBox.Text); the object that exposes the property (raceCarDriver); the name of the property to which to bind (raceCarDriver.Name and raceCarDriver.Wins); and whether to enable automatic formatting.[2]

[2] Although you always pass true as the last argument when creating a Binding object, formatting itself is discussed in Chapter 17: Applied Data Binding. Second, each binding object is inserted into the Bindings collection of the appropriate text box control, thereby establishing the binding.

As a simplification, it is possible to use an overload of the Bindings collection's Add method to pass the binding values directly:

// SimpleBindingAndItemDataSources.cs partial class SimpleBindingAndItemDataSources : Form { ... public RaceCarDriverForm() { ... // Bind the Name and Wins properties to the Name and Wins text boxes this.nameTextBox.DataBindings.Add( "Text", this.raceCarDriver, "Name"); this.winsTextBox.DataBindings.Add( "Text", this.raceCarDriver, "Wins"); } ... }

Whichever technique is used, two things happen when a binding is added. First, the data binding engine automatically populates the control's property with the value of the object's property, just as if we'd set nameTextBox.Text to raceCarDriver.Name manually. Any required data conversion occurs automatically (more on that in Chapter 17). Because the initialization is automatic, there is no need to manually set the initial content, and this is why there is no code to do so in the form's constructor.

Second, after initialization, the data binding engine takes care of synchronization between the control and the raceCarDriver object's properties. To ensure that changes are replicated from the object to the control, the binding engine looks for the INotifyPropertyChanged.PropertyChanged event when a Binding object is added to a control. If this event is found, the binding subscribes to it and, when it's fired, copies the new object property value to the bound control property. Consequently, we need not write any code to update the Wins text box when the Wins property is updated via the Add Win button's Click event handler.

Whenever you bind a control's property to an object's property, it is called simple binding. Most control properties (for example, Color, BackgroundImage) can be bound in this way and can be kept synchronized with public properties on any object. A simple binding is two-way only if the object fires an INotifyPropertyChanged.PropertyChanged event (or a PropertyNameChanged event) and if the public property is read-write (implements both get and set accessors). Further, in data binding parlance, a bound object like RaceCarDriver is known as an item data source because its data is located in a single item. However, if the data we want to bind to is located in a collection of items, we need a list data source.

Категории