English context:
Windows Forms Data Binding and Objects
Microsoft worked hard to make data binding useful when creating both Windows Forms and Web Forms interfaces. For the first time since data binding was introduced to Microsoft Visual Basic? Years ago, it is truly practical in a wide range of application scenarios.
One key advancement is that data binding supports not only the DataSet, but also objects, structures and collections of objects, or structures. The basic ability to bind an object or collection to a control on a Windows Form or Web Form requires no extra work on Our Part. It is an automatic feature of data binding.
Web Forms data binding is read-only. In other words, it pulls data from the data source (DataSet, object, or collection) and uses the data to populate controls that are then rendered to the client device. This is straightforward behavior and requires No Extra Work On Our Part As We Create Either Objects or The UI.
Windows Forms data binding is read-write, and therefore more complex. In this case, data is pulled from the data source and displayed in our UI controls, but any changes to the values in the controls are automatically updated back into the data source as Well. Much of this Behavior Is Automatic and Requires No Extra Work ON Our Part, But There Are A Number of Features Available To US IF We Choose To Write Some Extra Code.
We can add to our business and collection classes to better support the features of Windows Forms Data Binding:
· Having The Object or Collection Notify The Ui That Data Has Changed.
· Allowing the datagrid to bind correctly to an es Empty Collection.
.
For simple objects, we can implement events to notify Windows Forms data binding when our property values have changed. By adding these events, we enable the UI to automatically refresh its display any time the data in our object is changed. We also need to understand HOW to Notify The Ui That A Validation Rule Has Been By Newly Entered Data. Improper Implementation of Validation Can Make Data Binding Behave In Undesirable Ways.
In addition, there are a number of optional features we can support in our collections. Collections are typically bound to list controls such as the DataGrid. By properly implementing strongly-typed collection objects, we enable the DataGrid to intelligently interact with our collection and its CHILD Objects. We can also import the ibindinglist interface SO Our collection can intelligently interact with the datagrid in various woman.
Finally, there are some optional features we can support in objects that will be contained within a collection. We'll call these child objects. Child objects can implement the IEditableObject interface so the DataGrid can properly interact with the object during in-place editing. .
In the end, by adding a bit of code to our classes and collections, we can take advantage of one very powerful features of windows forms data binding.
SIMPLE Windows Forms Data Binding
SIMPLY BINDING Properties of An Object To Properties Of Controls ON A Form Is Not Complex. For Instance, Consider The Following Simple Order Class: Public Class Order
Private mid as string = "" "
Private MCUSTOMER AS STRING = ""
Public property ID () AS STRING
Get
Return MID
END GET
Set (byval value as string)
MID = Value
End set
End Property
Public property customer () AS STRING
Get
Return MCUSTOMER
END GET
Set (byval value as string)
MCUSTOMER = VALUE
End set
End Property
END CLASS
The Only Special Code Here is in The Declaration of the Variables:
Private mid as string = "" "
Private MCUSTOMER AS STRING = ""
Notice That The Variables Are Initialized with Empty Values As They Are Declared. This is not type by becault...
The reason we explicitly initialize them like this is because if we do not, the data binding will fail. It turns out that the automatic initialization of the variables does not occur by the time data binding tries to interact with our object, causing a Runtime Exception to Be Thrown When Data Binding Attempts to Retrieve The Value from the uninitialized variables.
However, explicit initialization of the variables occurs before data binding interacts with our object. This means that the variables are properly initialized by the time data binding retrieves their values so we avoid the runtime exception.
IF WE CREATE A FORM SIMILAR TO The One Shown in Figure 1. We can Simply Bind The Properties of the Object to the controls as the form loading.
Figure 1. Simple form layout for the order Object
THE CODE TO BIND An ORDER Object To The Form Would Would Look Like this: Private Morder As Order
Private sub orderrentry_load (Byval Sender as system.object, _
BYVAL E as system.eventargs) Handles mybase.load
Morder = new Order ()
TXTID.DATABINDINGS.ADD ("Text", Morder, "ID")
TXTCUSTOMER.DATABINDINGS.ADD ("Text", Morder, "Customer")
End Sub
The secret lies in the fact that every Windows Forms control has a DataBindings collection. This collection contains a list of bindings between the properties of the control and the properties of our data source (or data sources). An interesting side effect of this scheme is That We can Bind Properties from a Data Source To Several Different Control Properties. Also, We can Bind Different Control Properties To Properties from Multiple Data Source.
Just by using this simple data binding code we can create some pretty complex user interfaces. For example, in the sample code for this article you'll find that we bind the Enabled property of the Save button to an IsValid property on the business object. This Way the button is only available to the user when the object is ready to be saved.
Remember that this data binding is bi-directional. Not only is the data from the object displayed on the form, but any changes the user makes to the data is automatically updated back into our object. This occurs when the user tabs off each field. For instance, if the user changes the value in the txtID control, the new data is updated into the object as the user tabs out of the control. The data is updated into our object through the property Set routine. This is nice because it means Our EXISTINGPERTY CODE IS Automatic Or INVOKED; We don't need to do anything extra to support bi-directional data binding.notification of change Properties
Now that we've seen how simple data binding an object and the controls is, let's discuss how we can enhance our object to support automatic notification of changed properties. The issue here is that if some other code in our application changes the data in an Object, There is no way for the controls in the ui to know...............
What we need is a way for the object to notify the UI any time a property value changes. This is supported through events that we can optionally declare and raise from our object. When we bind a control to a property on our object, data binding Automatical Starts Listening for a Property Changed, WHERE Property Is The Name of the Property of the object.
For instance, our Order class defines an ID property. When the ID property is bound to a control, data binding starts listening for an IDChanged event. If this event is raised by our object, data binding automatically refreshes all controls bound to our object. We can Enhance Our ORDER CLASS BY DECLARING THESE Events:
Public Class Order
Public Event IDChange AS EventHandler
Public Event CustomerChanged As EventHandler
Notice that the events are declared to be of type EventHandler. This is required for data binding to understand the event. If we do not declare the events this way, we'll get a runtime exception when data binding attempts to interact with our object .
The EventHandler Is The Standard Event Model Used THROUGH Windows Forms. It defines The Event with Two Parameters-Sender (The Object Raising The Event) and E (An Eventargs Object).
With these events declared, we need to make sure to raise these events any time the corresponding property value changes One obvious place to do this is in the Set routines For instance, in the ID property we would do this..:
Public property ID () AS STRING
Get
Return MID
END GET
Set (byval value as string)
MID = Value
RaiseEvent Idchanged (Me, New Eventargs ())
End set
End Property
What can be trickier is to remember that any time we change mID anywhere in our class, we also need to raise this event. Most classes include code that modifies internal variables in addition to property Set routines. We must raise the appropriate event any time a Value Is Changed That Will Impact A Property.
For a better example, let's assume that our Order object will have a collection of LineItem objects We'll implement the collection a bit later, but right now let's look at the event and variable declarations of the basic LineItem class:. Public Class LineItem
Public Event ProductChanged As EventHandler
Public Event QUANTITYCHANGED AS EventHandler
Public Event PriceChanged As EventHandler
Public Event AmountChanged As EventHandler
Private MProduct As String
Private MQUANTITY AS INTEGER
Private MPRICE AS DOUBLE
Notice That We Have Four Events, But We Only Have Three Variables. The Amount Property Will Be Calculate by Multiplying Quantity and Price:
Public Readonly Property Amount () AS DOUBLE
Get
Return Mquantity * MPRICE
END GET
End Property
It is a read-only property. However, it can change. In fact, it will change any time that the value of either Price or Quantity changes, and thus we can raise an event to indicate that it has changed. For instance, when The Price Changes:
Public property price () As Double
Get
Return MPRICE
END GET
Set (ByVal Value As Double)
MPRICE = Value
RaiseEvent PriceChanged (ME, New EventArgs ())
RaiseEvent AmountChanged (ME, New Eventargs ())
End set
End Property
Not only do we raise the PriceChanged event because the Price property changed, but we also raise the AmountChanged event because we've indirectly caused the Amount property to change as well. This illustrates how we must be vigilant in our coding to ensure that these events Are raised when appropriate.
That said, it turns out that the AmountChanged event may not be strictly necessary. When we bind controls on a form to properties of an object, data binding listens for propertyChanged events for each property to which our controls are bound. If any one of them is raised, all the controls bound to that object are refreshed.In other words, if our form has controls bound to both the Price and Amount properties, raising the PriceChanged event will cause data binding to refresh not only the control bound to the Price property , but also the one bound to the Amount Property.
The downside to taking advantage of this fact is that the UI becomes tightly bound to the object implementation. If we later decide to only bind to Amount, our UI will not work correctly because no AmountChanged event will be raised. Because of this, it IS BEST to Declare and Raise a PropertyChanged Event for Each Property on Our Object.